// do an account manager RPC; // if URL is null, detach from current account manager // int ACCT_MGR_OP::do_rpc(ACCT_MGR_INFO& _ami, bool _via_gui) { int retval; unsigned int i; char buf[256]; ami = _ami; error_num = ERR_IN_PROGRESS; error_str = ""; via_gui = _via_gui; global_prefs_xml = ""; // if null URL, detach from current AMS // if (!strlen(ami.master_url) && strlen(gstate.acct_mgr_info.master_url)) { msg_printf(NULL, MSG_INFO, "Removing account manager info"); gstate.acct_mgr_info.clear(); boinc_delete_file(ACCT_MGR_URL_FILENAME); boinc_delete_file(ACCT_MGR_LOGIN_FILENAME); error_num = 0; for (i=0; i<gstate.projects.size(); i++) { gstate.projects[i]->detach_ams(); } ::rss_feeds.update_feed_list(); gstate.set_client_state_dirty("detach from AMS"); return 0; } canonicalize_master_url(ami.master_url, sizeof(ami.master_url)); if (!valid_master_url(ami.master_url)) { error_num = ERR_INVALID_URL; return 0; } FILE* f = boinc_fopen(ACCT_MGR_REQUEST_FILENAME, "w"); if (!f) return ERR_FOPEN; fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" "<acct_mgr_request>\n" ); if (strlen(ami.authenticator)) { fprintf(f, " <authenticator>%s</authenticator>\n", ami.authenticator ); } else { fprintf(f, " <name>%s</name>\n" " <password_hash>%s</password_hash>\n", ami.login_name, ami.password_hash ); } fprintf(f, " <host_cpid>%s</host_cpid>\n" " <domain_name>%s</domain_name>\n" " <client_version>%d.%d.%d</client_version>\n" " <run_mode>%s</run_mode>\n", gstate.host_info.host_cpid, gstate.host_info.domain_name, gstate.core_client_version.major, gstate.core_client_version.minor, gstate.core_client_version.release, run_mode_name[gstate.cpu_run_mode.get_perm()] ); gstate.write_platforms(NULL, f); if (strlen(gstate.acct_mgr_info.previous_host_cpid)) { fprintf(f, " <previous_host_cpid>%s</previous_host_cpid>\n", gstate.acct_mgr_info.previous_host_cpid ); } // If the AMS requested it, send GUI RPC port and password. // This is for the "farm" account manager so it // can know where to send GUI RPC requests to // without having to configure each host // if (gstate.acct_mgr_info.send_gui_rpc_info) { if (gstate.cmdline_gui_rpc_port) { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", gstate.cmdline_gui_rpc_port); } else { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", GUI_RPC_PORT); } if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) { char gui_rpc_password[256]; safe_strcpy(gui_rpc_password, ""); FILE* pwdf = fopen(GUI_RPC_PASSWD_FILE, "r"); if (pwdf) { if (fgets(gui_rpc_password, 256, pwdf)) { strip_whitespace(gui_rpc_password); } fclose(pwdf); } fprintf(f, " <gui_rpc_password>%s</gui_rpc_password>\n", gui_rpc_password ); } } for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; double not_started_dur, in_progress_dur; p->get_task_durs(not_started_dur, in_progress_dur); fprintf(f, " <project>\n" " <url>%s</url>\n" " <project_name>%s</project_name>\n" " <suspended_via_gui>%d</suspended_via_gui>\n" " <hostid>%d</hostid>\n" " <not_started_dur>%f</not_started_dur>\n" " <in_progress_dur>%f</in_progress_dur>\n" " <attached_via_acct_mgr>%d</attached_via_acct_mgr>\n" " <dont_request_more_work>%d</dont_request_more_work>\n" " <detach_when_done>%d</detach_when_done>\n" " <ended>%d</ended>\n" " <resource_share>%f</resource_share>\n" " <disk_usage>%f</disk_usage>\n" " <disk_share>%f</disk_share>\n", p->master_url, p->project_name, p->suspended_via_gui?1:0, p->hostid, not_started_dur, in_progress_dur, p->attached_via_acct_mgr?1:0, p->dont_request_more_work?1:0, p->detach_when_done?1:0, p->ended?1:0, p->resource_share, p->disk_usage, p->disk_share ); // send work and starvation-related info // if (ami.dynamic) { fprintf(f, " <nrpc_failures>%d</nrpc_failures>\n" " <cpu_ec>%f</cpu_ec>\n" " <cpu_time>%f</cpu_time>\n" " <gpu_ec>%f</gpu_ec>\n" " <gpu_time>%f</gpu_time>\n" " <njobs_success>%d</njobs_success>\n" " <njobs_error>%d</njobs_error>\n", p->nrpc_failures, p->cpu_ec, p->cpu_time, p->gpu_ec, p->gpu_time, p->njobs_success, p->njobs_error ); for (int j=0; j<coprocs.n_rsc; j++) { if (p->sched_req_no_work[j]) { fprintf(f, " <sched_req_no_work>%s</sched_req_no_work>\n", coprocs.coprocs[j].type ); } } } if (p->attached_via_acct_mgr) { fprintf(f, " <account_key>%s</account_key>\n", p->authenticator ); } fprintf(f, " </project>\n" ); } MIOFILE mf; mf.init_file(f); // send working prefs // fprintf(f, "<working_global_preferences>\n"); gstate.global_prefs.write(mf); fprintf(f, "</working_global_preferences>\n"); if (boinc_file_exists(GLOBAL_PREFS_FILE_NAME)) { FILE* fprefs = fopen(GLOBAL_PREFS_FILE_NAME, "r"); if (fprefs) { copy_stream(fprefs, f); fclose(fprefs); } } gstate.host_info.write(mf, !cc_config.suppress_net_info, true); if (strlen(gstate.acct_mgr_info.opaque)) { fprintf(f, " <opaque>\n%s\n" " </opaque>\n", gstate.acct_mgr_info.opaque ); } gstate.time_stats.write(mf, true); gstate.net_stats.write(mf); fprintf(f, "</acct_mgr_request>\n"); fclose(f); snprintf(buf, sizeof(buf), "%srpc.php", ami.master_url); retval = gui_http->do_rpc_post( this, buf, ACCT_MGR_REQUEST_FILENAME, ACCT_MGR_REPLY_FILENAME, true ); if (retval) { error_num = retval; return retval; } msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", ami.master_url); return 0; }
// do an account manager RPC; // if URL is null, detach from current account manager // int ACCT_MGR_OP::do_rpc( std::string _url, std::string name, std::string password_hash, bool _via_gui ) { int retval; unsigned int i; char url[256], password[256], buf[256]; FILE *pwdf; strlcpy(url, _url.c_str(), sizeof(url)); error_num = ERR_IN_PROGRESS; via_gui = _via_gui; if (global_prefs_xml) { free(global_prefs_xml); global_prefs_xml = 0; } // if null URL, detach from current AMS // if (!strlen(url) && strlen(gstate.acct_mgr_info.master_url)) { msg_printf(NULL, MSG_INFO, "Removing account manager info"); gstate.acct_mgr_info.clear(); boinc_delete_file(ACCT_MGR_URL_FILENAME); boinc_delete_file(ACCT_MGR_LOGIN_FILENAME); error_num = 0; for (i=0; i<gstate.projects.size(); i++) { gstate.projects[i]->detach_ams(); } return 0; } canonicalize_master_url(url); if (!valid_master_url(url)) { error_num = ERR_INVALID_URL; return 0; } strlcpy(ami.master_url, url, sizeof(ami.master_url)); strlcpy(ami.project_name, "", sizeof(ami.project_name)); strlcpy(ami.login_name, name.c_str(), sizeof(ami.login_name)); strlcpy(ami.password_hash, password_hash.c_str(), sizeof(ami.password_hash)); FILE* f = boinc_fopen(ACCT_MGR_REQUEST_FILENAME, "w"); if (!f) return ERR_FOPEN; fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" "<acct_mgr_request>\n" " <name>%s</name>\n" " <password_hash>%s</password_hash>\n" " <host_cpid>%s</host_cpid>\n" " <domain_name>%s</domain_name>\n" " <client_version>%d.%d.%d</client_version>\n" " <run_mode>%s</run_mode>\n", name.c_str(), password_hash.c_str(), gstate.host_info.host_cpid, gstate.host_info.domain_name, gstate.core_client_version.major, gstate.core_client_version.minor, gstate.core_client_version.release, run_mode_name[gstate.cpu_run_mode.get_perm()] ); if (strlen(gstate.acct_mgr_info.previous_host_cpid)) { fprintf(f, " <previous_host_cpid>%s</previous_host_cpid>\n", gstate.acct_mgr_info.previous_host_cpid ); } // If the AMS requested it, send GUI RPC port and password hash. // This is for the "farm" account manager so it // can know where to send GUI RPC requests to // without having to configure each host // if (gstate.acct_mgr_info.send_gui_rpc_info) { if (gstate.cmdline_gui_rpc_port) { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", gstate.cmdline_gui_rpc_port); } else { fprintf(f," <gui_rpc_port>%d</gui_rpc_port>\n", GUI_RPC_PORT); } if (boinc_file_exists(GUI_RPC_PASSWD_FILE)) { strcpy(password, ""); pwdf = fopen(GUI_RPC_PASSWD_FILE, "r"); if (pwdf) { if (fgets(password, 256, pwdf)) { strip_whitespace(password); } fclose(pwdf); } fprintf(f," <gui_rpc_password>%s</gui_rpc_password>\n", password); } } for (i=0; i<gstate.projects.size(); i++) { PROJECT* p = gstate.projects[i]; double not_started_dur, in_progress_dur; p->get_task_durs(not_started_dur, in_progress_dur); fprintf(f, " <project>\n" " <url>%s</url>\n" " <project_name>%s</project_name>\n" " <suspended_via_gui>%d</suspended_via_gui>\n" " <account_key>%s</account_key>\n" " <hostid>%d</hostid>\n" " <not_started_dur>%f</not_started_dur>\n" " <in_progress_dur>%f</in_progress_dur>\n" " <attached_via_acct_mgr>%d</attached_via_acct_mgr>\n" " <dont_request_more_work>%d</dont_request_more_work>\n" " <detach_when_done>%d</detach_when_done>\n" " <ended>%d</ended>\n" " </project>\n", p->master_url, p->project_name, p->suspended_via_gui?1:0, p->authenticator, p->hostid, not_started_dur, in_progress_dur, p->attached_via_acct_mgr?1:0, p->dont_request_more_work?1:0, p->detach_when_done?1:0, p->ended?1:0 ); } MIOFILE mf; mf.init_file(f); // send working prefs // fprintf(f, "<working_global_preferences>\n"); gstate.global_prefs.write(mf); fprintf(f, "</working_global_preferences>\n"); if (boinc_file_exists(GLOBAL_PREFS_FILE_NAME)) { FILE* fprefs = fopen(GLOBAL_PREFS_FILE_NAME, "r"); if (fprefs) { copy_stream(fprefs, f); fclose(fprefs); } } gstate.host_info.write(mf, !config.suppress_net_info, true); if (strlen(gstate.acct_mgr_info.opaque)) { fprintf(f, " <opaque>\n%s\n" " </opaque>\n", gstate.acct_mgr_info.opaque ); } gstate.time_stats.write(mf, true); gstate.net_stats.write(mf); fprintf(f, "</acct_mgr_request>\n"); fclose(f); sprintf(buf, "%srpc.php", url); retval = gui_http->do_rpc_post( this, buf, ACCT_MGR_REQUEST_FILENAME, ACCT_MGR_REPLY_FILENAME, true ); if (retval) { error_num = retval; return retval; } msg_printf(NULL, MSG_INFO, "Contacting account manager at %s", url); return 0; }