static void handle_project_suspend(GUI_RPC_CONN& grc) { PROJECT* p = get_project_parse(grc); if (!p) return; gstate.set_client_state_dirty("Project modified by user"); msg_printf(p, MSG_INFO, "project suspended by user"); p->suspend(); grc.mfout.printf("<success/>\n"); }
static void handle_project_op(char* buf, MIOFILE& fout, const char* op) { PROJECT* p = get_project(buf, fout); if (!p) { fout.printf("<error>no such project</error>\n"); return; } gstate.set_client_state_dirty("Project modified by user"); if (!strcmp(op, "reset")) { gstate.request_schedule_cpus("project reset by user"); gstate.request_work_fetch("project reset by user"); gstate.reset_project(p, false); } else if (!strcmp(op, "suspend")) { msg_printf(p, MSG_INFO, "suspended by user"); p->suspend(); } else if (!strcmp(op, "resume")) { msg_printf(p, MSG_INFO, "resumed by user"); p->resume(); } else if (!strcmp(op, "detach")) { if (p->attached_via_acct_mgr) { msg_printf(p, MSG_INFO, "This project must be detached using the account manager web site." ); fout.printf("<error>must detach using account manager</error>"); return; } gstate.detach_project(p); gstate.request_schedule_cpus("project detached by user"); gstate.request_work_fetch("project detached by user"); } else if (!strcmp(op, "update")) { msg_printf(p, MSG_INFO, "update requested by user"); p->sched_rpc_pending = RPC_REASON_USER_REQ; p->min_rpc_time = 0; #if 1 rss_feeds.trigger_fetch(p); #endif gstate.request_work_fetch("project updated by user"); } else if (!strcmp(op, "nomorework")) { msg_printf(p, MSG_INFO, "work fetch suspended by user"); p->dont_request_more_work = true; } else if (!strcmp(op, "allowmorework")) { msg_printf(p, MSG_INFO, "work fetch resumed by user"); p->dont_request_more_work = false; gstate.request_work_fetch("project allowed to fetch work by user"); } else if (!strcmp(op, "detach_when_done")) { msg_printf(p, MSG_INFO, "detach when done set by user"); p->detach_when_done = true; p->dont_request_more_work = true; } else if (!strcmp(op, "dont_detach_when_done")) { msg_printf(p, MSG_INFO, "detach when done cleared by user"); p->detach_when_done = false; p->dont_request_more_work = false; } fout.printf("<success/>\n"); }
void ACCT_MGR_OP::handle_reply(int http_op_retval) { unsigned int i; int retval; bool verified; PROJECT* pp; bool sig_ok; bool got_error = false; // check for failures of HTTP OP, reply parse // if (http_op_retval) { msg_printf(&ami, MSG_INFO, "AM RPC HTTP failure: %s", boincerror(http_op_retval) ); got_error = true; } else { FILE* f = fopen(ACCT_MGR_REPLY_FILENAME, "r"); if (f) { retval = parse(f); if (retval) { got_error = true; msg_printf(&ami, MSG_INFO, "AM reply parse error"); } fclose(f); } else { msg_printf(&ami, MSG_INFO, "AM reply file missing"); got_error = true; } } // if no errors so far, check for errors from AM // if (!got_error) { gstate.acct_mgr_info.password_error = false; if (error_num == ERR_BAD_PASSWD && !via_gui) { gstate.acct_mgr_info.password_error = true; } // Show error message from AM if available. // check both error_str and error_num since an account manager may only // return a BOINC based error code for password failures or invalid // email addresses // if (error_str.size()) { msg_printf(&ami, MSG_USER_ALERT, "%s: %s", _("Message from account manager"), error_str.c_str() ); got_error = true; } else if (error_num) { msg_printf(&ami, MSG_USER_ALERT, "%s: %s", _("Message from account manager"), boincerror(error_num) ); got_error = true; } } if (got_error) { gstate.acct_mgr_info.next_rpc_time = gstate.now + calculate_exponential_backoff( gstate.acct_mgr_info.nfailures, ACCT_MGR_MIN_BACKOFF, ACCT_MGR_MAX_BACKOFF ) ; gstate.acct_mgr_info.nfailures++; return; } // The RPC was successful // // Detach projects that are // - detach_when_done // - done // - attached via AM // while (1) { bool found = false; for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; if (p->detach_when_done && !gstate.nresults_for_project(p) && p->attached_via_acct_mgr) { gstate.detach_project(p); found = true; } } if (!found) break; } gstate.acct_mgr_info.nfailures = 0; msg_printf(NULL, MSG_INFO, "Account manager contact succeeded"); // demand a signing key // sig_ok = true; if (!strlen(ami.signing_key)) { msg_printf(NULL, MSG_INTERNAL_ERROR, "No signing key from account manager" ); sig_ok = false; } // don't accept new signing key if we already have one // if (strlen(gstate.acct_mgr_info.signing_key) && strcmp(gstate.acct_mgr_info.signing_key, ami.signing_key) ) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Inconsistent signing key from account manager" ); sig_ok = false; } if (sig_ok) { // if the AM RPC had an error, some items may be missing; don't copy // if (strlen(ami.project_name)) { safe_strcpy(gstate.acct_mgr_info.project_name, ami.project_name); } if (strlen(ami.signing_key)) { safe_strcpy(gstate.acct_mgr_info.signing_key, ami.signing_key); } if (strlen(ami.opaque)) { safe_strcpy(gstate.acct_mgr_info.opaque, ami.opaque); } safe_strcpy(gstate.acct_mgr_info.master_url, ami.master_url); safe_strcpy(gstate.acct_mgr_info.login_name, ami.login_name); safe_strcpy(gstate.acct_mgr_info.password_hash, ami.password_hash); safe_strcpy(gstate.acct_mgr_info.authenticator, ami.authenticator); gstate.acct_mgr_info.no_project_notices = ami.no_project_notices; gstate.acct_mgr_info.dynamic = ami.dynamic; // process projects // for (i=0; i<accounts.size(); i++) { AM_ACCOUNT& acct = accounts[i]; pp = gstate.lookup_project(acct.url.c_str()); if (pp) { if (acct.detach) { if (pp->attached_via_acct_mgr) { gstate.detach_project(pp); } } else { // The AM can leave authenticator blank if request message // had the current account info // if (acct.authenticator.size()) { if (strcmp(pp->authenticator, acct.authenticator.c_str())) { // if old and new auths are both weak, // use the new one // if (is_weak_auth(pp->authenticator) && is_weak_auth(acct.authenticator.c_str()) ) { safe_strcpy(pp->authenticator, acct.authenticator.c_str()); msg_printf(pp, MSG_INFO, "Received new authenticator from account manager" ); } else { // otherwise skip this update // msg_printf(pp, MSG_INFO, "Already attached to a different account" ); continue; } } } pp->attached_via_acct_mgr = true; if (acct.dont_request_more_work.present) { pp->dont_request_more_work = acct.dont_request_more_work.value; } else { pp->dont_request_more_work = false; } if (acct.detach_when_done.present) { pp->detach_when_done = acct.detach_when_done.value; if (pp->detach_when_done) { pp->dont_request_more_work = true; } } else { pp->detach_when_done = false; } // initiate a scheduler RPC if requested by AMS // if (acct.update) { pp->sched_rpc_pending = RPC_REASON_ACCT_MGR_REQ; pp->min_rpc_time = 0; } if (acct.resource_share.present) { pp->ams_resource_share = acct.resource_share.value; pp->resource_share = pp->ams_resource_share; } else { // no host-specific resource share; // if currently have one, restore to value from web // if (pp->ams_resource_share >= 0) { pp->ams_resource_share = -1; PROJECT p2; safe_strcpy(p2.master_url, pp->master_url); retval = p2.parse_account_file(); if (!retval) { pp->resource_share = p2.resource_share; } else { pp->resource_share = 100; } } } if (acct.suspend.present) { if (acct.suspend.value) { pp->suspend(); } else { pp->resume(); } } if (acct.abort_not_started.present) { if (acct.abort_not_started.value) { pp->abort_not_started(); } } for (int j=0; j<MAX_RSC; j++) { pp->no_rsc_ams[j] = acct.no_rsc[j]; } } } else { // here we don't already have the project. // retval = check_string_signature2( acct.url.c_str(), acct.url_signature, ami.signing_key, verified ); if (retval || !verified) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Bad signature for URL %s", acct.url.c_str() ); continue; } if (acct.authenticator.empty()) { msg_printf(NULL, MSG_INFO, "Account manager reply missing authenticator for %s", acct.url.c_str() ); continue; } // Attach to it, unless the acct mgr is telling us to detach // if (!acct.detach && !(acct.detach_when_done.present && acct.detach_when_done.value)) { msg_printf(NULL, MSG_INFO, "Attaching to %s", acct.url.c_str() ); gstate.add_project( acct.url.c_str(), acct.authenticator.c_str(), "", true ); pp = gstate.lookup_project(acct.url.c_str()); if (pp) { for (int j=0; j<MAX_RSC; j++) { pp->no_rsc_ams[j] = acct.no_rsc[j]; } if (acct.dont_request_more_work.present) { pp->dont_request_more_work = acct.dont_request_more_work.value; } if (acct.suspend.present && acct.suspend.value) { pp->suspend(); } } else { msg_printf(NULL, MSG_INTERNAL_ERROR, "Failed to add project: %s", acct.url.c_str() ); } } } } #ifdef USE_NET_PREFS bool read_prefs = false; if (strlen(host_venue) && strcmp(host_venue, gstate.main_host_venue)) { safe_strcpy(gstate.main_host_venue, host_venue); read_prefs = true; } // process prefs if any // if (!global_prefs_xml.empty()) { retval = gstate.save_global_prefs( global_prefs_xml.c_str(), ami.master_url, ami.master_url ); if (retval) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Can't save global prefs"); } read_prefs = true; } // process prefs if prefs or venue changed // if (read_prefs) { gstate.read_global_prefs(); } #endif handle_sr_feeds(rss_feeds, &gstate.acct_mgr_info); // in case no_project_notices changed // ::rss_feeds.update_feed_list(); } safe_strcpy(gstate.acct_mgr_info.user_name, ami.user_name); safe_strcpy(gstate.acct_mgr_info.team_name, ami.team_name); safe_strcpy( gstate.acct_mgr_info.previous_host_cpid, gstate.host_info.host_cpid ); if (repeat_sec) { gstate.acct_mgr_info.next_rpc_time = gstate.now + repeat_sec; } else { gstate.acct_mgr_info.next_rpc_time = gstate.now + 86400; } gstate.acct_mgr_info.user_keywords = ami.user_keywords; gstate.acct_mgr_info.write_info(); gstate.set_client_state_dirty("account manager RPC"); }