/** * @brief * status_sched - Build the status reply for single scheduler * * @param[in] psched - ptr to sched receiving status query * @param[in] preq - ptr to the decoded request * @param[out] pstathd - head of list to append status to * * @return int * @retval 0 : success * @retval !0 : PBSE error code */ static int status_sched(pbs_sched *psched, struct batch_request *preq, pbs_list_head *pstathd) { int rc = 0; struct brp_status *pstat; svrattrl *pal; pstat = (struct brp_status *)malloc(sizeof(struct brp_status)); if (pstat == NULL) return (PBSE_SYSTEM); pstat->brp_objtype = MGR_OBJ_SCHED; (void)strncpy(pstat->brp_objname, psched->sc_name, (PBS_MAXSVRJOBID > PBS_MAXDEST ? PBS_MAXSVRJOBID : PBS_MAXDEST) -1); pstat->brp_objname[(PBS_MAXSVRJOBID > PBS_MAXDEST ? PBS_MAXSVRJOBID : PBS_MAXDEST) - 1] = '\0'; CLEAR_LINK(pstat->brp_stlink); CLEAR_HEAD(pstat->brp_attr); append_link(pstathd, &pstat->brp_stlink, pstat); bad = 0; pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); if (status_attrib(pal, sched_attr_def, psched->sch_attr, SCHED_ATR_LAST, preq->rq_perm, &pstat->brp_attr, &bad)) reply_badattr(PBSE_NOATTR, bad, pal, preq); return (rc); }
void req_stat_svr(struct batch_request *preq) { svrattrl *pal; struct batch_reply *preply; struct brp_status *pstat; /* update count and state counts from sv_numjobs and sv_jobstates */ server.sv_attr[(int)SRV_ATR_TotalJobs].at_val.at_long = server.sv_qs.sv_numjobs; server.sv_attr[(int)SRV_ATR_TotalJobs].at_flags |= ATR_VFLAG_SET|ATR_VFLAG_MODCACHE; update_state_ct(&server.sv_attr[(int)SRV_ATR_JobsByState], server.sv_jobstates, server.sv_jobstbuf); update_license_ct(&server.sv_attr[(int)SRV_ATR_license_count], server.sv_license_ct_buf); /* allocate a reply structure and a status sub-structure */ preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); pstat = (struct brp_status *)malloc(sizeof(struct brp_status)); if (pstat == NULL) { reply_free(preply); req_reject(PBSE_SYSTEM, 0, preq); return; } CLEAR_LINK(pstat->brp_stlink); (void)strcpy(pstat->brp_objname, server_name); pstat->brp_objtype = MGR_OBJ_SERVER; CLEAR_HEAD(pstat->brp_attr); append_link(&preply->brp_un.brp_status, &pstat->brp_stlink, pstat); /* add attributes to the status reply */ bad = 0; pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); if (status_attrib(pal, svr_attr_def, server.sv_attr, SRV_ATR_LAST, preq->rq_perm, &pstat->brp_attr, &bad)) reply_badattr(PBSE_NOATTR, bad, pal, preq); else (void)reply_send(preq); }
void req_stat_sched(struct batch_request *preq) { svrattrl *pal; struct batch_reply *preply; int rc = 0; pbs_sched *psched; /* allocate a reply structure and a status sub-structure */ preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); for (psched = (pbs_sched *) GET_NEXT(svr_allscheds); (psched != NULL); psched = (pbs_sched *) GET_NEXT(psched->sc_link) ) { rc = status_sched(psched, preq, &preply->brp_un.brp_status); if (rc != 0) { break; } } if (!rc) { (void)reply_send(preq); } else { if (rc != PBSE_NOATTR) req_reject(rc, 0, preq); else { pal = (svrattrl *)GET_NEXT(preq->rq_ind. rq_status.rq_attr); reply_badattr(rc, bad, pal, preq); } } }
int req_stat_svr( struct batch_request *preq) /* ptr to the decoded request */ { svrattrl *pal; struct batch_reply *preply; struct brp_status *pstat; int bad = 0; char nc_buf[128]; int numjobs; int netrates[3]; memset(netrates, 0, sizeof(netrates)); /* update count and state counts from sv_numjobs and sv_jobstates */ lock_sv_qs_mutex(server.sv_qs_mutex, __func__); numjobs = server.sv_qs.sv_numjobs; unlock_sv_qs_mutex(server.sv_qs_mutex, __func__); pthread_mutex_lock(server.sv_attr_mutex); server.sv_attr[SRV_ATR_TotalJobs].at_val.at_long = numjobs; server.sv_attr[SRV_ATR_TotalJobs].at_flags |= ATR_VFLAG_SET; pthread_mutex_lock(server.sv_jobstates_mutex); update_state_ct( &server.sv_attr[SRV_ATR_JobsByState], server.sv_jobstates, server.sv_jobstbuf); pthread_mutex_unlock(server.sv_jobstates_mutex); netcounter_get(netrates); snprintf(nc_buf, 127, "%d %d %d", netrates[0], netrates[1], netrates[2]); if (server.sv_attr[SRV_ATR_NetCounter].at_val.at_str != NULL) free(server.sv_attr[SRV_ATR_NetCounter].at_val.at_str); server.sv_attr[SRV_ATR_NetCounter].at_val.at_str = strdup(nc_buf); if (server.sv_attr[SRV_ATR_NetCounter].at_val.at_str != NULL) server.sv_attr[SRV_ATR_NetCounter].at_flags |= ATR_VFLAG_SET; pthread_mutex_unlock(server.sv_attr_mutex); /* allocate a reply structure and a status sub-structure */ preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); pstat = (struct brp_status *)calloc(1, sizeof(struct brp_status)); if (pstat == NULL) { reply_free(preply); req_reject(PBSE_SYSTEM, 0, preq, NULL, NULL); pthread_mutex_unlock(server.sv_attr_mutex); return(PBSE_SYSTEM); } CLEAR_LINK(pstat->brp_stlink); strcpy(pstat->brp_objname, server_name); pstat->brp_objtype = MGR_OBJ_SERVER; CLEAR_HEAD(pstat->brp_attr); append_link(&preply->brp_un.brp_status, &pstat->brp_stlink, pstat); /* add attributes to the status reply */ pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); if (status_attrib( pal, svr_attr_def, server.sv_attr, SRV_ATR_LAST, preq->rq_perm, &pstat->brp_attr, &bad, 1)) /* IsOwner == TRUE */ { reply_badattr(PBSE_NOATTR, bad, pal, preq); } else { reply_send_svr(preq); } return(PBSE_NONE); } /* END req_stat_svr() */
int req_stat_node( struct batch_request *preq) { char *name; int rc = PBSE_NONE; int type = 0; int bad = 0; struct pbsnode *pnode = NULL; struct batch_reply *preply; struct prop props; svrattrl *pal; /* * first, check that the server indeed has a list of nodes * and if it does, validate the name of the requested object-- * either name is that of a specific node, or name[0] is null/@ * meaning request is for all nodes in the server's jurisdiction */ if (LOGLEVEL >= 6) { log_record( PBSEVENT_SCHED, PBS_EVENTCLASS_REQUEST, __func__, "entered"); } if (svr_totnodes <= 0) { rc = PBSE_NONODES; req_reject(rc, 0, preq, NULL, "node list is empty - check 'server_priv/nodes' file"); return rc; } name = preq->rq_ind.rq_status.rq_id; if ((*name == '\0') || (*name == '@')) { type = 1; } else if ((*name == ':') && (*(name + 1) != '\0')) { if (!strcmp(name + 1, "ALL")) { type = 1; /* psuedo-group for all nodes */ } else { type = 2; props.name = name + 1; props.mark = 1; props.next = NULL; } } preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); if (type == 0) { /* get status of the named node */ pnode = find_nodebyname(name); if (pnode == NULL) { rc = PBSE_UNKNODE; req_reject(rc, 0, preq, NULL, "cannot locate specified node"); return(rc); } /* get the status on all of the numa nodes */ if (pnode->nd_is_alps_reporter == TRUE) rc = get_alps_statuses(pnode, preq, &bad, &preply->brp_un.brp_status); else rc = get_numa_statuses(pnode, preq, &bad, &preply->brp_un.brp_status); unlock_node(pnode, __func__, "type == 0", LOGLEVEL); } else { /* get status of all or several nodes */ all_nodes_iterator *iter = NULL; while ((pnode = next_host(&allnodes,&iter,NULL)) != NULL) { if ((type == 2) && (!hasprop(pnode, &props))) { unlock_node(pnode, __func__, "type != 0, next_host", LOGLEVEL); continue; } /* get the status on all of the numa nodes */ if (pnode->nd_is_alps_reporter == TRUE) rc = get_alps_statuses(pnode, preq, &bad, &preply->brp_un.brp_status); else rc = get_numa_statuses(pnode, preq, &bad, &preply->brp_un.brp_status); if (rc != PBSE_NONE) { unlock_node(pnode, __func__, "type != 0, rc != 0, get_numa_statuses", LOGLEVEL); break; } unlock_node(pnode, __func__, "type != 0, rc == 0, get_numa_statuses", LOGLEVEL); } if (iter != NULL) delete iter; } if (rc == PBSE_NONE) { /* SUCCESS */ reply_send_svr(preq); } else { if (rc != PBSE_UNKNODEATR) { req_reject(rc, 0, preq, NULL, NULL); } else { pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); reply_badattr(rc, bad, pal, preq); } } return(rc); } /* END req_stat_node() */
void mgr_node_modify( struct batch_request *preq) /* I */ { int need_todo = 0; int rc; int bad = 0; const char *nodename = NULL; svrattrl *plist; node_check_info nci; struct pbsnode *pnode = NULL; nodename = preq->rq_ind.rq_manager.rq_objname; pnode = find_nodebyname(nodename); if (pnode == NULL) { req_reject(PBSE_UNKNODE, 0, preq, NULL, NULL); return; } plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_manager.rq_attr); save_characteristic(pnode,&nci); rc = mgr_modify_node( &pnode, node_attr_def, ND_ATR_LAST, plist, preq->rq_perm, &bad, ATR_ACTION_ALTER); if (rc != 0) { /* In the specific node case, reply w/ error and return*/ switch (rc) { case PBSE_INTERNAL: case PBSE_SYSTEM: req_reject(rc, bad, preq, NULL, NULL); break; case PBSE_NOATTR: case PBSE_ATTRRO: case PBSE_MUTUALEX: case PBSE_BADNDATVAL: reply_badattr(rc, bad, plist, preq); break; default: req_reject(rc, 0, preq, NULL, NULL); break; } if(pnode != NULL) { unlock_node(pnode, "mgr_node_set", (char *)"error", LOGLEVEL); pnode = NULL; } return; } /* END if (rc != 0) */ else { /* modifications succeeded for this node */ if(pnode != NULL) { chk_characteristic(pnode, &nci, &need_todo); } } if(pnode != NULL) { unlock_node(pnode, "mgr_node_set", (char *)"single_node", LOGLEVEL); pnode = NULL; } if (need_todo & WRITENODE_STATE) { /*some nodes set to "offline"*/ write_node_state(); need_todo &= ~(WRITENODE_STATE); } if (need_todo & WRITENODE_POWER_STATE) { /*some nodes changed power state*/ write_node_power_state(); need_todo &= ~(WRITENODE_POWER_STATE); } if (need_todo & WRITENODE_NOTE) { /*some nodes have new "note"s*/ write_node_note(); need_todo &= ~(WRITENODE_NOTE); } if (need_todo & WRITE_NEW_NODESFILE) { /*create/delete/prop/ntype change*/ if (!update_nodes_file(NULL)) need_todo &= ~(WRITE_NEW_NODESFILE); /*successful on update*/ } recompute_ntype_cnts(); reply_ack(preq); /*request completely successful*/ return; } /* END void mgr_node_set() */
void *req_modifyjob( void *vp) /* I */ { job *pjob; svrattrl *plist; int rc; int checkpoint_req = FALSE; struct batch_request *preq = (struct batch_request *)vp; pjob = chk_job_request(preq->rq_ind.rq_modify.rq_objname, preq); if (pjob == NULL) { return(NULL); } plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); if (plist == NULL) { /* nothing to do */ reply_ack(preq); /* SUCCESS */ unlock_ji_mutex(pjob, __func__, "1", LOGLEVEL); return(NULL); } /* If async modify, reply now; otherwise reply is handled later */ if (preq->rq_type == PBS_BATCH_AsyModifyJob) { reply_ack(preq); preq->rq_noreply = TRUE; /* set for no more replies */ } /* pbs_mom sets the extend string to trigger copying of checkpoint files */ if (preq->rq_extend != NULL) { if (strcmp(preq->rq_extend,CHECKPOINTHOLD) == 0) { checkpoint_req = CHK_HOLD; } else if (strcmp(preq->rq_extend,CHECKPOINTCONT) == 0) { checkpoint_req = CHK_CONT; } } if ((rc = modify_job((void **)&pjob, plist, preq, checkpoint_req, 0)) != 0) { if ((rc == PBSE_MODATRRUN) || (rc == PBSE_UNKRESC)) reply_badattr(rc,1,plist,preq); else if ( rc == PBSE_RELAYED_TO_MOM ) { unlock_ji_mutex(pjob, __func__, "2", LOGLEVEL); return(NULL); } else req_reject(rc,0,preq,NULL,NULL); } else reply_ack(preq); unlock_ji_mutex(pjob, __func__, "3", LOGLEVEL); return(NULL); } /* END req_modifyjob() */
/** * @brief Service the Modify Reservation Request from client such as pbs_ralter. * * This request atomically modifies one or more of a reservation's attributes. * An error is returned to the client if the user does not have permission * to perform the modification, the attribute is read-only, the reservation is * running and the attribute is only modifiable when the reservation is not * running or is empty. * * @param[in] preq - pointer to batch request from client */ void req_modifyReservation(struct batch_request *preq) { char *rid = NULL; svrattrl *psatl = NULL; attribute_def *pdef = NULL; int rc = 0; int bad = 0; char buf[PBS_MAXUSER + PBS_MAXHOSTNAME + 32] = {0}; int sock; int resc_access_perm_save = 0; int send_to_scheduler = 0; int log_len = 0; char *fmt = "%a %b %d %H:%M:%S %Y"; int is_standing = 0; int next_occr_start = 0; extern char *msg_stdg_resv_occr_conflict; resc_resv *presv; if (preq == NULL) return; sock = preq->rq_conn; presv = chk_rescResv_request(preq->rq_ind.rq_modify.rq_objname, preq); /* Note: on failure, chk_rescResv_request invokes req_reject * appropriate reply is sent and batch_request is freed. */ if (presv == NULL) return; rid = preq->rq_ind.rq_modify.rq_objname; if ((presv = find_resv(rid)) == NULL) { /* Not on "all_resvs" list try "new_resvs" list */ presv = (resc_resv *)GET_NEXT(svr_newresvs); while (presv) { if (!strcmp(presv->ri_qs.ri_resvID, rid)) break; presv = (resc_resv *)GET_NEXT(presv->ri_allresvs); } } if (presv == NULL) { req_reject(PBSE_UNKRESVID, 0, preq); return; } is_standing = presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long; if (is_standing) next_occr_start = get_occurrence(presv->ri_wattr[RESV_ATR_resv_rrule].at_val.at_str, presv->ri_wattr[RESV_ATR_start].at_val.at_long, presv->ri_wattr[RESV_ATR_resv_timezone].at_val.at_str, 2); resc_access_perm_save = resc_access_perm; psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); presv->ri_alter_flags = 0; while (psatl) { long temp = 0; char *end = NULL; int index; /* identify the attribute by name */ index = find_attr(resv_attr_def, psatl->al_name, RESV_ATR_LAST); if (index < 0) { /* didn`t recognize the name */ reply_badattr(PBSE_NOATTR, 1, psatl, preq); return; } pdef = &resv_attr_def[index]; /* Does attribute's definition flags indicate that * we have sufficient permission to write the attribute? */ resc_access_perm = resc_access_perm_save; /* reset */ if (psatl->al_flags & ATR_VFLAG_HOOK) { resc_access_perm = ATR_DFLAG_USWR | \ ATR_DFLAG_OPWR | \ ATR_DFLAG_MGWR | \ ATR_DFLAG_SvWR | \ ATR_DFLAG_Creat; } if ((pdef->at_flags & resc_access_perm) == 0) { reply_badattr(PBSE_ATTRRO, 1, psatl, preq); return; } switch (index) { case RESV_ATR_start: if ((presv->ri_wattr[RESV_ATR_state].at_val.at_long != RESV_RUNNING) || !(presv->ri_qp->qu_numjobs)) { temp = strtol(psatl->al_value, &end, 10); if ((temp > time(NULL)) && (temp != presv->ri_wattr[RESV_ATR_start].at_val.at_long)) { if (!is_standing || (temp < next_occr_start)) { send_to_scheduler = RESV_START_TIME_MODIFIED; presv->ri_alter_stime = presv->ri_wattr[RESV_ATR_start].at_val.at_long; presv->ri_alter_flags |= RESV_START_TIME_MODIFIED; } else { snprintf(log_buffer, sizeof(log_buffer), "%s", msg_stdg_resv_occr_conflict); log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); req_reject(PBSE_STDG_RESV_OCCR_CONFLICT, 0, preq); return; } } else { req_reject(PBSE_BADTSPEC, 0, preq); return; } } else { if (presv->ri_qp->qu_numjobs) req_reject(PBSE_RESV_NOT_EMPTY, 0, preq); else req_reject(PBSE_BADTSPEC, 0, preq); return; } break; case RESV_ATR_end: temp = strtol(psatl->al_value, &end, 10); if (temp == presv->ri_wattr[RESV_ATR_end].at_val.at_long) { req_reject(PBSE_BADTSPEC, 0, preq); return; } if (!is_standing || temp < next_occr_start) { send_to_scheduler = RESV_END_TIME_MODIFIED; presv->ri_alter_etime = presv->ri_wattr[RESV_ATR_end].at_val.at_long; presv->ri_alter_flags |= RESV_END_TIME_MODIFIED; } else { snprintf(log_buffer, sizeof(log_buffer), "%s", msg_stdg_resv_occr_conflict); log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); req_reject(PBSE_STDG_RESV_OCCR_CONFLICT, 0, preq); return; } break; default: break; } /* decode attribute */ rc = pdef->at_decode(&presv->ri_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value); if (rc != 0) { reply_badattr(rc, 1, psatl, preq); return; } psatl = (svrattrl *)GET_NEXT(psatl->al_link); } resc_access_perm = resc_access_perm_save; /* restore perm */ if (send_to_scheduler) { presv->ri_alter_state = presv->ri_wattr[RESV_ATR_state].at_val.at_long; resv_setResvState(presv, RESV_BEING_ALTERED, presv->ri_qs.ri_substate); /*"start", "end","duration", and "wall"; derive and check */ if (start_end_dur_wall(presv, RESC_RESV_OBJECT)) { req_reject(PBSE_BADTSPEC, 0, preq); resv_revert_alter_times(presv); return; } presv->ri_wattr[RESV_ATR_resource].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } bad = 0; psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); if (psatl) rc = modify_resv_attr(presv, psatl, preq->rq_perm, &bad); if (send_to_scheduler) set_scheduler_flag(SCH_SCHEDULE_RESV_RECONFIRM, dflt_scheduler); (void)sprintf(log_buffer, "Attempting to modify reservation"); if (presv->ri_alter_flags & RESV_START_TIME_MODIFIED) { strftime(buf, sizeof(buf), fmt, localtime((time_t *) &presv->ri_wattr[RESV_ATR_start].at_val.at_long)); log_len = strlen(log_buffer); snprintf(log_buffer + log_len, sizeof(log_buffer) - log_len," start=%s", buf); } if (presv->ri_alter_flags & RESV_END_TIME_MODIFIED) { strftime(buf, sizeof(buf), fmt, localtime((time_t *) &presv->ri_wattr[RESV_ATR_end].at_val.at_long)); log_len = strlen(log_buffer); snprintf(log_buffer + log_len, sizeof(log_buffer) - log_len," end=%s", buf); } log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); if ((presv->ri_wattr[RESV_ATR_interactive].at_flags & ATR_VFLAG_SET) == 0) { char buf1[PBS_MAXUSER + PBS_MAXHOSTNAME + 32] = {0}; /*Not "interactive" so don't wait on scheduler, reply now*/ sprintf(buf, "%s ALTER REQUESTED", presv->ri_qs.ri_resvID); sprintf(buf1, "requestor=%s@%s", preq->rq_user, preq->rq_host); if ((rc = reply_text(preq, PBSE_NONE, buf))) { /* reply failed, close connection; DON'T purge resv */ close_client(sock); return; } } else { /*Don't reply back until scheduler decides*/ long dt; presv->ri_brp = preq; dt = presv->ri_wattr[RESV_ATR_interactive].at_val.at_long; /*reply with id and state no decision in +dt secs*/ (void)gen_future_reply(presv, dt); (void)snprintf(buf, sizeof(buf), "requestor=%s@%s Interactive=%ld", preq->rq_user, preq->rq_host, dt); } }
void req_modifyjob(struct batch_request *preq) { int add_to_am_list = 0; /* if altered during sched cycle */ int bad = 0; int jt; /* job type */ int newstate; int newsubstate; resource_def *outsideselect = NULL; job *pjob; svrattrl *plist; resource *presc; resource_def *prsd; int rc; int running = 0; int sendmom = 0; char hook_msg[HOOK_MSG_SIZE]; int mod_project = 0; pbs_sched *psched; switch (process_hooks(preq, hook_msg, sizeof(hook_msg), pbs_python_set_interrupt)) { case 0: /* explicit reject */ reply_text(preq, PBSE_HOOKERROR, hook_msg); return; case 1: /* explicit accept */ if (recreate_request(preq) == -1) { /* error */ /* we have to reject the request, as 'preq' */ /* may have been partly modified */ strcpy(hook_msg, "modifyjob event: rejected request"); log_event(PBSEVENT_ERROR, PBS_EVENTCLASS_HOOK, LOG_ERR, "", hook_msg); reply_text(preq, PBSE_HOOKERROR, hook_msg); return; } break; case 2: /* no hook script executed - go ahead and accept event*/ break; default: log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_HOOK, LOG_INFO, "", "modifyjob event: accept req by default"); } if (pseldef == NULL) /* do one time to keep handy */ pseldef = find_resc_def(svr_resc_def, "select", svr_resc_size); pjob = chk_job_request(preq->rq_ind.rq_modify.rq_objname, preq, &jt); if (pjob == NULL) return; if ((jt == IS_ARRAY_Single) || (jt == IS_ARRAY_Range)) { req_reject(PBSE_IVALREQ, 0, preq); return; } psched = find_sched_from_sock(preq->rq_conn); /* allow scheduler to modify job */ if (psched == NULL) { /* provisioning job is not allowed to be modified */ if ((pjob->ji_qs.ji_state == JOB_STATE_RUNNING) && (pjob->ji_qs.ji_substate == JOB_SUBSTATE_PROVISION)) { req_reject(PBSE_BADSTATE, 0, preq); return; } } /* cannot be in exiting or transit, exiting has already be checked */ if (pjob->ji_qs.ji_state == JOB_STATE_TRANSIT) { req_reject(PBSE_BADSTATE, 0, preq); return; } plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); if (plist == NULL) { /* nothing to do */ reply_ack(preq); return; } /* * Special checks must be made: * if during a scheduling cycle and certain attributes are altered, * make a note of the job to prevent it from being run now; * if job is running, only certain attributes/resources can be * altered. */ if (pjob->ji_qs.ji_state == JOB_STATE_RUNNING) { running = 1; } while (plist) { int i; i = find_attr(job_attr_def, plist->al_name, JOB_ATR_LAST); /* * Is the attribute being altered one which could change * scheduling (ATR_DFLAG_SCGALT set) and if a scheduling * cycle is in progress, then set flag to add the job to list * of jobs which cannot be run in this cycle. * If the scheduler itself sends a modify job request, * no need to delay the job until next cycle. */ if ((psched == NULL) && (scheduler_jobs_stat) && (job_attr_def[i].at_flags & ATR_DFLAG_SCGALT)) add_to_am_list = 1; /* Is the attribute modifiable in RUN state ? */ if (i < 0) { reply_badattr(PBSE_NOATTR, 1, plist, preq); return; } if ((running == 1) && ((job_attr_def[i].at_flags & ATR_DFLAG_ALTRUN) == 0)) { reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return; } if (i == (int)JOB_ATR_resource) { prsd = find_resc_def(svr_resc_def, plist->al_resc, svr_resc_size); if (prsd == 0) { reply_badattr(PBSE_UNKRESC, 1, plist, preq); return; } /* is the specified resource modifiable while */ /* the job is running */ if (running) { if ((prsd->rs_flags & ATR_DFLAG_ALTRUN) == 0) { reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return; } sendmom = 1; } /* should the resource be only in a select spec */ if (prsd->rs_flags & ATR_DFLAG_CVTSLT && !outsideselect && plist->al_atopl.value && plist->al_atopl.value[0]) { /* if "-lresource" is set and has non-NULL value, ** remember as potential bad resource ** if this appears along "select". */ outsideselect = prsd; } } if (strcmp(plist->al_name, ATTR_project) == 0) { mod_project = 1; } else if ((strcmp(plist->al_name, ATTR_runcount) == 0) && ((plist->al_flags & ATR_VFLAG_HOOK) == 0) && (plist->al_value != NULL) && (plist->al_value[0] != '\0') && ((preq->rq_perm & (ATR_DFLAG_MGWR | ATR_DFLAG_OPWR)) == 0) && (atol(plist->al_value) < \ pjob->ji_wattr[(int)JOB_ATR_runcount].at_val.at_long)) { sprintf(log_buffer, "regular user %s@%s cannot decrease '%s' attribute value from %ld to %ld", preq->rq_user, preq->rq_host, ATTR_runcount, pjob->ji_wattr[(int)JOB_ATR_runcount].at_val.at_long, atol(plist->al_value)); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_ERR, pjob->ji_qs.ji_jobid, log_buffer); req_reject(PBSE_PERM, 0, preq); return; } plist = (svrattrl *)GET_NEXT(plist->al_link); } if (outsideselect) { presc = find_resc_entry(&pjob->ji_wattr[(int)JOB_ATR_resource], pseldef); if (presc && ((presc->rs_value.at_flags & ATR_VFLAG_DEFLT) == 0)) { /* select is not a default, so reject qalter */ resc_in_err = strdup(outsideselect->rs_name); req_reject(PBSE_INVALJOBRESC, 0, preq); return; } } /* modify the jobs attributes */ bad = 0; plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); rc = modify_job_attr(pjob, plist, preq->rq_perm, &bad); if (rc) { if (pjob->ji_clterrmsg) reply_text(preq, rc, pjob->ji_clterrmsg); else reply_badattr(rc, bad, plist, preq); return; } /* If certain attributes modified and if in scheduling cycle */ /* then add to list of jobs which cannot be run in this cycle */ if (add_to_am_list) am_jobs_add(pjob); /* see req_runjob() */ /* check if project attribute was requested to be modified to */ /* be the default project value */ if (mod_project && (pjob->ji_wattr[(int)JOB_ATR_project].at_flags & \ ATR_VFLAG_SET)) { if (strcmp(pjob->ji_wattr[(int)JOB_ATR_project].at_val.at_str, PBS_DEFAULT_PROJECT) == 0) { sprintf(log_buffer, msg_defproject, ATTR_project, PBS_DEFAULT_PROJECT); #ifdef NAS /* localmod 107 */ log_event(PBSEVENT_DEBUG4, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); #else log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); #endif /* localmod 107 */ } } if (pjob->ji_wattr[(int)JOB_ATR_resource].at_flags & ATR_VFLAG_MODIFY) { presc = find_resc_entry(&pjob->ji_wattr[(int)JOB_ATR_resource], pseldef); if (presc && (presc->rs_value.at_flags & ATR_VFLAG_DEFLT)) { /* changing Resource_List and select is a default */ /* clear "select" so it is rebuilt inset_resc_deflt */ pseldef->rs_free(&presc->rs_value); } } /* Reset any defaults resource limit which might have been unset */ if ((rc = set_resc_deflt((void *)pjob, JOB_OBJECT, NULL)) != 0) { req_reject(rc, 0, preq); return; } /* if job is not running, may need to change its state */ if (pjob->ji_qs.ji_state != JOB_STATE_RUNNING) { svr_evaljobstate(pjob, &newstate, &newsubstate, 0); (void)svr_setjobstate(pjob, newstate, newsubstate); } else { (void)job_save(pjob, SAVEJOB_FULL); } (void)sprintf(log_buffer, msg_manager, msg_jobmod, preq->rq_user, preq->rq_host); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); /* if a resource limit changed for a running job, send to MOM */ if (sendmom) { rc = relay_to_mom(pjob, preq, post_modify_req); if (rc) req_reject(rc, 0, preq); /* unable to get to MOM */ return; } reply_ack(preq); }
int modify_job( void **j, /* O */ svrattrl *plist, /* I */ batch_request *preq, /* I */ int checkpoint_req, /* I */ int flag) /* I */ { int bad = 0; int i; int newstate; int newsubstate; resource_def *prsd; int rc; int sendmom = 0; int copy_checkpoint_files = FALSE; char jobid[PBS_MAXSVRJOBID + 1]; char log_buf[LOCAL_LOG_BUF_SIZE]; svrattrl *plist_hold; job **pjob_ptr = (job **)j; job *pjob = *pjob_ptr; if (pjob == NULL) { sprintf(log_buf, "job structure is NULL"); log_err(PBSE_IVALREQ, __func__, log_buf); req_reject(PBSE_IVALREQ, 0, preq, NULL, NULL); return(PBSE_IVALREQ); } plist_hold = plist; /* cannot be in exiting or transit, exiting has already been checked */ if (pjob->ji_qs.ji_state == JOB_STATE_TRANSIT) { /* FAILURE */ snprintf(log_buf,sizeof(log_buf), "Cannot modify job '%s' in transit\n", pjob->ji_qs.ji_jobid); log_err(PBSE_BADSTATE, __func__, log_buf); req_reject(PBSE_BADSTATE, 0, preq, NULL, NULL); return(PBSE_BADSTATE); } if (((checkpoint_req == CHK_HOLD) || (checkpoint_req == CHK_CONT)) && (pjob->ji_qs.ji_substate == JOB_SUBSTATE_RUNNING)) { /* May need to request copy of the checkpoint file from mom */ copy_checkpoint_files = TRUE; if (checkpoint_req == CHK_HOLD) { sprintf(log_buf,"setting jobsubstate for %s to RERUN\n", pjob->ji_qs.ji_jobid); pjob->ji_qs.ji_substate = JOB_SUBSTATE_RERUN; job_save(pjob, SAVEJOB_QUICK, 0); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, pjob->ji_qs.ji_jobid, log_buf); /* remove checkpoint restart file if there is one */ if (pjob->ji_wattr[JOB_ATR_restart_name].at_flags & ATR_VFLAG_SET) { cleanup_restart_file(pjob); } } } /* if job is running, special checks must be made */ /* NOTE: must determine if job exists down at MOM - this will occur if job is running, job is held, or job was held and just barely released (ie qhold/qrls) */ if (pjob->ji_qs.ji_state == JOB_STATE_RUNNING) { while (plist != NULL) { /* is the pbs_attribute modifiable in RUN state ? */ i = find_attr(job_attr_def, plist->al_name, JOB_ATR_LAST); if ((i < 0) || ((job_attr_def[i].at_flags & ATR_DFLAG_ALTRUN) == 0)) { /* FAILURE */ snprintf(log_buf,sizeof(log_buf), "Cannot modify attribute '%s' while running\n", plist->al_name); log_err(PBSE_MODATRRUN, __func__, log_buf); reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return(PBSE_MODATRRUN); } /* NOTE: only explicitly specified job attributes are routed down to MOM */ if (i == JOB_ATR_resource) { /* is the specified resource modifiable while */ /* the job is running */ prsd = find_resc_def(svr_resc_def, plist->al_resc, svr_resc_size); if (prsd == NULL) { /* FAILURE */ snprintf(log_buf,sizeof(log_buf), "Unknown attribute '%s'\n", plist->al_name); log_err(PBSE_UNKRESC, __func__, log_buf); reply_badattr(PBSE_UNKRESC, 1, plist, preq); return(PBSE_UNKRESC); } if ((prsd->rs_flags & ATR_DFLAG_ALTRUN) == 0) { /* FAILURE */ snprintf(log_buf,sizeof(log_buf), "Cannot modify attribute '%s' while running\n", plist->al_name); log_err(PBSE_MODATRRUN, __func__, log_buf); reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return(PBSE_MODATRRUN); } sendmom = 1; } plist = (svrattrl *)GET_NEXT(plist->al_link); } } /* END if (pjob->ji_qs.ji_state == JOB_STATE_RUNNING) */ /* modify the job's attributes */ bad = 0; /* if the job was running we need to reset plist */ plist = plist_hold; while (plist != NULL) { rc = modify_job_attr(pjob, plist, preq->rq_perm, &bad); if (rc) { /* FAILURE */ snprintf(log_buf,sizeof(log_buf), "Cannot set attributes for job '%s'\n", pjob->ji_qs.ji_jobid); log_err(rc, __func__, log_buf); if (rc == PBSE_JOBNOTFOUND) *j = NULL; req_reject(rc, 0, preq, NULL, NULL); return(rc); } plist = (svrattrl *)GET_NEXT(plist->al_link); } /* Reset any defaults resource limit which might have been unset */ set_resc_deflt(pjob, NULL, FALSE); /* if job is not running, may need to change its state */ if (pjob->ji_qs.ji_state != JOB_STATE_RUNNING) { svr_evaljobstate(pjob, &newstate, &newsubstate, 0); svr_setjobstate(pjob, newstate, newsubstate, FALSE); } else { job_save(pjob, SAVEJOB_FULL, 0); } sprintf(log_buf, msg_manager, msg_jobmod, preq->rq_user, preq->rq_host); log_event(PBSEVENT_JOB,PBS_EVENTCLASS_JOB,pjob->ji_qs.ji_jobid,log_buf); /* if a resource limit changed for a running job, send to MOM */ if (sendmom) { /* if the NO_MOM_RELAY flag is set the calling function will call relay_to_mom so we do not need to do it here */ if (flag != NO_MOM_RELAY) { /* The last number is unused unless this is an array */ if ((rc = relay_to_mom(&pjob, preq, NULL))) { req_reject(rc, 0, preq, NULL, NULL); if (pjob != NULL) { snprintf(log_buf,sizeof(log_buf), "Unable to relay information to mom for job '%s'\n", pjob->ji_qs.ji_jobid); log_err(rc, __func__, log_buf); } return(rc); /* unable to get to MOM */ } else { jobid[0] = '\0'; if (pjob != NULL) { strcpy(jobid, pjob->ji_qs.ji_jobid); unlock_ji_mutex(pjob, __func__, "2", LOGLEVEL); } post_modify_req(preq); if (jobid[0] != '\0') pjob = svr_find_job(jobid, TRUE); if (pjob == NULL) *pjob_ptr = NULL; } } else reply_ack(preq); return(PBSE_RELAYED_TO_MOM); } else reply_ack(preq); if (copy_checkpoint_files) { struct batch_request *momreq = 0; momreq = cpy_checkpoint(momreq, pjob, JOB_ATR_checkpoint_name, CKPT_DIR_OUT); if (momreq != NULL) { /* have files to copy */ momreq->rq_extra = strdup(pjob->ji_qs.ji_jobid); /* The momreq is freed in relay_to_mom (failure) * or in issue_Drequest (success) */ rc = relay_to_mom(&pjob, momreq, NULL); if (rc != PBSE_NONE) { free_br(momreq); req_reject(rc, 0, preq, NULL, NULL); if (pjob != NULL) { snprintf(log_buf,sizeof(log_buf), "Unable to relay information to mom for job '%s'\n", pjob->ji_qs.ji_jobid); log_err(rc, __func__, log_buf); } return(PBSE_NONE); /* come back when mom replies */ } else if (checkpoint_req == CHK_HOLD) chkpt_xfr_hold(momreq, pjob); else chkpt_xfr_done(momreq); } else { log_err(-1, __func__, "Failed to get batch request"); } } return(PBSE_NONE); } /* END modify_job() */
void req_quejob( struct batch_request *preq) /* ptr to the decoded request */ { char *id = "req_quejob"; char basename[PBS_JOBBASE + 1]; int created_here = 0; int index; char *jid; attribute_def *pdef; job *pj; svrattrl *psatl; int rc; int sock = preq->rq_conn; int IsCheckpoint = 0; /* set basic (user) level access permission */ resc_access_perm = ATR_DFLAG_USWR | ATR_DFLAG_Creat; if (PBSNodeCheckProlog) { check_state(1); mom_server_all_update_stat(); if (internal_state & INUSE_DOWN) { req_reject(PBSE_MOMREJECT,0,preq,NULL,NULL); return; } } if (preq->rq_fromsvr) { /* from another server - accept the extra attributes */ resc_access_perm |= ATR_DFLAG_MGWR | ATR_DFLAG_SvWR | ATR_DFLAG_MOM; jid = preq->rq_ind.rq_queuejob.rq_jid; } else { /* request must be from server */ log_err(errno, id, "request not from server"); req_reject(PBSE_IVALREQ, 0, preq, NULL, "request not received from server"); return; } /* does job already exist, check both old and new jobs */ if ((pj = find_job(jid)) == NULL) { pj = (job *)GET_NEXT(svr_newjobs); while (pj != NULL) { if (!strcmp(pj->ji_qs.ji_jobid, jid)) break; pj = (job *)GET_NEXT(pj->ji_alljobs); } } /* * New job ... * * for MOM - rather than make up a hashname, we use the name sent * to us by the server as an attribute. */ psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_queuejob.rq_attr); while (psatl != NULL) { if (!strcmp(psatl->al_name,ATTR_hashname)) { strcpy(basename,psatl->al_value); break; } psatl = (svrattrl *)GET_NEXT(psatl->al_link); } if (pj != NULL) { /* newly queued job already exists */ if (pj->ji_qs.ji_substate == JOB_SUBSTATE_RUNNING) { /* FAILURE - job exists and is running */ log_err(errno,id,"cannot queue new job, job exists and is running"); req_reject(PBSE_JOBEXIST,0,preq,NULL,"job is running"); return; } /* if checkpointed, then keep old and skip rest of process */ if (pj->ji_qs.ji_svrflags & JOB_SVFLG_CHECKPOINT_FILE) { IsCheckpoint = 1; } /* END if (pj->ji_qs.ji_svrflags & JOB_SVFLG_CHECKPOINT_FILE) */ else { /* unlink job from svr_alljobs since it will be placed on newjobs */ delete_link(&pj->ji_alljobs); } } /* END if (pj != NULL) */ else { /* if not already here, allocate job struct */ if ((pj = job_alloc()) == NULL) { /* FAILURE */ req_reject(PBSE_SYSTEM, 0, preq, NULL, "cannot allocate new job structure"); return; } } /* END else (pj != NULL) */ if (IsCheckpoint == 0) { strcpy(pj->ji_qs.ji_jobid,jid); strcpy(pj->ji_qs.ji_fileprefix,basename); pj->ji_modified = 1; pj->ji_qs.ji_svrflags = created_here; pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; } /* decode attributes from request into job structure */ psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_queuejob.rq_attr); while (psatl != NULL) { if (IsCheckpoint == 1) { if (strcmp(psatl->al_name,ATTR_checkpoint_name) && strcmp(psatl->al_name,ATTR_v)) { psatl = (svrattrl *)GET_NEXT(psatl->al_link); continue; } } /* identify the attribute by name */ index = find_attr(job_attr_def,psatl->al_name,JOB_ATR_LAST); if (index < 0) { /* FAILURE */ /* didn`t recognize the name */ job_purge(pj); /* CRI - 12/20/2004 */ reply_badattr(PBSE_NOATTR,1,psatl,preq); return; } pdef = &job_attr_def[index]; /* Is attribute not writeable by manager or by a server? */ if ((pdef->at_flags & resc_access_perm) == 0) { /* FAILURE */ job_purge(pj); reply_badattr(PBSE_ATTRRO,1,psatl,preq); return; } /* decode attribute */ if (!strcmp(psatl->al_name,ATTR_v)) { rc = decode_arst_merge( &pj->ji_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value); } else { rc = pdef->at_decode( &pj->ji_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value); } if (rc != 0) { /* FAILURE */ /* all errors are fatal for MOM */ job_purge(pj); reply_badattr(rc,1,psatl,preq); return; } if (psatl->al_op == DFLT) { if (psatl->al_resc) { resource *presc; resource_def *prdef; prdef = find_resc_def(svr_resc_def,psatl->al_resc,svr_resc_size); if (prdef == NULL) { job_purge(pj); reply_badattr(rc,1,psatl, preq); return; } presc = find_resc_entry(&pj->ji_wattr[index],prdef); if (presc != NULL) presc->rs_value.at_flags |= ATR_VFLAG_DEFLT; } else { pj->ji_wattr[index].at_flags |= ATR_VFLAG_DEFLT; } } /* END if (psatl->al_op == DFLT) */ psatl = (svrattrl *)GET_NEXT(psatl->al_link); } /* END while (psatl != NULL) */ if (IsCheckpoint == 1) { pj->ji_qs.ji_substate = JOB_SUBSTATE_TRANSIN; if (reply_jobid(preq,pj->ji_qs.ji_jobid,BATCH_REPLY_CHOICE_Queue) == 0) { delete_link(&pj->ji_alljobs); append_link(&svr_newjobs,&pj->ji_alljobs,pj); pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; pj->ji_qs.ji_un.ji_newt.ji_fromsock = sock; pj->ji_qs.ji_un.ji_newt.ji_fromaddr = get_connectaddr(sock); pj->ji_qs.ji_un.ji_newt.ji_scriptsz = 0; /* Per Eric R., req_mvjobfile was giving error in open_std_file, showed up as fishy error message */ if (pj->ji_grpcache != NULL) { free(pj->ji_grpcache); pj->ji_grpcache = NULL; } } else { close_conn(sock); } /* SUCCESS */ return; } /* set remaining job structure elements */ pj->ji_qs.ji_state = JOB_STATE_TRANSIT; pj->ji_qs.ji_substate = JOB_SUBSTATE_TRANSIN; pj->ji_wattr[(int)JOB_ATR_mtime].at_val.at_long = (long)time_now; pj->ji_wattr[(int)JOB_ATR_mtime].at_flags |= ATR_VFLAG_SET; pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; pj->ji_qs.ji_un.ji_newt.ji_fromsock = sock; pj->ji_qs.ji_un.ji_newt.ji_fromaddr = get_connectaddr(sock); pj->ji_qs.ji_un.ji_newt.ji_scriptsz = 0; /* acknowledge the request with the job id */ if (reply_jobid(preq, pj->ji_qs.ji_jobid, BATCH_REPLY_CHOICE_Queue) != 0) { /* reply failed, purge the job and close the connection */ close_conn(sock); job_purge(pj); return; } /* link job into server's new jobs list request */ append_link(&svr_newjobs, &pj->ji_alljobs, pj); return; } /* END req_quejob() */
void mom_req_quejob( batch_request *preq) /* ptr to the decoded request */ { char basename[PBS_JOBBASE + 1]; int created_here = 0; int index; char *jid; attribute_def *pdef; job *pj; svrattrl *psatl; int rc; int sock = preq->rq_conn; int IsCheckpoint = 0; /* set basic (user) level access permission */ int resc_access_perm = ATR_DFLAG_USWR | ATR_DFLAG_Creat; memset(basename, 0, sizeof(basename)); if (PBSNodeCheckProlog) { check_state(1); if (internal_state & INUSE_DOWN) { req_reject(PBSE_BADMOMSTATE, 0, preq, NULL, NULL); return; } } if (reject_job_submit == TRUE) { req_reject(-1, 0, preq, NULL, "This mom is configured not to run jobs"); return; } if (preq->rq_fromsvr) { /* from another server - accept the extra attributes */ resc_access_perm |= ATR_DFLAG_MGWR | ATR_DFLAG_SvWR | ATR_DFLAG_MOM; jid = preq->rq_ind.rq_queuejob.rq_jid; } else { /* request must be from server */ log_err(errno, __func__, (char *)"request not from server"); req_reject(PBSE_IVALREQ, 0, preq, NULL, "request not received from server"); return; } /* does job already exist, check both old and new jobs */ if ((pj = mom_find_job(jid)) == NULL) { pj = (job *)GET_NEXT(svr_newjobs); while (pj != NULL) { if (!strcmp(pj->ji_qs.ji_jobid, jid)) break; pj = (job *)GET_NEXT(pj->ji_alljobs); } } /* * New job ... * * for MOM - rather than make up a hashname, we use the name sent * to us by the server as an pbs_attribute. */ psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_queuejob.rq_attr); while (psatl != NULL) { if (!strcmp(psatl->al_name,ATTR_hashname)) { snprintf(basename, sizeof(basename), "%s", psatl->al_value); break; } psatl = (svrattrl *)GET_NEXT(psatl->al_link); } if (basename[0] == '\0') snprintf(basename, sizeof(basename), "%s", jid); if (pj != NULL) { /* newly queued job already exists */ if (pj->ji_qs.ji_substate == JOB_SUBSTATE_RUNNING) { /* FAILURE - job exists and is running */ log_err(errno, __func__, (char *)"cannot queue new job, job exists and is running"); req_reject(PBSE_JOBEXIST, 0, preq, NULL, "job is running"); return; } /* if checkpointed, then keep old and skip rest of process */ if (pj->ji_qs.ji_svrflags & JOB_SVFLG_CHECKPOINT_FILE) { IsCheckpoint = 1; } /* END if (pj->ji_qs.ji_svrflags & JOB_SVFLG_CHECKPOINT_FILE) */ else { /* reject the job. It is already working here. */ sprintf(log_buffer, "Job already exists. State: %d substate: %d", pj->ji_qs.ji_state, pj->ji_qs.ji_substate); log_err(-1, __func__, log_buffer); sprintf(log_buffer, "Job %s already on mom", pj->ji_qs.ji_jobid); req_reject(PBSE_JOBEXIST, 0, preq, NULL, log_buffer); return; } } /* END if (pj != NULL) */ else { /* if not already here, allocate job struct */ if ((pj = job_alloc()) == NULL) { /* FAILURE */ req_reject(PBSE_MEM_MALLOC, 0, preq, NULL, "cannot allocate new job structure"); return; } } /* END else (pj != NULL) */ if (IsCheckpoint == 0) { strcpy(pj->ji_qs.ji_jobid,jid); strcpy(pj->ji_qs.ji_fileprefix,basename); pj->ji_modified = 1; pj->ji_qs.ji_svrflags = created_here; pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; /* changing the union type overwrites the euid for the job, and if * ji_grpcache is set this potentially allows jobs to run as root. Unsetting * ji_grpcache fixes this problem --dbeer */ if (pj->ji_grpcache != NULL) { free(pj->ji_grpcache); pj->ji_grpcache = NULL; } } /* decode attributes from request into job structure */ psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_queuejob.rq_attr); while (psatl != NULL) { if (IsCheckpoint == 1) { if (strcmp(psatl->al_name,ATTR_checkpoint_name) && strcmp(psatl->al_name,ATTR_v)) { psatl = (svrattrl *)GET_NEXT(psatl->al_link); continue; } } /* identify the pbs_attribute by name */ index = find_attr(job_attr_def,psatl->al_name,JOB_ATR_LAST); if (index < 0) { /* FAILURE */ /* didn`t recognize the name */ mom_job_purge(pj); /* CRI - 12/20/2004 */ reply_badattr(PBSE_NOATTR, 1, psatl, preq); return; } pdef = &job_attr_def[index]; /* Is pbs_attribute not writeable by manager or by a server? */ if ((pdef->at_flags & resc_access_perm) == 0) { /* FAILURE */ mom_job_purge(pj); reply_badattr(PBSE_ATTRRO, 1, psatl, preq); return; } /* decode pbs_attribute */ if (!strcmp(psatl->al_name,ATTR_v)) { rc = decode_arst_merge( &pj->ji_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value); } else { rc = pdef->at_decode( &pj->ji_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value, resc_access_perm); } if (rc != 0) { /* FAILURE */ /* all errors are fatal for MOM */ mom_job_purge(pj); reply_badattr(rc, 1, psatl, preq); return; } if (psatl->al_op == DFLT) { if (psatl->al_resc) { resource *presc; resource_def *prdef; prdef = find_resc_def(svr_resc_def,psatl->al_resc,svr_resc_size); if (prdef == NULL) { mom_job_purge(pj); reply_badattr(rc, 1, psatl, preq); return; } presc = find_resc_entry(&pj->ji_wattr[index],prdef); if (presc != NULL) presc->rs_value.at_flags |= ATR_VFLAG_DEFLT; } else { pj->ji_wattr[index].at_flags |= ATR_VFLAG_DEFLT; } } /* END if (psatl->al_op == DFLT) */ psatl = (svrattrl *)GET_NEXT(psatl->al_link); } /* END while (psatl != NULL) */ if (IsCheckpoint == 1) { pj->ji_qs.ji_substate = JOB_SUBSTATE_TRANSIN; if (reply_jobid(preq,pj->ji_qs.ji_jobid,BATCH_REPLY_CHOICE_Queue) == 0) { remove_from_job_list(pj); append_link(&svr_newjobs,&pj->ji_alljobs,pj); if (pj->ji_grpcache != NULL) { free(pj->ji_grpcache); pj->ji_grpcache = NULL; } pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; pj->ji_qs.ji_un.ji_newt.ji_fromsock = sock; pj->ji_qs.ji_un.ji_newt.ji_fromaddr = get_connectaddr(sock,FALSE); pj->ji_qs.ji_un.ji_newt.ji_scriptsz = 0; /* Per Eric R., req_mvjobfile was giving error in open_std_file, showed up as fishy error message */ if (pj->ji_grpcache != NULL) { free(pj->ji_grpcache); pj->ji_grpcache = NULL; } } else { close_conn(sock, FALSE); } /* SUCCESS */ return; } /* set remaining job structure elements */ pj->ji_qs.ji_state = JOB_STATE_TRANSIT; pj->ji_qs.ji_substate = JOB_SUBSTATE_TRANSIN; pj->ji_wattr[JOB_ATR_mtime].at_val.at_long = (long)time_now; pj->ji_wattr[JOB_ATR_mtime].at_flags |= ATR_VFLAG_SET; if (pj->ji_grpcache != NULL) { free(pj->ji_grpcache); pj->ji_grpcache = NULL; } pj->ji_qs.ji_un_type = JOB_UNION_TYPE_NEW; pj->ji_qs.ji_un.ji_newt.ji_fromsock = sock; pj->ji_qs.ji_un.ji_newt.ji_fromaddr = get_connectaddr(sock,FALSE); pj->ji_qs.ji_un.ji_newt.ji_scriptsz = 0; /* acknowledge the request with the job id */ if (reply_jobid(preq, pj->ji_qs.ji_jobid, BATCH_REPLY_CHOICE_Queue) != 0) { /* reply failed, purge the job and close the connection */ // call mom_job_purge first so that double-frees don't happen // when the on_close function is called mom_job_purge(pj); close_conn(sock, FALSE); return; } /* link job into server's new jobs list request */ append_link(&svr_newjobs, &pj->ji_alljobs, pj); return; } /* END mom_req_quejob() */
void req_stat_node(struct batch_request *preq) { char *name; struct batch_reply *preply; svrattrl *pal; struct pbsnode *pnode = NULL; int rc = 0; int type = 0; int i; /* * first, check that the server indeed has a list of nodes * and if it does, validate the name of the requested object-- * either name is that of a spedific node, or name[0] is null/@ * meaning request is for all nodes in the server's jurisdiction */ if (pbsndlist == 0 || svr_totnodes <= 0) { req_reject(PBSE_NONODES, 0, preq); return; } resc_access_perm = preq->rq_perm; name = preq->rq_ind.rq_status.rq_id; if ((*name == '\0') || (*name =='@')) type = 1; else { pnode = find_nodebyname(name); if (pnode == NULL) { req_reject(PBSE_UNKNODE, 0, preq); return; } } preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); if (type == 0) { /* get status of the named node */ rc = status_node(pnode, preq, &preply->brp_un.brp_status); } else { /* get status of all nodes */ for (i = 0; i < svr_totnodes; i++) { pnode = pbsndlist[i]; rc = status_node(pnode, preq, &preply->brp_un.brp_status); if (rc) break; } } if (!rc) { (void)reply_send(preq); } else { if (rc != PBSE_UNKNODEATR) req_reject(rc, 0, preq); else { pal = (svrattrl *)GET_NEXT(preq->rq_ind. rq_status.rq_attr); reply_badattr(rc, bad, pal, preq); } } }
void req_stat_svr( struct batch_request *preq) /* ptr to the decoded request */ { svrattrl *pal; struct batch_reply *preply; struct brp_status *pstat; int *nc; static char nc_buf[128]; /* update count and state counts from sv_numjobs and sv_jobstates */ server.sv_attr[(int)SRV_ATR_TotalJobs].at_val.at_long = server.sv_qs.sv_numjobs; server.sv_attr[(int)SRV_ATR_TotalJobs].at_flags |= ATR_VFLAG_SET; update_state_ct( &server.sv_attr[(int)SRV_ATR_JobsByState], server.sv_jobstates, server.sv_jobstbuf); nc = netcounter_get(); sprintf(nc_buf, "%d %d %d", *nc, *(nc + 1), *(nc + 2)); server.sv_attr[(int)SRV_ATR_NetCounter].at_val.at_str = nc_buf; server.sv_attr[(int)SRV_ATR_NetCounter].at_flags |= ATR_VFLAG_SET; /* allocate a reply structure and a status sub-structure */ preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); pstat = (struct brp_status *)malloc(sizeof(struct brp_status)); if (pstat == NULL) { reply_free(preply); req_reject(PBSE_SYSTEM, 0, preq, NULL, NULL); return; } CLEAR_LINK(pstat->brp_stlink); strcpy(pstat->brp_objname, server_name); pstat->brp_objtype = MGR_OBJ_SERVER; CLEAR_HEAD(pstat->brp_attr); append_link(&preply->brp_un.brp_status, &pstat->brp_stlink, pstat); /* add attributes to the status reply */ bad = 0; pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); if (status_attrib( pal, svr_attr_def, server.sv_attr, SRV_ATR_LAST, preq->rq_perm, &pstat->brp_attr, &bad, 1)) /* IsOwner == TRUE */ { reply_badattr(PBSE_NOATTR, bad, pal, preq); } else { reply_send(preq); } return; } /* END req_stat_svr() */
void req_stat_node( struct batch_request *preq) /* ptr to the decoded request */ { char *name; struct pbsnode *pnode = NULL; struct batch_reply *preply; svrattrl *pal; int rc = 0; int type = 0; int i; struct prop props; char *id = "req_stat_node"; /* * first, check that the server indeed has a list of nodes * and if it does, validate the name of the requested object-- * either name is that of a specific node, or name[0] is null/@ * meaning request is for all nodes in the server's jurisdiction */ if (LOGLEVEL >= 6) { log_record( PBSEVENT_SCHED, PBS_EVENTCLASS_REQUEST, id, "entered"); } if ((pbsndmast == NULL) || (svr_totnodes <= 0)) { req_reject(PBSE_NONODES, 0, preq, NULL, "node list is empty - check 'server_priv/nodes' file"); return; } name = preq->rq_ind.rq_status.rq_id; if ((*name == '\0') || (*name == '@')) { type = 1; } else if ((*name == ':') && (*(name + 1) != '\0')) { if (!strcmp(name + 1, "ALL")) { type = 1; /* psuedo-group for all nodes */ } else { type = 2; props.name = name + 1; props.mark = 1; props.next = NULL; } } else { pnode = find_nodebyname(name); if (pnode == NULL) { req_reject(PBSE_UNKNODE, 0, preq, NULL, "cannot locate specified node"); return; } } preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); if (type == 0) { /* get status of the named node */ rc = status_node(pnode, preq, &preply->brp_un.brp_status); } else { /* get status of all or several nodes */ for (i = 0;i < svr_totnodes;i++) { pnode = pbsndmast[i]; if ((type == 2) && !hasprop(pnode, &props)) continue; if ((rc = status_node(pnode, preq, &preply->brp_un.brp_status)) != 0) break; } } if (!rc) { /* SUCCESS */ reply_send(preq); } else { if (rc != PBSE_UNKNODEATR) { req_reject(rc, 0, preq, NULL, NULL); } else { pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); reply_badattr(rc, bad, pal, preq); } } return; } /* END req_stat_node() */