Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / libadmin / cfg / cfgservers.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /* This file implements configuration functions in the following categories:
11 * cfg_BosServer*() - configure the BOS server.
12 * cfg_DbServers*() - configure the database servers.
13 * cfg_FileServer*() - configure the fileserver.
14 * cfg_UpdateServer*() - configure the update server.
15 * cfg_UpdateClient*() - configure update clients.
16 */
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20 #include <afs/stds.h>
21
22 #include <roken.h>
23
24 #include <ctype.h>
25
26 #ifdef AFS_NT40_ENV
27 #include <windows.h>
28 #include <WINNT/afsreg.h>
29 #endif /* AFS_NT40_ENV */
30
31 #include <pthread.h>
32
33 #include <rx/rx.h>
34 #include <rx/rxstat.h>
35
36 #include <afs/afs_Admin.h>
37 #include <afs/afs_AdminErrors.h>
38 #include <afs/afs_bosAdmin.h>
39 #include <afs/afs_clientAdmin.h>
40 #include <afs/afs_utilAdmin.h>
41 #include <afs/afs_vosAdmin.h>
42
43 #include <afs/dirpath.h>
44 #include <afs/bnode.h>
45 #include <afs/cellconfig.h>
46 #include <afs/bubasics.h>
47 #include <rx/rx_null.h>
48
49 #define UBIK_INTERNALS /* need "internal" symbols from ubik.h */
50 #include <ubik.h>
51
52 #include "cfginternal.h"
53 #include "afs_cfgAdmin.h"
54
55
56 /* Local declarations and definitions */
57
58 #define KASERVER_BOSNAME "kaserver"
59 #define KASERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/kaserver"
60
61 #define PTSERVER_BOSNAME "ptserver"
62 #define PTSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/ptserver"
63
64 #define VLSERVER_BOSNAME "vlserver"
65 #define VLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/vlserver"
66
67 #define BUSERVER_BOSNAME "buserver"
68 #define BUSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/buserver"
69
70 #define UPSERVER_BOSNAME "upserver"
71 #define UPSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upserver"
72
73 #define UPCLIENT_BOSNAME "upclient"
74 #define UPCLIENT_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upclient"
75
76 #define FILESERVER_BOSNAME "fs"
77 #define FILESERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/fileserver"
78 #define VOLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/volserver"
79 #define SALVAGER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/salvager"
80
81
82 static int
83 SimpleProcessStart(void *bosHandle, const char *instance,
84 const char *executable, const char *args,
85 afs_status_p st);
86
87 static int
88 FsProcessStart(void *bosHandle, const char *instance,
89 const char *fileserverExe, const char *volserverExe,
90 const char *salvagerExe, afs_status_p st);
91
92 static int
93 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st);
94
95 static void
96 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP);
97
98 static int
99 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance,
100 short *hasQuorum, afs_status_p st);
101
102 static int
103 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
104 short *isSyncSite, short *isWriteReady,
105 afs_status_p st);
106
107
108
109
110
111
112 /* ---------------- Exported constants ---------------- */
113
114 const char *cfg_kaserverBosName = KASERVER_BOSNAME;
115 const char *cfg_ptserverBosName = PTSERVER_BOSNAME;
116 const char *cfg_vlserverBosName = VLSERVER_BOSNAME;
117 const char *cfg_buserverBosName = BUSERVER_BOSNAME;
118 const char *cfg_fileserverBosName = FILESERVER_BOSNAME;
119 const char *cfg_upserverBosName = UPSERVER_BOSNAME;
120
121 const char *cfg_upclientBosNamePrefix = UPCLIENT_BOSNAME;
122 const char *cfg_upclientSysBosSuffix = "etc";
123 const char *cfg_upclientBinBosSuffix = "bin";
124
125
126
127 /* ---------------- Exported BOS Server functions ------------------ */
128
129
130 /*
131 * cfg_BosServerStart() -- Start the BOS server on host.
132 *
133 * Timeout is the maximum time, in seconds, to wait for BOS to start.
134 */
135 int ADMINAPI
136 cfg_BosServerStart(void *hostHandle, /* host config handle */
137 short noAuth, /* start in NoAuth mode */
138 unsigned int timeout, /* timeout (in seconds) */
139 afs_status_p st)
140 { /* completion status */
141 int rc = 1;
142 afs_status_t tst2, tst = 0;
143 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
144 short wasRunning = 0;
145
146 /* validate parameters */
147
148 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
149 tst = tst2;
150 }
151
152 /* remote configuration not yet supported in this function */
153
154 if (tst == 0) {
155 if (!cfg_host->is_local) {
156 tst = ADMCFGNOTSUPPORTED;
157 }
158 }
159
160 /* start bosserver (if not already running) */
161
162 #ifdef AFS_NT40_ENV
163 /* Windows - bosserver is controlled via the BOS control service */
164 if (tst == 0) {
165 DWORD auxArgc;
166 LPCTSTR auxArgBuf[1], *auxArgv;
167
168 if (noAuth) {
169 auxArgc = 1;
170 auxArgv = auxArgBuf;
171 auxArgBuf[0] = "-noauth";
172 } else {
173 auxArgc = 0;
174 auxArgv = NULL;
175 }
176
177 if (!cfgutil_WindowsServiceStart
178 (AFSREG_SVR_SVC_NAME, auxArgc, auxArgv, timeout, &wasRunning,
179 &tst2)) {
180 /* failed to start BOS control service */
181 tst = tst2;
182 }
183 }
184 #else
185 if (tst == 0) {
186 /* function not yet implemented for Unix */
187 tst = ADMCFGNOTSUPPORTED;
188 }
189 #endif /* AFS_NT40_ENV */
190
191 /* put bosserver into requested auth mode if was already running */
192
193 if (tst == 0 && wasRunning) {
194 if (!cfgutil_HostSetNoAuthFlag(cfg_host, noAuth, &tst2)) {
195 tst = tst2;
196 }
197 }
198
199 if (tst != 0) {
200 /* indicate failure */
201 rc = 0;
202 }
203 if (st != NULL) {
204 *st = tst;
205 }
206 return rc;
207 }
208
209
210
211 /*
212 * cfg_BosServerStop() -- Stop the BOS server on host.
213 *
214 * Timeout is the maximum time, in seconds, to wait for BOS to stop.
215 */
216 int ADMINAPI
217 cfg_BosServerStop(void *hostHandle, /* host config handle */
218 unsigned int timeout, /* timeout (in seconds) */
219 afs_status_p st)
220 { /* completion status */
221 int rc = 1;
222 afs_status_t tst2, tst = 0;
223 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
224
225 /* validate parameters */
226
227 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
228 tst = tst2;
229 }
230
231 /* remote configuration not yet supported in this function */
232
233 if (tst == 0) {
234 if (!cfg_host->is_local) {
235 tst = ADMCFGNOTSUPPORTED;
236 }
237 }
238
239 /* stop the bosserver (if running) */
240
241 #ifdef AFS_NT40_ENV
242 /* Windows - bosserver is controlled via the BOS control service */
243 if (tst == 0) {
244 short wasStopped;
245
246 if (!cfgutil_WindowsServiceStop
247 (AFSREG_SVR_SVC_NAME, timeout, &wasStopped, &tst2)) {
248 /* failed to stop BOS control service */
249 tst = tst2;
250 }
251 }
252 #else
253 if (tst == 0) {
254 /* function not yet implemented for Unix */
255 tst = ADMCFGNOTSUPPORTED;
256 }
257 #endif /* AFS_NT40_ENV */
258
259 if (tst != 0) {
260 /* indicate failure */
261 rc = 0;
262 }
263 if (st != NULL) {
264 *st = tst;
265 }
266 return rc;
267 }
268
269
270 /*
271 * cfg_BosServerQueryStatus() -- Query status of BOS server on host.
272 *
273 * The argument *isBosProcP is set to TRUE only if BOS processes
274 * are currently executing (as opposed to configured but stopped).
275 */
276 int ADMINAPI
277 cfg_BosServerQueryStatus(void *hostHandle, /* host config handle */
278 short *isStartedP, /* BOS server is started */
279 short *isBosProcP, /* BOS processes running */
280 afs_status_p st)
281 { /* completion status */
282 int rc = 1;
283 afs_status_t tst2, tst = 0;
284 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
285
286 /* validate parameters and prepare host handle for bos functions */
287
288 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
289 tst = tst2;
290 } else if (isStartedP == NULL) {
291 tst = ADMCFGSTARTEDFLAGPNULL;
292 } else if (isBosProcP == NULL) {
293 tst = ADMCFGBOSSERVERPROCSFLAGPNULL;
294 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
295 tst = tst2;
296 }
297
298 /* remote configuration not yet supported in this function */
299
300 if (tst == 0) {
301 if (!cfg_host->is_local) {
302 tst = ADMCFGNOTSUPPORTED;
303 }
304 }
305
306 /* determine if bosserver is running */
307
308 #ifdef AFS_NT40_ENV
309 /* Windows - bosserver is controlled via the BOS control service */
310 if (tst == 0) {
311 DWORD svcState;
312
313 *isStartedP = *isBosProcP = 0;
314
315 if (!cfgutil_WindowsServiceQuery
316 (AFSREG_SVR_SVC_NAME, &svcState, &tst2)) {
317 tst = tst2;
318 } else if (svcState == SERVICE_RUNNING) {
319 *isStartedP = 1;
320 }
321 }
322 #else
323 if (tst == 0) {
324 /* function not yet implemented for Unix */
325 tst = ADMCFGNOTSUPPORTED;
326 }
327 #endif /* AFS_NT40_ENV */
328
329
330 /* query status of bos processes */
331
332 if (tst == 0 && *isStartedP) {
333 void *procIter;
334
335 *isBosProcP = 0;
336
337 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
338 tst = tst2;
339 } else {
340 /* iterate over process names, checking status of each */
341 char procName[BOS_MAX_NAME_LEN];
342 bos_ProcessExecutionState_t procState;
343 char procAuxState[BOS_MAX_NAME_LEN];
344 int procDone = 0;
345
346 while (!procDone) {
347 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
348 /* no more processes (or failure) */
349 if (tst2 != ADMITERATORDONE) {
350 tst = tst2;
351 }
352 procDone = 1;
353
354 } else
355 if (!bos_ProcessExecutionStateGet
356 (cfg_host->bosHandle, procName, &procState,
357 procAuxState, &tst2)) {
358 /* process removed (or failure) */
359 if (tst2 != BZNOENT) {
360 tst = tst2;
361 procDone = 1;
362 }
363
364 } else {
365 if (procState != BOS_PROCESS_STOPPED) {
366 *isBosProcP = 1;
367 procDone = 1;
368 }
369 }
370 }
371
372 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
373 tst = tst2;
374 }
375 }
376 }
377
378 if (tst != 0) {
379 /* indicate failure */
380 rc = 0;
381 }
382 if (st != NULL) {
383 *st = tst;
384 }
385 return rc;
386 }
387
388
389
390
391 /* ---------------- Exported Database Server functions ------------------ */
392
393
394
395 /*
396 * cfg_AuthServerStart() -- Start authentication server on host and wait
397 * for server to be ready to accept requests.
398 *
399 * This function is intended to be used when configuring the first
400 * machine in a cell; it enables the AFS server principal to be created
401 * and configured before starting the remaining database servers.
402 */
403 int ADMINAPI
404 cfg_AuthServerStart(void *hostHandle, /* host config handle */
405 afs_status_p st)
406 { /* completion status */
407 int rc = 1;
408 afs_status_t tst2, tst = 0;
409 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
410
411 /* validate parameters and prepare host handle for bos functions */
412
413 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
414 tst = tst2;
415 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
416 tst = tst2;
417 }
418
419 /* create and start authentication server instance */
420
421 if (tst == 0) {
422 if (!SimpleProcessStart
423 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
424 &tst2)) {
425 tst = tst2;
426 }
427 }
428
429 /* wait for authentication server to achieve quorum */
430
431 if (tst == 0) {
432 time_t timeStart = time(NULL);
433 short kaHasQuorum;
434
435 while (1) {
436 if (!UbikQuorumCheck
437 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
438 tst = tst2;
439 break;
440
441 } else if (kaHasQuorum) {
442 /* quorum on authentication server */
443 break;
444
445 } else {
446 /* quorum not yet achieved on authentication server */
447 if (difftime(time(NULL), timeStart) > 180) {
448 tst = ADMCFGQUORUMWAITTIMEOUT;
449 break;
450 } else {
451 cfgutil_Sleep(2);
452 }
453 }
454 }
455 }
456
457 if (tst != 0) {
458 /* indicate failure */
459 rc = 0;
460 }
461 if (st != NULL) {
462 *st = tst;
463 }
464 return rc;
465 }
466
467
468 /*
469 * cfg_DbServersStart() -- Start the standard (required) database servers,
470 * and optionally the backup database server, on host.
471 *
472 * The BOS instance names used are the string constants:
473 * cfg_kaserverBosName - authentication server
474 * cfg_ptserverBosName - protection server
475 * cfg_vlserverBosName - volume location server
476 * cfg_buserverBosName - backup server
477 */
478 int ADMINAPI
479 cfg_DbServersStart(void *hostHandle, /* host config handle */
480 short startBkDb, /* start backup server */
481 afs_status_p st)
482 { /* completion status */
483 int rc = 1;
484 afs_status_t tst2, tst = 0;
485 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
486
487 /* validate parameters and prepare host handle for bos functions */
488
489 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
490 tst = tst2;
491 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
492 tst = tst2;
493 }
494
495 /* create and start database server instances */
496
497 if (tst == 0) {
498 /* try all regardless of failures; last error code wins */
499 if (!SimpleProcessStart
500 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
501 &tst2)) {
502 tst = tst2;
503 }
504 if (!SimpleProcessStart
505 (cfg_host->bosHandle, PTSERVER_BOSNAME, PTSERVER_EXEPATH, NULL,
506 &tst2)) {
507 tst = tst2;
508 }
509 if (!SimpleProcessStart
510 (cfg_host->bosHandle, VLSERVER_BOSNAME, VLSERVER_EXEPATH, NULL,
511 &tst2)) {
512 tst = tst2;
513 }
514 if (startBkDb
515 && !SimpleProcessStart(cfg_host->bosHandle, BUSERVER_BOSNAME,
516 BUSERVER_EXEPATH, NULL, &tst2)) {
517 tst = tst2;
518 }
519 }
520
521 if (tst != 0) {
522 /* indicate failure */
523 rc = 0;
524 }
525 if (st != NULL) {
526 *st = tst;
527 }
528 return rc;
529 }
530
531
532 /*
533 * cfg_DbServersStop() -- Stop, and unconfigure, the database servers on host.
534 */
535 int ADMINAPI
536 cfg_DbServersStop(void *hostHandle, /* host config handle */
537 afs_status_p st)
538 { /* completion status */
539 int rc = 1;
540 afs_status_t tst2, tst = 0;
541 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
542
543 /* validate parameters and prepare host handle for bos functions */
544
545 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
546 tst = tst2;
547 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
548 tst = tst2;
549 }
550
551 /* stop and delete database server instances */
552
553 if (tst == 0) {
554 /* try all regardless of failures; last error code wins */
555 if (!BosProcessDelete(cfg_host->bosHandle, KASERVER_BOSNAME, &tst2)) {
556 tst = tst2;
557 }
558 if (!BosProcessDelete(cfg_host->bosHandle, PTSERVER_BOSNAME, &tst2)) {
559 tst = tst2;
560 }
561 if (!BosProcessDelete(cfg_host->bosHandle, VLSERVER_BOSNAME, &tst2)) {
562 tst = tst2;
563 }
564 if (!BosProcessDelete(cfg_host->bosHandle, BUSERVER_BOSNAME, &tst2)) {
565 tst = tst2;
566 }
567 }
568
569 if (tst != 0) {
570 /* indicate failure */
571 rc = 0;
572 }
573 if (st != NULL) {
574 *st = tst;
575 }
576 return rc;
577 }
578
579
580 /*
581 * cfg_DbServersQueryStatus() -- Query status of database servers on host.
582 *
583 * If detailed status information is not required, detailsP can be NULL.
584 *
585 * If *isStdDbP is FALSE and *isBkDbP is TRUE then the host is in an
586 * inconsistent state; the remaining database servers should be configured.
587 */
588 int ADMINAPI
589 cfg_DbServersQueryStatus(void *hostHandle, /* host config handle */
590 short *isStdDbP, /* std DB servers configured */
591 short *isBkDbP, /* backup DB server configured */
592 cfg_dbServersStatus_t * detailsP, /* config details */
593 afs_status_p st)
594 { /* completion status */
595 int rc = 1;
596 afs_status_t tst2, tst = 0;
597 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
598 short inCellServDb, isKaserver, isPtserver, isVlserver, isBuserver;
599
600 inCellServDb = isKaserver = isPtserver = isVlserver = isBuserver = 0;
601
602 /* validate parameters and prepare host handle for bos functions */
603
604 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
605 tst = tst2;
606 } else if (isStdDbP == NULL || isBkDbP == NULL) {
607 tst = ADMCFGDBSERVERCONFIGFLAGPNULL;
608 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
609 tst = tst2;
610 }
611
612 /* query host's server CellServDb to see if it lists itself */
613
614 if (tst == 0) {
615 char hostNameAlias[MAXHOSTCHARS];
616
617 if (!cfgutil_HostNameGetCellServDbAlias
618 (cfg_host->hostName, cfg_host->hostName, hostNameAlias, &tst2)) {
619 tst = tst2;
620 } else if (*hostNameAlias != '\0') {
621 /* host in its own CellServDb */
622 inCellServDb = 1;
623 }
624 }
625
626 /* query bosserver to determine what database servers are configured */
627
628 if (tst == 0) {
629 bos_ProcessType_t procType;
630 bos_ProcessInfo_t procInfo;
631
632 if (bos_ProcessInfoGet
633 (cfg_host->bosHandle, KASERVER_BOSNAME, &procType, &procInfo,
634 &tst2)) {
635 isKaserver = 1;
636 } else if (tst2 != BZNOENT) {
637 tst = tst2;
638 }
639
640 if (tst == 0) {
641 if (bos_ProcessInfoGet
642 (cfg_host->bosHandle, PTSERVER_BOSNAME, &procType, &procInfo,
643 &tst2)) {
644 isPtserver = 1;
645 } else if (tst2 != BZNOENT) {
646 tst = tst2;
647 }
648 }
649
650 if (tst == 0) {
651 if (bos_ProcessInfoGet
652 (cfg_host->bosHandle, VLSERVER_BOSNAME, &procType, &procInfo,
653 &tst2)) {
654 isVlserver = 1;
655 } else if (tst2 != BZNOENT) {
656 tst = tst2;
657 }
658 }
659
660 if (tst == 0) {
661 if (bos_ProcessInfoGet
662 (cfg_host->bosHandle, BUSERVER_BOSNAME, &procType, &procInfo,
663 &tst2)) {
664 isBuserver = 1;
665 } else if (tst2 != BZNOENT) {
666 tst = tst2;
667 }
668 }
669 }
670
671 if (tst == 0) {
672 /* success; return results */
673 *isStdDbP = (inCellServDb && isKaserver && isPtserver && isVlserver);
674 *isBkDbP = (inCellServDb && isBuserver);
675
676 if (detailsP) {
677 detailsP->inCellServDb = inCellServDb;
678 detailsP->isKaserver = isKaserver;
679 detailsP->isPtserver = isPtserver;
680 detailsP->isVlserver = isVlserver;
681 detailsP->isBuserver = isBuserver;
682 }
683 } else {
684 /* indicate failure */
685 rc = 0;
686 }
687 if (st != NULL) {
688 *st = tst;
689 }
690 return rc;
691 }
692
693
694 /*
695 * cfg_DbServersRestartAll() -- Restart all database servers in host's cell.
696 */
697 int ADMINAPI
698 cfg_DbServersRestartAll(void *hostHandle, /* host config handle */
699 afs_status_p st)
700 { /* completion status */
701 int rc = 1;
702 afs_status_t tst2, tst = 0;
703 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
704
705 /* validate parameters and prepare host handle for bos functions */
706
707 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
708 tst = tst2;
709 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
710 tst = tst2;
711 }
712
713 /* restart all database servers in host's cell */
714
715 if (tst == 0) {
716 void *dbIter;
717
718 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
719 tst = tst2;
720 } else {
721 /* iterate over server CellServDb, restarting db servers */
722 char dbhostName[BOS_MAX_NAME_LEN];
723 void *dbhostHandle;
724 int dbhostDone = 0;
725
726 while (!dbhostDone) {
727 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
728 /* no more entries (or failure) */
729 if (tst2 != ADMITERATORDONE) {
730 tst = tst2;
731 }
732 dbhostDone = 1;
733
734 } else
735 if (!bos_ServerOpen
736 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
737 &tst2)) {
738 /* failed to get bos handle; note error but keep going */
739 tst = tst2;
740
741 } else {
742 /* restart db servers; note errors, but keep going */
743 if (!bos_ProcessRestart
744 (dbhostHandle, KASERVER_BOSNAME, &tst2)) {
745 tst = tst2;
746 }
747 if (!bos_ProcessRestart
748 (dbhostHandle, PTSERVER_BOSNAME, &tst2)) {
749 tst = tst2;
750 }
751 if (!bos_ProcessRestart
752 (dbhostHandle, VLSERVER_BOSNAME, &tst2)) {
753 tst = tst2;
754 }
755 if (!bos_ProcessRestart
756 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
757 /* may not be running a backup server */
758 if (tst2 != BZNOENT) {
759 tst = tst2;
760 }
761 }
762
763 if (!bos_ServerClose(dbhostHandle, &tst2)) {
764 tst = tst2;
765 }
766 }
767 }
768
769 if (!bos_HostGetDone(dbIter, &tst2)) {
770 tst = tst2;
771 }
772 }
773 }
774
775 if (tst != 0) {
776 /* indicate failure */
777 rc = 0;
778
779 /* should really utilize a callback (or some other mechanism) to
780 * indicate which restarts failed and why.
781 */
782 }
783 if (st != NULL) {
784 *st = tst;
785 }
786 return rc;
787 }
788
789
790 /*
791 * cfg_DbServersWaitForQuorum() -- Wait for database servers in host's cell
792 * to achieve quorum.
793 *
794 * Timeout is the maximum time, in seconds, to wait for quorum.
795 *
796 * NOTE: Function does not check for backup server quorum since
797 * configuration does not require modifying the backup database.
798 */
799 int ADMINAPI
800 cfg_DbServersWaitForQuorum(void *hostHandle, /* host config handle */
801 unsigned int timeout, /* timeout in sec. */
802 afs_status_p st)
803 { /* completion status */
804 int rc = 1;
805 afs_status_t tst2, tst = 0;
806 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
807
808 /* validate parameters and prepare host handle for bos functions */
809
810 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
811 tst = tst2;
812 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
813 tst = tst2;
814 }
815
816 /* wait for the database servers in host's cell to achieve quorum */
817
818 if (tst == 0) {
819 time_t timeStart = time(NULL);
820 short kaHasQuorum, ptHasQuorum, vlHasQuorum;
821
822 kaHasQuorum = ptHasQuorum = vlHasQuorum = 0;
823
824 while (1) {
825 if (!kaHasQuorum) {
826 if (!UbikQuorumCheck
827 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
828 tst = tst2;
829 break;
830 }
831 }
832
833 if (!ptHasQuorum) {
834 if (!UbikQuorumCheck
835 (cfg_host, PTSERVER_BOSNAME, &ptHasQuorum, &tst2)) {
836 tst = tst2;
837 break;
838 }
839 }
840
841 if (!vlHasQuorum) {
842 if (!UbikQuorumCheck
843 (cfg_host, VLSERVER_BOSNAME, &vlHasQuorum, &tst2)) {
844 tst = tst2;
845 break;
846 }
847 }
848
849 if (kaHasQuorum && ptHasQuorum && vlHasQuorum) {
850 /* quorum on all dbservers of interest */
851 break;
852 } else {
853 /* quorum not yet achieved for one or more dbservers */
854 if ((timeout == 0)
855 || (difftime(time(NULL), timeStart) > timeout)) {
856 tst = ADMCFGQUORUMWAITTIMEOUT;
857 break;
858 } else {
859 cfgutil_Sleep(10);
860 }
861 }
862 }
863 }
864
865 if (tst != 0) {
866 /* indicate failure */
867 rc = 0;
868 }
869 if (st != NULL) {
870 *st = tst;
871 }
872 return rc;
873 }
874
875
876
877 /*
878 * cfg_DbServersStopAllBackup() -- Stop, and unconfigure, all backup servers
879 * in host's cell.
880 */
881 int ADMINAPI
882 cfg_DbServersStopAllBackup(void *hostHandle, /* host config handle */
883 afs_status_p st)
884 { /* completion status */
885 int rc = 1;
886 afs_status_t tst2, tst = 0;
887 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
888
889 /* validate parameters and prepare host handle for bos functions */
890
891 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
892 tst = tst2;
893 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
894 tst = tst2;
895 }
896
897 /* stop and delete all backup servers in host's cell */
898
899 if (tst == 0) {
900 void *dbIter;
901
902 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
903 tst = tst2;
904 } else {
905 /* iterate over server CellServDb, unconfiguring backup servers */
906 char dbhostName[BOS_MAX_NAME_LEN];
907 void *dbhostHandle;
908 int dbhostDone = 0;
909
910 while (!dbhostDone) {
911 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
912 /* no more entries (or failure) */
913 if (tst2 != ADMITERATORDONE) {
914 tst = tst2;
915 }
916 dbhostDone = 1;
917
918 } else
919 if (!bos_ServerOpen
920 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
921 &tst2)) {
922 /* failed to get bos handle; note error but keep going */
923 tst = tst2;
924
925 } else {
926 /* unconfig backup server; note errors, but keep going */
927 if (!BosProcessDelete
928 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
929 tst = tst2;
930 }
931
932 if (!bos_ServerClose(dbhostHandle, &tst2)) {
933 tst = tst2;
934 }
935 }
936 }
937
938 if (!bos_HostGetDone(dbIter, &tst2)) {
939 tst = tst2;
940 }
941 }
942 }
943
944 if (tst != 0) {
945 /* indicate failure */
946 rc = 0;
947
948 /* should really utilize a callback (or some other mechanism) to
949 * indicate which stops failed and why.
950 */
951 }
952 if (st != NULL) {
953 *st = tst;
954 }
955 return rc;
956 }
957
958
959
960
961
962 /* ---------------- Exported File Server functions ------------------ */
963
964
965 /*
966 * cfg_FileServerStart() -- Start the file server on host.
967 *
968 * The BOS instance name used is the string constant cfg_fileserverBosName.
969 */
970 int ADMINAPI
971 cfg_FileServerStart(void *hostHandle, /* host config handle */
972 afs_status_p st)
973 { /* completion status */
974 int rc = 1;
975 afs_status_t tst2, tst = 0;
976 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
977
978 /* validate parameters and prepare host handle for bos functions */
979
980 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
981 tst = tst2;
982 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
983 tst = tst2;
984 }
985
986 /* create and start file server instance */
987
988 if (tst == 0) {
989 if (!FsProcessStart
990 (cfg_host->bosHandle, FILESERVER_BOSNAME, FILESERVER_EXEPATH,
991 VOLSERVER_EXEPATH, SALVAGER_EXEPATH, &tst2)) {
992 tst = tst2;
993 } else {
994 /* TO BE DONE: need a reliable "is started and ready" check */
995 cfgutil_Sleep(5);
996 }
997 }
998
999 if (tst != 0) {
1000 /* indicate failure */
1001 rc = 0;
1002 }
1003 if (st != NULL) {
1004 *st = tst;
1005 }
1006 return rc;
1007 }
1008
1009
1010 /*
1011 * cfg_FileServerStop() -- Stop, and unconfigure, the file server on host.
1012 */
1013 int ADMINAPI
1014 cfg_FileServerStop(void *hostHandle, /* host config handle */
1015 afs_status_p st)
1016 { /* completion status */
1017 int rc = 1;
1018 afs_status_t tst2, tst = 0;
1019 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1020
1021 /* validate parameters and prepare host handle for bos functions */
1022
1023 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1024 tst = tst2;
1025 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1026 tst = tst2;
1027 }
1028
1029 /* stop and delete file server instance */
1030
1031 if (tst == 0) {
1032 if (!BosProcessDelete(cfg_host->bosHandle, FILESERVER_BOSNAME, &tst2)) {
1033 tst = tst2;
1034 } else {
1035 /* file server instance deleted; remove its addresses from VLDB */
1036 int addrCount, i;
1037 afs_int32 *addrList = NULL;
1038
1039 /* note: ignore any errors since address removal is optional;
1040 * e.g., a common source of errors will be attempting to remove
1041 * an address while volumes tied to that address are still listed
1042 * in the VLDB (in which case the address is not removed).
1043 */
1044 if (cfgutil_HostAddressFetchAll
1045 (cfg_host->hostName, &addrCount, &addrList, &tst2)) {
1046 for (i = 0; i < addrCount; i++) {
1047 (void)vos_FileServerAddressRemove(cfg_host->cellHandle,
1048 NULL, addrList[i],
1049 &tst2);
1050 }
1051 if (addrList) {
1052 free(addrList);
1053 addrList = NULL;
1054 }
1055 }
1056 }
1057 }
1058
1059 if (tst != 0) {
1060 /* indicate failure */
1061 rc = 0;
1062 }
1063 if (st != NULL) {
1064 *st = tst;
1065 }
1066 return rc;
1067 }
1068
1069
1070 /*
1071 * cfg_FileServerQueryStatus() -- Query status of file server on host.
1072 */
1073 int ADMINAPI
1074 cfg_FileServerQueryStatus(void *hostHandle, /* host config handle */
1075 short *isFsP, /* file server configured */
1076 afs_status_p st)
1077 { /* completion status */
1078 int rc = 1;
1079 afs_status_t tst2, tst = 0;
1080 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1081
1082 /* validate parameters and prepare host handle for bos functions */
1083
1084 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1085 tst = tst2;
1086 } else if (isFsP == NULL) {
1087 tst = ADMCFGFILESERVERCONFIGFLAGPNULL;
1088 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1089 tst = tst2;
1090 }
1091
1092 /* query bosserver to determine if fileserver is configured */
1093
1094 if (tst == 0) {
1095 bos_ProcessType_t procType;
1096 bos_ProcessInfo_t procInfo;
1097
1098 *isFsP = 0;
1099
1100 if (bos_ProcessInfoGet
1101 (cfg_host->bosHandle, FILESERVER_BOSNAME, &procType, &procInfo,
1102 &tst2)) {
1103 /* instance exists; check type for good measure */
1104 if (procType == BOS_PROCESS_FS) {
1105 *isFsP = 1;
1106 }
1107 } else if (tst2 != BZNOENT) {
1108 tst = tst2;
1109 }
1110 }
1111
1112 if (tst != 0) {
1113 /* indicate failure */
1114 rc = 0;
1115 }
1116 if (st != NULL) {
1117 *st = tst;
1118 }
1119 return rc;
1120 }
1121
1122
1123
1124
1125 /* ---------------- Exported Update Server functions ------------------ */
1126
1127
1128
1129 /*
1130 * cfg_UpdateServerStart() -- Start the Update server on host.
1131 *
1132 * Argument strings exportClear and exportCrypt each specify a set of
1133 * space-separated directories to export or are NULL.
1134 *
1135 * The BOS instance name used is the string constant cfg_upserverBosName.
1136 */
1137 int ADMINAPI
1138 cfg_UpdateServerStart(void *hostHandle, /* host config handle */
1139 const char *exportClear, /* dirs to export in clear */
1140 const char *exportCrypt, /* dirs to export encrypted */
1141 afs_status_p st)
1142 { /* completion status */
1143 int rc = 1;
1144 afs_status_t tst2, tst = 0;
1145 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1146
1147 /* validate parameters and prepare host handle for bos functions */
1148
1149 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1150 tst = tst2;
1151 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1152 tst = tst2;
1153 }
1154
1155 /* stop and delete existing update server instance, if any.
1156 * we do this because the set of exported directores might be changing.
1157 */
1158
1159 if (tst == 0) {
1160 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1161 tst = tst2;
1162 }
1163 }
1164
1165 /* create and start update server instance */
1166
1167 if (tst == 0) {
1168 char *args = NULL;
1169 int r;
1170
1171 if (exportClear != NULL && *exportClear != '\0') {
1172 if (exportCrypt != NULL && *exportCrypt != '\0') {
1173 r = asprintf(&args, "-clear %s -crypt %s",
1174 exportClear, exportCrypt);
1175 } else {
1176 r = asprintf(&args, "-clear %s", exportClear);
1177 }
1178 } else {
1179 if (exportCrypt != NULL && *exportCrypt != '\0') {
1180 r = asprintf(&args, "-crypt %s", exportCrypt);
1181 } else {
1182 args = NULL;
1183 r = 0;
1184 }
1185 }
1186 if (r < 0) {
1187 tst = ADMNOMEM;
1188 args = NULL;
1189 }
1190
1191 if (tst == 0) {
1192 if (!SimpleProcessStart
1193 (cfg_host->bosHandle, UPSERVER_BOSNAME, UPSERVER_EXEPATH,
1194 args, &tst2)) {
1195 tst = tst2;
1196 }
1197 }
1198 free(args);
1199 }
1200
1201 if (tst != 0) {
1202 /* indicate failure */
1203 rc = 0;
1204 }
1205 if (st != NULL) {
1206 *st = tst;
1207 }
1208 return rc;
1209 }
1210
1211
1212 /*
1213 * cfg_UpdateServerStop() -- Stop, and unconfigure, the Update server on host.
1214 */
1215 int ADMINAPI
1216 cfg_UpdateServerStop(void *hostHandle, /* host config handle */
1217 afs_status_p st)
1218 { /* completion status */
1219 int rc = 1;
1220 afs_status_t tst2, tst = 0;
1221 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1222
1223 /* validate parameters and prepare host handle for bos functions */
1224
1225 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1226 tst = tst2;
1227 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1228 tst = tst2;
1229 }
1230
1231 /* stop and delete upserver instance */
1232
1233 if (tst == 0) {
1234 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1235 tst = tst2;
1236 }
1237 }
1238
1239 if (tst != 0) {
1240 /* indicate failure */
1241 rc = 0;
1242 }
1243 if (st != NULL) {
1244 *st = tst;
1245 }
1246 return rc;
1247 }
1248
1249
1250 /*
1251 * cfg_UpdateServerQueryStatus() -- Query status of Update server on host.
1252 */
1253 int ADMINAPI
1254 cfg_UpdateServerQueryStatus(void *hostHandle, /* host config handle */
1255 short *isUpserverP, /* update server configured */
1256 short *isSysCtrlP, /* system control configured */
1257 short *isBinDistP, /* binary dist configured */
1258 afs_status_p st)
1259 { /* completion status */
1260 int rc = 1;
1261 afs_status_t tst2, tst = 0;
1262 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1263
1264 /* validate parameters and prepare host handle for bos functions */
1265
1266 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1267 tst = tst2;
1268 } else if (isUpserverP == NULL || isSysCtrlP == NULL
1269 || isBinDistP == NULL) {
1270 tst = ADMCFGUPSERVERCONFIGFLAGPNULL;
1271 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1272 tst = tst2;
1273 }
1274
1275 /* query bosserver to determine if, and how, upserver is configured */
1276
1277 if (tst == 0) {
1278 void *cmdIter;
1279
1280 *isUpserverP = *isSysCtrlP = *isBinDistP = 0;
1281
1282 if (!bos_ProcessParameterGetBegin
1283 (cfg_host->bosHandle, UPSERVER_BOSNAME, &cmdIter, &tst2)) {
1284 tst = tst2;
1285 } else {
1286 char cmdString[BOS_MAX_NAME_LEN];
1287
1288 if (!bos_ProcessParameterGetNext(cmdIter, cmdString, &tst2)) {
1289 /* no upserver instance (or error) */
1290 if (tst2 != BZNOENT) {
1291 tst = tst2;
1292 }
1293 } else {
1294 /* parse upserver command line to determine how configured */
1295 short hasSysPath, hasBinPath;
1296
1297 UpdateCommandParse(cmdString, &hasSysPath, &hasBinPath);
1298
1299 *isUpserverP = 1;
1300
1301 if (hasSysPath) {
1302 *isSysCtrlP = 1;
1303 }
1304 if (hasBinPath) {
1305 *isBinDistP = 1;
1306 }
1307 }
1308
1309 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1310 tst = tst2;
1311 }
1312 }
1313 }
1314
1315 if (tst != 0) {
1316 /* indicate failure */
1317 rc = 0;
1318 }
1319 if (st != NULL) {
1320 *st = tst;
1321 }
1322 return rc;
1323 }
1324
1325
1326 /*
1327 * cfg_SysBinServerStart() -- Start Update server in System Control and/or
1328 * Binary Distribution machine configuration on host.
1329 *
1330 * This function is a convenience wrapper for cfg_UpdateServerStart().
1331 */
1332 int ADMINAPI
1333 cfg_SysBinServerStart(void *hostHandle, /* host config handle */
1334 short makeSysCtrl, /* config as sys control mach */
1335 short makeBinDist, /* config as binary dist mach */
1336 afs_status_p st)
1337 { /* completion status */
1338 char *cryptSysDir = NULL;
1339 char *clearBinDir = NULL;
1340
1341 if (makeSysCtrl) {
1342 cryptSysDir = AFSDIR_CANONICAL_SERVER_ETC_DIRPATH;
1343 }
1344
1345 if (makeBinDist) {
1346 clearBinDir = AFSDIR_CANONICAL_SERVER_BIN_DIRPATH;
1347 }
1348
1349 return cfg_UpdateServerStart(hostHandle, clearBinDir, cryptSysDir, st);
1350 }
1351
1352
1353
1354 /* ---------------- Exported Update Client functions ------------------ */
1355
1356
1357
1358 /*
1359 * cfg_UpdateClientStart() -- Start an Update client on host.
1360 *
1361 * Argument string import specifies a set of space-separated directories
1362 * to import. Argument frequency specifies the import interval in
1363 * seconds; if the value is zero (0) then the default frequency is used.
1364 *
1365 * The BOS instance name used is the concatenation of the string constant
1366 * cfg_upclientBosNamePrefix and the argument string bosSuffix.
1367 */
1368 int ADMINAPI
1369 cfg_UpdateClientStart(void *hostHandle, /* host config handle */
1370 const char *bosSuffix, /* BOS instance suffix */
1371 const char *upserver, /* upserver to import from */
1372 short crypt, /* import encrypted */
1373 const char *import, /* dirs to import */
1374 unsigned int frequency, /* import interval in sec. */
1375 afs_status_p st)
1376 { /* completion status */
1377 int rc = 1;
1378 afs_status_t tst2, tst = 0;
1379 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1380 char upclientInstance[BOS_MAX_NAME_LEN];
1381
1382 /* validate parameters and prepare host handle for bos functions */
1383
1384 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1385 tst = tst2;
1386 } else if (bosSuffix == NULL) {
1387 tst = ADMCFGUPCLIENTSUFFIXNULL;
1388 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1389 BOS_MAX_NAME_LEN) {
1390 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1391 } else if (upserver == NULL || *upserver == '\0') {
1392 tst = ADMCFGUPCLIENTTARGETSERVERNULL;
1393 } else if (import == NULL || *import == '\0') {
1394 tst = ADMCFGUPCLIENTIMPORTDIRNULL;
1395 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1396 tst = tst2;
1397 }
1398
1399 /* stop and delete existing update client instance, if any.
1400 * we do this because the set of imported directores might be changing.
1401 */
1402
1403 if (tst == 0) {
1404 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1405
1406 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1407 tst = tst2;
1408 }
1409 }
1410
1411 /* create and start update client instance */
1412
1413 if (tst == 0) {
1414 char *args = NULL;
1415 int r;
1416
1417 if (frequency != 0)
1418 r = asprintf(&args, "%s %s -t %u %s", upserver,
1419 crypt ? "-crypt" : "-clear", frequency, import);
1420 else
1421 r = asprintf(&args, "%s %s %s", upserver,
1422 crypt ? "-crypt" : "-clear", import);
1423
1424 if (r < 0) {
1425 tst = ADMNOMEM;
1426 args = NULL;
1427 } else {
1428 /* create and start instance */
1429 if (!SimpleProcessStart
1430 (cfg_host->bosHandle, upclientInstance, UPCLIENT_EXEPATH,
1431 args, &tst2)) {
1432 tst = tst2;
1433 }
1434 }
1435 free(args);
1436 }
1437
1438 if (tst != 0) {
1439 /* indicate failure */
1440 rc = 0;
1441 }
1442 if (st != NULL) {
1443 *st = tst;
1444 }
1445 return rc;
1446 }
1447
1448
1449 /*
1450 * cfg_UpdateClientStop() -- Stop, and unconfigure, an Update client on host.
1451 */
1452 int ADMINAPI
1453 cfg_UpdateClientStop(void *hostHandle, /* host config handle */
1454 const char *bosSuffix, /* BOS instance suffix */
1455 afs_status_p st)
1456 { /* completion status */
1457 int rc = 1;
1458 afs_status_t tst2, tst = 0;
1459 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1460 char upclientInstance[BOS_MAX_NAME_LEN];
1461
1462 /* validate parameters and prepare host handle for bos functions */
1463
1464 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1465 tst = tst2;
1466 } else if (bosSuffix == NULL) {
1467 tst = ADMCFGUPCLIENTSUFFIXNULL;
1468 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1469 BOS_MAX_NAME_LEN) {
1470 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1471 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1472 tst = tst2;
1473 }
1474
1475 /* stop and delete specified update client instance */
1476
1477 if (tst == 0) {
1478 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1479
1480 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1481 tst = tst2;
1482 }
1483 }
1484
1485 if (tst != 0) {
1486 /* indicate failure */
1487 rc = 0;
1488 }
1489 if (st != NULL) {
1490 *st = tst;
1491 }
1492 return rc;
1493 }
1494
1495
1496 /*
1497 * cfg_UpdateClientStopAll() -- Stop, and unconfigure, all Update clients
1498 * on host.
1499 */
1500 int ADMINAPI
1501 cfg_UpdateClientStopAll(void *hostHandle, /* host config handle */
1502 afs_status_p st)
1503 { /* completion status */
1504 int rc = 1;
1505 afs_status_t tst2, tst = 0;
1506 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1507
1508 /* validate parameters and prepare host handle for bos functions */
1509
1510 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1511 tst = tst2;
1512 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1513 tst = tst2;
1514 }
1515
1516 /* find, stop, and delete all update client instances */
1517
1518 if (tst == 0) {
1519 void *procIter;
1520
1521 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1522 tst = tst2;
1523 } else {
1524 /* iterate over process names, looking for update clients */
1525 char procName[BOS_MAX_NAME_LEN];
1526 int procDone = 0;
1527
1528 while (!procDone) {
1529 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1530 /* no more processes (or failure) */
1531 if (tst2 != ADMITERATORDONE) {
1532 tst = tst2;
1533 }
1534 procDone = 1;
1535
1536 } else
1537 if (!strncmp
1538 (UPCLIENT_BOSNAME, procName,
1539 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1540 /* upclient instance prefix; assume is upclient */
1541 if (!BosProcessDelete
1542 (cfg_host->bosHandle, procName, &tst2)) {
1543 tst = tst2;
1544 procDone = 1;
1545 }
1546 }
1547 }
1548
1549 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1550 tst = tst2;
1551 }
1552 }
1553 }
1554
1555 if (tst != 0) {
1556 /* indicate failure */
1557 rc = 0;
1558 }
1559 if (st != NULL) {
1560 *st = tst;
1561 }
1562 return rc;
1563 }
1564
1565
1566 /*
1567 * cfg_UpdateClientQueryStatus() -- Query status of Update clients on host.
1568 */
1569 int ADMINAPI
1570 cfg_UpdateClientQueryStatus(void *hostHandle, /* host config handle */
1571 short *isUpclientP, /* an upclient is configured */
1572 short *isSysP, /* system control client */
1573 short *isBinP, /* binary dist. client */
1574 afs_status_p st)
1575 { /* completion status */
1576 int rc = 1;
1577 afs_status_t tst2, tst = 0;
1578 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1579
1580 /* validate parameters and prepare host handle for bos functions */
1581
1582 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1583 tst = tst2;
1584 } else if (isUpclientP == NULL || isSysP == NULL || isBinP == NULL) {
1585 tst = ADMCFGUPCLIENTCONFIGFLAGPNULL;
1586 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1587 tst = tst2;
1588 }
1589
1590 /* determine if, and how, any upclients are configured */
1591
1592 if (tst == 0) {
1593 void *procIter;
1594
1595 *isUpclientP = *isSysP = *isBinP = 0;
1596
1597 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1598 tst = tst2;
1599 } else {
1600 /* iterate over process names, looking for update clients */
1601 char procName[BOS_MAX_NAME_LEN];
1602 int procDone = 0;
1603
1604 while (!procDone) {
1605 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1606 /* no more processes (or failure) */
1607 if (tst2 != ADMITERATORDONE) {
1608 tst = tst2;
1609 }
1610 procDone = 1;
1611
1612 } else
1613 if (!strncmp
1614 (UPCLIENT_BOSNAME, procName,
1615 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1616 /* upclient instance prefix; assume is upclient */
1617 void *cmdIter;
1618
1619 *isUpclientP = 1;
1620
1621 if (!bos_ProcessParameterGetBegin
1622 (cfg_host->bosHandle, procName, &cmdIter, &tst2)) {
1623 tst = tst2;
1624 } else {
1625 char cmdString[BOS_MAX_NAME_LEN];
1626
1627 if (!bos_ProcessParameterGetNext
1628 (cmdIter, cmdString, &tst2)) {
1629 /* instance deleted out from under us (or error) */
1630 if (tst2 != BZNOENT) {
1631 tst = tst2;
1632 }
1633 } else {
1634 /* parse command line to determine how config */
1635 short hasSysPath, hasBinPath;
1636
1637 UpdateCommandParse(cmdString, &hasSysPath,
1638 &hasBinPath);
1639
1640 if (hasSysPath) {
1641 *isSysP = 1;
1642 }
1643 if (hasBinPath) {
1644 *isBinP = 1;
1645 }
1646 }
1647
1648 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1649 tst = tst2;
1650 }
1651 }
1652
1653 if (tst != 0) {
1654 procDone = 1;
1655 }
1656 }
1657 } /* while() */
1658
1659 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1660 tst = tst2;
1661 }
1662 }
1663 }
1664
1665 if (tst != 0) {
1666 /* indicate failure */
1667 rc = 0;
1668 }
1669 if (st != NULL) {
1670 *st = tst;
1671 }
1672 return rc;
1673 }
1674
1675
1676 /*
1677 * cfg_SysControlClientStart() -- Start an Update client in System Control
1678 * client configuration on host.
1679 *
1680 * This function is a convenience wrapper for cfg_UpdateClientStart().
1681 * The BOS instance suffix used is the constant cfg_upclientSysBosSuffix.
1682 */
1683 int ADMINAPI
1684 cfg_SysControlClientStart(void *hostHandle, /* host config handle */
1685 const char *upserver, /* upserver to import from */
1686 afs_status_p st)
1687 { /* completion status */
1688 return cfg_UpdateClientStart(hostHandle, cfg_upclientSysBosSuffix,
1689 upserver, 1 /* crypt */ ,
1690 AFSDIR_CANONICAL_SERVER_ETC_DIRPATH,
1691 0 /* default frequency */ ,
1692 st);
1693 }
1694
1695
1696 /*
1697 * cfg_BinDistClientStart() -- Start an Update client in Binary Distribution
1698 * client configuration on host.
1699 *
1700 * This function is a convenience wrapper for cfg_UpdateClientStart().
1701 * The BOS instance suffix used is the constant cfg_upclientBinBosSuffix.
1702 */
1703 int ADMINAPI
1704 cfg_BinDistClientStart(void *hostHandle, /* host config handle */
1705 const char *upserver, /* upserver to import from */
1706 afs_status_p st)
1707 { /* completion status */
1708 return cfg_UpdateClientStart(hostHandle, cfg_upclientBinBosSuffix,
1709 upserver, 0 /* crypt */ ,
1710 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
1711 0 /* default frequency */ ,
1712 st);
1713 }
1714
1715
1716
1717 /* ---------------- Local functions ------------------ */
1718
1719 /*
1720 * SimpleProcessStart() -- create and start a simple bosserver instance.
1721 *
1722 * RETURN CODES: 1 success, 0 failure (st indicates why)
1723 */
1724 static int
1725 SimpleProcessStart(void *bosHandle, const char *instance,
1726 const char *executable, const char *args, afs_status_p st)
1727 {
1728 int rc = 1;
1729 afs_status_t tst2, tst = 0;
1730 char *cmd;
1731
1732 if (args == NULL) {
1733 cmd = strdup(executable);
1734 } else {
1735 if (asprintf(&cmd, "%s %s", executable, args) < 0)
1736 cmd = NULL;
1737 }
1738
1739 if (cmd == NULL) {
1740 tst = ADMNOMEM;
1741 } else {
1742 if (!bos_ProcessCreate
1743 (bosHandle, (char *)instance, BOS_PROCESS_SIMPLE, cmd, NULL, NULL, &tst2)
1744 && tst2 != BZEXISTS) {
1745 /* failed to create instance (and not because existed) */
1746 tst = tst2;
1747 } else
1748 if (!bos_ProcessExecutionStateSet
1749 (bosHandle, (char *)instance, BOS_PROCESS_RUNNING, &tst2)) {
1750 /* failed to set instance state to running */
1751 tst = tst2;
1752 }
1753 free(cmd);
1754 }
1755
1756 if (tst != 0) {
1757 /* indicate failure */
1758 rc = 0;
1759 }
1760 if (st != NULL) {
1761 *st = tst;
1762 }
1763 return rc;
1764 }
1765
1766
1767
1768 /*
1769 * FsProcessStart() -- create and start a fs bosserver instance.
1770 *
1771 * RETURN CODES: 1 success, 0 failure (st indicates why)
1772 */
1773 static int
1774 FsProcessStart(void *bosHandle, const char *instance,
1775 const char *fileserverExe, const char *volserverExe,
1776 const char *salvagerExe, afs_status_p st)
1777 {
1778 int rc = 1;
1779 afs_status_t tst2, tst = 0;
1780
1781 if (!bos_FSProcessCreate
1782 (bosHandle, (char *)instance, (char *)fileserverExe, (char *)volserverExe, (char *)salvagerExe, NULL,
1783 &tst2) && tst2 != BZEXISTS) {
1784 /* failed to create instance (and not because existed) */
1785 tst = tst2;
1786 } else
1787 if (!bos_ProcessExecutionStateSet
1788 (bosHandle, instance, BOS_PROCESS_RUNNING, &tst2)) {
1789 /* failed to set instance state to running */
1790 tst = tst2;
1791 }
1792
1793 if (tst != 0) {
1794 /* indicate failure */
1795 rc = 0;
1796 }
1797 if (st != NULL) {
1798 *st = tst;
1799 }
1800 return rc;
1801 }
1802
1803
1804
1805 /*
1806 * BosProcessDelete() -- stop and delete a bosserver instance, if it exists.
1807 *
1808 * RETURN CODES: 1 success, 0 failure (st indicates why)
1809 */
1810 static int
1811 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st)
1812 {
1813 int rc = 1;
1814 afs_status_t tst2, tst = 0;
1815
1816 if (!bos_ProcessExecutionStateSet
1817 (bosHandle, instance, BOS_PROCESS_STOPPED, &tst2)) {
1818 /* failed to set instance state to stopped (or does not exist) */
1819 if (tst2 != BZNOENT) {
1820 tst = tst2;
1821 }
1822
1823 } else if (!bos_ProcessAllWaitTransition(bosHandle, &tst2)) {
1824 /* failed to wait for process to stop */
1825 tst = tst2;
1826
1827 } else if (!bos_ProcessDelete(bosHandle, (char *)instance, &tst2)) {
1828 /* failed to delete instance (or does not exist) */
1829 if (tst2 != BZNOENT) {
1830 tst = tst2;
1831 }
1832 }
1833
1834 if (tst != 0) {
1835 /* indicate failure */
1836 rc = 0;
1837 }
1838 if (st != NULL) {
1839 *st = tst;
1840 }
1841 return rc;
1842 }
1843
1844
1845 /*
1846 * UpdateCommandParse() -- Parse an upserver or upclient command to determine:
1847 * 1) if it explicitly exports/imports the system control directory
1848 * 2) if it explicitly exports/imports the binary directory
1849 *
1850 * NOTE: cmdString altered (made all lower case and forward slashes)
1851 */
1852 static void
1853 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP)
1854 {
1855 char *argp, *dirp;
1856
1857 *hasSysPathP = *hasBinPathP = 0;
1858
1859 /* make command string all lower case and forward slashes */
1860
1861 for (argp = cmdString; *argp != '\0'; argp++) {
1862 if (isupper(*argp)) {
1863 *argp = tolower(*argp);
1864 } else if (*argp == '\\') {
1865 *argp = '/';
1866 }
1867 }
1868
1869 /* find end of update executable path (and hence beginning of arguments */
1870
1871 argp = cmdString;
1872
1873 while (isspace(*argp)) {
1874 argp++;
1875 }
1876 while (*argp != '\0' && !isspace(*argp)) {
1877 argp++;
1878 }
1879
1880 /* search for well-known system control directory */
1881
1882 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_ETC_DIRPATH);
1883
1884 if (dirp != NULL) {
1885 /* check that not a portition of a larger path */
1886 char oneBefore, oneAfter;
1887 char twoAfter = 0;
1888
1889 oneBefore = *(dirp - 1);
1890 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH) - 1);
1891
1892 if (oneAfter != '\0') {
1893 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH));
1894 }
1895
1896 if (isspace(oneBefore)) {
1897 if ((isspace(oneAfter)) || (oneAfter == '\0')
1898 || (oneAfter == '/'
1899 && (isspace(twoAfter) || twoAfter == '\0'))) {
1900 *hasSysPathP = 1;
1901 }
1902 }
1903 }
1904
1905 /* search for well-known binary directory */
1906
1907 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
1908
1909 if (dirp != NULL) {
1910 /* check that not a portition of a larger path */
1911 char oneBefore, oneAfter;
1912 char twoAfter = 0;
1913
1914 oneBefore = *(dirp - 1);
1915 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH) - 1);
1916
1917 if (oneAfter != '\0') {
1918 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH));
1919 }
1920
1921 if (isspace(oneBefore)) {
1922 if ((isspace(oneAfter)) || (oneAfter == '\0')
1923 || (oneAfter == '/'
1924 && (isspace(twoAfter) || twoAfter == '\0'))) {
1925 *hasBinPathP = 1;
1926 }
1927 }
1928 }
1929 }
1930
1931
1932
1933 /*
1934 * UbikQuorumCheck() -- Determine if Ubik has achieved quorum for a specified
1935 * database instance in host's cell.
1936 *
1937 * RETURN CODES: 1 success, 0 failure (st indicates why)
1938 */
1939 static int
1940 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance, short *hasQuorum,
1941 afs_status_p st)
1942 {
1943 int rc = 1;
1944 afs_status_t tst2, tst = 0;
1945 void *dbIter;
1946
1947 *hasQuorum = 0;
1948
1949 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
1950 tst = tst2;
1951 } else {
1952 /* iterate over server CellServDb, looking for dbserver sync site */
1953 char dbhostName[BOS_MAX_NAME_LEN];
1954 int dbhostAddr;
1955 unsigned short dbhostPort = 0;
1956 int dbhostDone = 0;
1957 int dbhostQueries = 0;
1958
1959 if (!strcmp(dbInstance, KASERVER_BOSNAME)) {
1960 dbhostPort = AFSCONF_KAUTHPORT;
1961 } else if (!strcmp(dbInstance, PTSERVER_BOSNAME)) {
1962 dbhostPort = AFSCONF_PROTPORT;
1963 } else if (!strcmp(dbInstance, VLSERVER_BOSNAME)) {
1964 dbhostPort = AFSCONF_VLDBPORT;
1965 } else if (!strcmp(dbInstance, BUSERVER_BOSNAME)) {
1966 dbhostPort = AFSCONF_BUDBPORT;
1967 }
1968
1969 while (!dbhostDone) {
1970 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
1971 /* no more entries (or failure) */
1972 if (tst2 == ADMITERATORDONE) {
1973 if (dbhostQueries == 0) {
1974 /* consider quorum to have been achieved when no
1975 * database servers in cell; otherwise higher-level
1976 * functions will timeout and fail.
1977 */
1978 *hasQuorum = 1;
1979 }
1980 } else {
1981 tst = tst2;
1982 }
1983 dbhostDone = 1;
1984
1985 } else
1986 if (!util_AdminServerAddressGetFromName
1987 (dbhostName, &dbhostAddr, &tst2)) {
1988 tst = tst2;
1989 dbhostDone = 1;
1990 } else {
1991 short isSyncSite = 0;
1992 short isWriteReady = 0;
1993
1994 /* ignore errors fetching Ubik vote status; there might be
1995 * an unreachable dbserver yet a reachable sync site.
1996 */
1997 dbhostQueries++;
1998
1999 if (UbikVoteStatusFetch
2000 (dbhostAddr, dbhostPort, &isSyncSite, &isWriteReady,
2001 &tst2)) {
2002 /* have quorum if is sync site AND is ready for updates */
2003 if (isSyncSite) {
2004 if (isWriteReady) {
2005 *hasQuorum = 1;
2006 }
2007 dbhostDone = 1;
2008 }
2009 }
2010 }
2011 }
2012
2013 if (!bos_HostGetDone(dbIter, &tst2)) {
2014 tst = tst2;
2015 }
2016 }
2017
2018 if (tst != 0) {
2019 /* indicate failure */
2020 rc = 0;
2021 }
2022 if (st != NULL) {
2023 *st = tst;
2024 }
2025 return rc;
2026 }
2027
2028
2029 /*
2030 * UbikVoteStatusFetch() -- Fetch Ubik vote status parameters of interest from
2031 * specified server and port.
2032 *
2033 * RETURN CODES: 1 success, 0 failure (st indicates why)
2034 */
2035 static int
2036 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
2037 short *isSyncSite, short *isWriteReady, afs_status_p st)
2038 {
2039 int rc = 1;
2040 afs_status_t tst = 0;
2041 struct rx_securityClass *nullSecurity;
2042 struct rx_connection *serverConn;
2043
2044 nullSecurity = rxnull_NewClientSecurityObject(); /* never fails */
2045
2046 if ((serverConn =
2047 rx_GetCachedConnection(htonl(serverAddr), htons(serverPort),
2048 VOTE_SERVICE_ID, nullSecurity, 0)) == NULL) {
2049 tst = ADMCFGUBIKVOTENOCONNECTION;
2050 } else {
2051 int rpcCode;
2052 struct ubik_debug udebugInfo;
2053
2054 if ((rpcCode = VOTE_Debug(serverConn, &udebugInfo)) == 0) {
2055 /* talking to a 3.5 or later server */
2056 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2057 *isWriteReady = 0;
2058
2059 if (*isSyncSite) {
2060 /* as of 3.5 the database is writable if "labeled" or if all
2061 * prior recovery states have been achieved; see defect 9477.
2062 */
2063 if (((udebugInfo.recoveryState & UBIK_RECLABELDB))
2064 || ((udebugInfo.recoveryState & UBIK_RECSYNCSITE)
2065 && (udebugInfo.recoveryState & UBIK_RECFOUNDDB)
2066 && (udebugInfo.recoveryState & UBIK_RECHAVEDB))) {
2067 *isWriteReady = 1;
2068 }
2069 }
2070
2071 } else if (rpcCode == RXGEN_OPCODE) {
2072 /* talking to old (pre 3.5) server */
2073 struct ubik_debug_old udebugInfo;
2074
2075 if ((rpcCode = VOTE_DebugOld(serverConn, &udebugInfo)) == 0) {
2076 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2077 *isWriteReady = 0;
2078
2079 if (*isSyncSite) {
2080 /* pre 3.5 the database is writable only if "labeled" */
2081 if (udebugInfo.recoveryState & UBIK_RECLABELDB) {
2082 *isWriteReady = 1;
2083 }
2084 }
2085 }
2086 }
2087
2088 (void)rx_ReleaseCachedConnection(serverConn);
2089
2090 tst = rpcCode;
2091 }
2092
2093 if (tst != 0) {
2094 /* indicate failure */
2095 rc = 0;
2096 }
2097 if (st != NULL) {
2098 *st = tst;
2099 }
2100 return rc;
2101 }