00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdCmsClientConfigCVSID = "$Id: XrdCmsClientConfig.cc 35287 2010-09-14 21:19:35Z ganis $";
00014
00015
00016
00017 #include <unistd.h>
00018 #include <ctype.h>
00019 #include <strings.h>
00020 #include <stdio.h>
00021 #include <sys/param.h>
00022 #include <sys/socket.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <sys/un.h>
00026 #include <fcntl.h>
00027
00028 #include "XrdCms/XrdCmsClientConfig.hh"
00029 #include "XrdCms/XrdCmsClientMsg.hh"
00030 #include "XrdCms/XrdCmsSecurity.hh"
00031 #include "XrdCms/XrdCmsTrace.hh"
00032
00033 #include "XrdSys/XrdSysHeaders.hh"
00034 #include "XrdOuc/XrdOuca2x.hh"
00035 #include "XrdOuc/XrdOucEnv.hh"
00036 #include "XrdOuc/XrdOucStream.hh"
00037 #include "XrdOuc/XrdOucTList.hh"
00038 #include "XrdOuc/XrdOucUtils.hh"
00039 #include "XrdNet/XrdNetDNS.hh"
00040
00041 using namespace XrdCms;
00042
00043
00044
00045
00046
00047 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config);
00048
00049
00050
00051
00052
00053 XrdCmsClientConfig::~XrdCmsClientConfig()
00054 {
00055 XrdOucTList *tp, *tpp;
00056
00057 tpp = ManList;
00058 while((tp = tpp)) {tpp = tp->next; delete tp;}
00059 tpp = PanList;
00060 while((tp = tpp)) {tpp = tp->next; delete tp;}
00061 }
00062
00063
00064
00065
00066
00067 int XrdCmsClientConfig::Configure(char *cfn, configWhat What, configHow How)
00068 {
00069
00070
00071
00072
00073
00074
00075
00076 EPNAME("Configure");
00077 static const char *mySid = 0;
00078 XrdOucTList *tpe, *tpl;
00079 int i, NoGo = 0;
00080 const char *eText = 0;
00081 char buff[256], *slash, *temp, *bP, sfx;
00082
00083
00084
00085 myHost = getenv("XRDHOST");
00086 myName = XrdOucUtils::InstName(1);
00087 CMSPath= strdup("/tmp/");
00088 isMeta = How & configMeta;
00089 isMan = What& configMan;
00090
00091
00092
00093 if (!(NoGo = ConfigProc(cfn)) && isMan)
00094 {if (How & configProxy) eText = (PanList ? 0 : "Proxy manager");
00095 else if (!ManList)
00096 eText = (How & configMeta ? "Meta manager" : "Manager");
00097 if (eText) {Say.Emsg("Config", eText, "not specified."); NoGo=1;}
00098 }
00099
00100
00101
00102 if (getenv("XRDDEBUG")) Trace.What = TRACE_ALL;
00103
00104
00105
00106 temp=XrdOucUtils::genPath(CMSPath, XrdOucUtils::InstName(-1), ".olb");
00107 free(CMSPath); CMSPath = temp;
00108 XrdOucEnv::Export("XRDCMSPATH", temp);
00109 XrdOucEnv::Export("XRDOLBPATH", temp);
00110
00111
00112
00113 tpl = (How & configProxy ? PanList : ManList);
00114 if (!mySid)
00115 { if (What & configServer) sfx = 's';
00116 else if (What & configSuper) sfx = 'u';
00117 else sfx = 'm';
00118 if (!(mySid = XrdCmsSecurity::setSystemID(tpl, myName, myHost, sfx)))
00119 {Say.Emsg("xrootd","Unable to generate system ID; too many managers.");
00120 NoGo = 1;
00121 } else {DEBUG("Global System Identification: " <<mySid);}
00122 }
00123
00124
00125
00126 if (tpl)
00127 {i = 0; tpe = tpl;
00128 while(tpe) {i += strlen(tpe->text) + 9; tpe = tpe->next;}
00129 bP = temp = (char *)malloc(i);
00130 while(tpl)
00131 {bP += sprintf(bP, "%s:%d ", tpl->text, tpl->val);
00132 tpl = tpl->next;
00133 }
00134 *(bP-1) = '\0';
00135 XrdOucEnv::Export("XRDCMSMAN", temp); free(temp);
00136 }
00137
00138
00139
00140 i = strlen(CMSPath);
00141 if (What & configSuper)
00142 {while((tpl = ManList)) {ManList = tpl->next; delete tpl;}
00143 slash = (CMSPath[i-1] == '/' ? (char *)"" : (char *)"/");
00144 sprintf(buff, "%s%solbd.super", CMSPath, slash);
00145 ManList = new XrdOucTList(buff, -1, 0);
00146 SMode = SModeP = FailOver;
00147 }
00148
00149
00150
00151 temp = (What & (configMan|configSuper) ? (char *)"nimda" : (char *)"admin");
00152 slash = (CMSPath[i-1] == '/' ? (char *)"" : (char *)"/");
00153 sprintf(buff, "%s%solbd.%s", CMSPath, slash, temp);
00154 free(CMSPath); CMSPath = strdup(buff);
00155
00156 RepWaitMS = RepWait * 1000;
00157
00158
00159
00160 if (XrdCmsClientMsg::Init())
00161 {Say.Emsg("Config", ENOMEM, "allocate initial msg objects");
00162 NoGo = 1;
00163 }
00164
00165 return NoGo;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175 int XrdCmsClientConfig::ConfigProc(char *ConfigFN)
00176 {
00177 static int DoneOnce = 0;
00178 char *var;
00179 int cfgFD, retc, NoGo = 0;
00180 XrdOucEnv myEnv;
00181 XrdOucStream Config((DoneOnce ? 0 : &Say), getenv("XRDINSTANCE"),
00182 &myEnv, "=====> ");
00183
00184
00185
00186 if (!ConfigFN || !*ConfigFN)
00187 {Say.Emsg("Config", "cms configuration file not specified.");
00188 return 1;
00189 }
00190
00191
00192
00193 if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00194 {Say.Emsg("Config", errno, "open config file", ConfigFN);
00195 return 1;
00196 }
00197 Config.Attach(cfgFD);
00198
00199
00200
00201 while((var = Config.GetMyFirstWord()))
00202 {if (!strncmp(var, "cms.", 4)
00203 || !strncmp(var, "odc.", 4)
00204 || !strcmp(var, "all.manager")
00205 || !strcmp(var, "all.adminpath")
00206 || !strcmp(var, "olb.adminpath"))
00207 if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
00208 }
00209
00210
00211
00212 if ((retc = Config.LastError()))
00213 NoGo = Say.Emsg("Config", retc, "read config file", ConfigFN);
00214 Config.Close();
00215
00216
00217
00218 DoneOnce = 1;
00219 return NoGo;
00220 }
00221
00222
00223
00224
00225
00226 int XrdCmsClientConfig::ConfigXeq(char *var, XrdOucStream &Config)
00227 {
00228
00229
00230
00231 TS_Xeq("conwait", xconw);
00232 TS_Xeq("manager", xmang);
00233 TS_Xeq("adminpath", xapath);
00234 TS_Xeq("request", xreqs);
00235 TS_Xeq("trace", xtrac);
00236 return 0;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 int XrdCmsClientConfig::xapath(XrdOucStream &Config)
00257 {
00258 struct sockaddr_un USock;
00259 char *pval;
00260
00261
00262
00263 pval = Config.GetWord();
00264 if (!pval || !pval[0])
00265 {Say.Emsg("Config", "cms admin path not specified"); return 1;}
00266
00267
00268
00269 if (*pval != '/')
00270 {Say.Emsg("Config", "cms admin path not absolute"); return 1;}
00271
00272
00273
00274 if (strlen(pval) > sizeof(USock.sun_path) - 11)
00275 {Say.Emsg("Config", "cms admin path is too long.");
00276 return 1;
00277 }
00278
00279
00280
00281 if (CMSPath) free(CMSPath);
00282 CMSPath = strdup(pval);
00283 return 0;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 int XrdCmsClientConfig::xconw(XrdOucStream &Config)
00302 {
00303 char *val;
00304 int cw;
00305
00306 if (!(val = Config.GetWord()))
00307 {Say.Emsg("Config", "conwait value not specified."); return 1;}
00308
00309 if (XrdOuca2x::a2tm(Say,"conwait value",val,&cw,1)) return 1;
00310
00311 ConWait = cw;
00312 return 0;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 int XrdCmsClientConfig::xmang(XrdOucStream &Config)
00351 {
00352 struct sockaddr InetAddr[8];
00353 XrdOucTList *tp = 0, *tpp = 0, *tpnew;
00354 char *val, *bval = 0, *mval = 0;
00355 int rc, i, j, port, xMeta = 0, isProxy = 0, smode = FailOver;
00356
00357
00358
00359 if ((val = Config.GetWord()))
00360 {if (!strcmp("peer", val)) return Config.noEcho();
00361 if ((isProxy = !strcmp("proxy", val))) val = Config.GetWord();
00362 else if ((xMeta = !strcmp("meta", val)))
00363 if (isMeta || isMan) val = Config.GetWord();
00364 else return Config.noEcho();
00365 else if (isMeta) return Config.noEcho();
00366 }
00367
00368
00369
00370 if (val)
00371 { if (!strcmp("any", val)) smode = FailOver;
00372 else if (!strcmp("all", val)) smode = RoundRob;
00373 else smode = 0;
00374 if (smode)
00375 {if (isProxy) SModeP = smode;
00376 else SMode = smode;
00377 val = Config.GetWord();
00378 }
00379 }
00380
00381
00382
00383 if (!val)
00384 {Say.Emsg("Config","manager host name not specified"); return 1;}
00385 else mval = strdup(val);
00386
00387 if (!(val = index(mval,':'))) val = Config.GetWord();
00388 else {*val = '\0'; val++;}
00389
00390 if (val)
00391 {if (isdigit(*val))
00392 {if (XrdOuca2x::a2i(Say,"manager port",val,&port,1,65535))
00393 port = 0;
00394 }
00395 else if (!(port = XrdNetDNS::getPort(val, "tcp")))
00396 {Say.Emsg("Config", "unable to find tcp service", val);
00397 port = 0;
00398 }
00399 } else Say.Emsg("Config","manager port not specified for",mval);
00400
00401 if (!port) {free(mval); return 1;}
00402
00403 if (myHost && (val = Config.GetWord()) && !strcmp("if", val))
00404 if ((rc = XrdOucUtils::doIf(&Say,Config,"role directive",myHost, myName,
00405 getenv("XRDPROG"))) <= 0)
00406 {free(mval);
00407 return (rc < 0);
00408 }
00409
00410 i = strlen(mval);
00411 if (mval[i-1] != '+')
00412 {i = 0; val = mval; mval = XrdNetDNS::getHostName(mval); free(val);}
00413 else {bval = strdup(mval); mval[i-1] = '\0';
00414 if (!(i = XrdNetDNS::getHostAddr(mval, InetAddr, 8)))
00415 {Say.Emsg("Config","Manager host", mval, "not found");
00416 free(bval); free(mval); return 1;
00417 }
00418 }
00419
00420 if (xMeta && !isMeta)
00421 {haveMeta = 1; free(bval); free(mval); return 0;}
00422
00423 do {if (i)
00424 {i--; free(mval);
00425 mval = XrdNetDNS::getHostName(InetAddr[i]);
00426 Say.Emsg("Config", bval, "-> all.manager", mval);
00427 }
00428 tp = (isProxy ? PanList : ManList); tpp = 0; j = 1;
00429 while(tp)
00430 if ((j = strcmp(tp->text, mval)) < 0 || tp->val != port)
00431 {tpp = tp; tp = tp->next;}
00432 else {if (!j) Say.Emsg("Config","Duplicate manager",mval);
00433 break;
00434 }
00435 if (j) {tpnew = new XrdOucTList(mval, port, tp);
00436 if (tpp) tpp->next = tpnew;
00437 else if (isProxy) PanList = tpnew;
00438 else ManList = tpnew;
00439 }
00440 } while(i);
00441
00442 if (bval) free(bval);
00443 free(mval);
00444 return 0;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 int XrdCmsClientConfig::xreqs(XrdOucStream &Config)
00467 {
00468 char *val;
00469 static struct reqsopts {const char *opname; int istime; int *oploc;}
00470 rqopts[] =
00471 {
00472 {"delay", 1, &RepDelay},
00473 {"noresp", 0, &RepNone},
00474 {"prep", 1, &PrepWait},
00475 {"repwait", 1, &RepWait}
00476 };
00477 int i, ppp, numopts = sizeof(rqopts)/sizeof(struct reqsopts);
00478
00479 if (!(val = Config.GetWord()))
00480 {Say.Emsg("Config", "request arguments not specified"); return 1;}
00481
00482 while (val)
00483 do {for (i = 0; i < numopts; i++)
00484 if (!strcmp(val, rqopts[i].opname))
00485 { if (!(val = Config.GetWord()))
00486 {Say.Emsg("Config","request argument value not specified");
00487 return 1;}
00488 if (rqopts[i].istime ?
00489 XrdOuca2x::a2tm(Say,"request value",val,&ppp,1) :
00490 XrdOuca2x::a2i( Say,"request value",val,&ppp,1))
00491 return 1;
00492 else *rqopts[i].oploc = ppp;
00493 break;
00494 }
00495 if (i >= numopts) Say.Say("Config warning: ignoring invalid request option '",val,"'.");
00496 } while((val = Config.GetWord()));
00497 return 0;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 int XrdCmsClientConfig::xtrac(XrdOucStream &Config)
00515 {
00516 char *val;
00517 static struct traceopts {const char *opname; int opval;} tropts[] =
00518 {
00519 {"all", TRACE_ALL},
00520 {"debug", TRACE_Debug},
00521 {"forward", TRACE_Forward},
00522 {"redirect", TRACE_Redirect},
00523 {"defer", TRACE_Defer},
00524 {"stage", TRACE_Stage}
00525 };
00526 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
00527
00528 if (!(val = Config.GetWord()))
00529 {Say.Emsg("config", "trace option not specified"); return 1;}
00530 while (val)
00531 {if (!strcmp(val, "off")) trval = 0;
00532 else {if ((neg = (val[0] == '-' && val[1]))) val++;
00533 for (i = 0; i < numopts; i++)
00534 {if (!strcmp(val, tropts[i].opname))
00535 {if (neg) trval &= ~tropts[i].opval;
00536 else trval |= tropts[i].opval;
00537 break;
00538 }
00539 }
00540 if (i >= numopts)
00541 Say.Say("Config warning: ignoring invalid trace option '",val,"'.");
00542 }
00543 val = Config.GetWord();
00544 }
00545 Trace.What = trval;
00546 return 0;
00547 }