/src/modules/rms.c
C | 180 lines | 84 code | 24 blank | 72 comment | 7 complexity | 262b46de9020d7d305b0530f074efa12 MD5 | raw file
1/*****************************************************************************\ 2 * $Id$ 3 ***************************************************************************** 4 * Copyright (C) 2001-2006 The Regents of the University of California. 5 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 6 * Written by Jim Garlick <garlick@llnl.gov>. 7 * UCRL-CODE-2003-005. 8 * 9 * This file is part of Pdsh, a parallel remote shell program. 10 * For details, see <http://www.llnl.gov/linux/pdsh/>. 11 * 12 * Pdsh is free software; you can redistribute it and/or modify it under 13 * the terms of the GNU General Public License as published by the Free 14 * Software Foundation; either version 2 of the License, or (at your option) 15 * any later version. 16 * 17 * Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY 18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 20 * details. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with Pdsh; if not, write to the Free Software Foundation, Inc., 24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 25\*****************************************************************************/ 26 27#if HAVE_CONFIG_H 28# include "config.h" 29#endif 30 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34 35#include "src/common/hostlist.h" 36#include "src/common/err.h" 37#include "src/common/xmalloc.h" 38#include "src/common/xstring.h" 39#include "src/pdsh/xpopen.h" 40#include "src/pdsh/mod.h" 41 42#if STATIC_MODULES 43# define pdsh_module_info rms_module_info 44# define pdsh_module_priority rms_module_priority 45#endif 46 47int pdsh_module_priority = 10; 48 49/* 50 * Call this module after all option processing. The module will only 51 * try to read the RMS_RESOURCEID if opt->wcoll is not already set. 52 * Calling the module in postop allows us to be sure that all other 53 * modules had a chance to update the wcoll. 54 */ 55static int mod_rms_postop(opt_t *opt); 56static hostlist_t _rms_rid_to_nodes(char *part, int rid); 57static hostlist_t _rms_wcoll(void); 58 59/* 60 * Export generic pdsh module options 61 */ 62struct pdsh_module_operations rms_module_ops = { 63 (ModInitF) NULL, 64 (ModExitF) NULL, 65 (ModReadWcollF) NULL, 66 (ModPostOpF) mod_rms_postop 67}; 68 69/* 70 * Export rcmd module operations 71 */ 72struct pdsh_rcmd_operations rms_rcmd_ops = { 73 (RcmdInitF) NULL, 74 (RcmdSigF) NULL, 75 (RcmdF) NULL, 76}; 77 78/* 79 * Export module options 80 */ 81struct pdsh_module_option rms_module_options[] = 82 { 83 PDSH_OPT_TABLE_END 84 }; 85 86/* 87 * Rms module info 88 */ 89struct pdsh_module pdsh_module_info = { 90 "misc", 91 "rms", 92 "Jim Garlick <garlick@llnl.gov>", 93 "Attempt to read wcoll from RMS_RESOURCEID env var", 94 DSH | PCP, 95 96 &rms_module_ops, 97 &rms_rcmd_ops, 98 &rms_module_options[0], 99}; 100 101/* 102 * If no wcoll has been established by this time, look for the 103 * RMS_RESOURCE env var, and set wcoll to the list of nodes allocated 104 * to that resource. 105 */ 106static int mod_rms_postop(opt_t *opt) 107{ 108 if (opt->wcoll) 109 return 0; 110 111 opt->wcoll = _rms_wcoll(); 112 113 return 0; 114} 115 116/* 117 * Helper for rms_wcoll() - RMS provides no API to get the list of nodes 118 * once allocated, so we query the msql database with 'rmsquery'. 119 * part (IN) partition name 120 * rid (IN) resource id 121 * result (RETURN) NULL or a list of hostnames 122 */ 123static hostlist_t _rms_rid_to_nodes(char *part, int rid) 124{ 125 FILE *f; 126 char tmp[256]; 127 128 /* XXX how to specify partition? do we need to? */ 129 snprintf(tmp, sizeof(tmp), 130 "%s \"select hostnames from resources where name='%d'\"", 131 _PATH_RMSQUERY, rid); 132 f = xpopen(tmp, "r"); 133 if (f == NULL) 134 errx("%p: error running %s\n", _PATH_RMSQUERY); 135 *tmp = '\0'; 136 while (fgets(tmp, sizeof(tmp), f) != NULL); 137 xpclose(f); 138 /* should either have empty string or host[n-m] range */ 139 /* turn elanid range into list of hostnames */ 140 xstrcln(tmp, "\r\n\t "); /* drop trailing \n */ 141 return hostlist_create(tmp); 142} 143 144/* 145 * If RMS_RESOURCE is set, return wcoll corresponding to RMS res allocation. 146 * result (RETURN) NULL or a list of hostnames 147 */ 148static hostlist_t _rms_wcoll(void) 149{ 150 char *rhs; 151 hostlist_t result = NULL; 152 153 /* extract partition and resource ID from environment, if present */ 154 if ((rhs = getenv("RMS_RESOURCEID"))) { 155 char *part, *ridstr = strchr(rhs, '.'); 156 int rid; 157 158 if (!ridstr) 159 errx("%p: malformed RMS_RESOURCEID value\n"); 160 *ridstr++ = '\0'; 161 rid = atoi(ridstr); 162 part = rhs; 163 164 result = _rms_rid_to_nodes(part, rid); 165 } 166 167 /* 168 * Depend on PAM to keep user from setting RMS_RESOURCEID to 169 * someone else's allocation and stealing cycles. pam_rms should 170 * check to see if user has allocated the node before allowing qshd 171 * authorization to succede. 172 */ 173 174 return result; 175} 176 177 178/* 179 * vi: tabstop=4 shiftwidth=4 expandtab 180 */