2 * Copyright 2000, International Business Machines Corporation and others.
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
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.
18 #include <afsconfig.h>
19 #include <afs/param.h>
28 #include <WINNT/afsreg.h>
29 #endif /* AFS_NT40_ENV */
34 #include <rx/rxstat.h>
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>
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>
49 #define UBIK_INTERNALS /* need "internal" symbols from ubik.h */
52 #include "cfginternal.h"
53 #include "afs_cfgAdmin.h"
56 /* Local declarations and definitions */
58 #define KASERVER_BOSNAME "kaserver"
59 #define KASERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/kaserver"
61 #define PTSERVER_BOSNAME "ptserver"
62 #define PTSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/ptserver"
64 #define VLSERVER_BOSNAME "vlserver"
65 #define VLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/vlserver"
67 #define BUSERVER_BOSNAME "buserver"
68 #define BUSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/buserver"
70 #define UPSERVER_BOSNAME "upserver"
71 #define UPSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upserver"
73 #define UPCLIENT_BOSNAME "upclient"
74 #define UPCLIENT_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upclient"
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"
83 SimpleProcessStart(void *bosHandle, const char *instance,
84 const char *executable, const char *args,
88 FsProcessStart(void *bosHandle, const char *instance,
89 const char *fileserverExe, const char *volserverExe,
90 const char *salvagerExe, afs_status_p st);
93 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st);
96 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP);
99 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance,
100 short *hasQuorum, afs_status_p st);
103 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
104 short *isSyncSite, short *isWriteReady,
112 /* ---------------- Exported constants ---------------- */
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;
121 const char *cfg_upclientBosNamePrefix = UPCLIENT_BOSNAME;
122 const char *cfg_upclientSysBosSuffix = "etc";
123 const char *cfg_upclientBinBosSuffix = "bin";
127 /* ---------------- Exported BOS Server functions ------------------ */
131 * cfg_BosServerStart() -- Start the BOS server on host.
133 * Timeout is the maximum time, in seconds, to wait for BOS to start.
136 cfg_BosServerStart(void *hostHandle, /* host config handle */
137 short noAuth, /* start in NoAuth mode */
138 unsigned int timeout, /* timeout (in seconds) */
140 { /* completion status */
142 afs_status_t tst2, tst = 0;
143 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
144 short wasRunning = 0;
146 /* validate parameters */
148 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
152 /* remote configuration not yet supported in this function */
155 if (!cfg_host->is_local) {
156 tst = ADMCFGNOTSUPPORTED;
160 /* start bosserver (if not already running) */
163 /* Windows - bosserver is controlled via the BOS control service */
166 LPCTSTR auxArgBuf[1], *auxArgv;
171 auxArgBuf[0] = "-noauth";
177 if (!cfgutil_WindowsServiceStart
178 (AFSREG_SVR_SVC_NAME, auxArgc, auxArgv, timeout, &wasRunning,
180 /* failed to start BOS control service */
186 /* function not yet implemented for Unix */
187 tst = ADMCFGNOTSUPPORTED;
189 #endif /* AFS_NT40_ENV */
191 /* put bosserver into requested auth mode if was already running */
193 if (tst == 0 && wasRunning) {
194 if (!cfgutil_HostSetNoAuthFlag(cfg_host, noAuth, &tst2)) {
200 /* indicate failure */
212 * cfg_BosServerStop() -- Stop the BOS server on host.
214 * Timeout is the maximum time, in seconds, to wait for BOS to stop.
217 cfg_BosServerStop(void *hostHandle, /* host config handle */
218 unsigned int timeout, /* timeout (in seconds) */
220 { /* completion status */
222 afs_status_t tst2, tst = 0;
223 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
225 /* validate parameters */
227 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
231 /* remote configuration not yet supported in this function */
234 if (!cfg_host->is_local) {
235 tst = ADMCFGNOTSUPPORTED;
239 /* stop the bosserver (if running) */
242 /* Windows - bosserver is controlled via the BOS control service */
246 if (!cfgutil_WindowsServiceStop
247 (AFSREG_SVR_SVC_NAME, timeout, &wasStopped, &tst2)) {
248 /* failed to stop BOS control service */
254 /* function not yet implemented for Unix */
255 tst = ADMCFGNOTSUPPORTED;
257 #endif /* AFS_NT40_ENV */
260 /* indicate failure */
271 * cfg_BosServerQueryStatus() -- Query status of BOS server on host.
273 * The argument *isBosProcP is set to TRUE only if BOS processes
274 * are currently executing (as opposed to configured but stopped).
277 cfg_BosServerQueryStatus(void *hostHandle, /* host config handle */
278 short *isStartedP, /* BOS server is started */
279 short *isBosProcP, /* BOS processes running */
281 { /* completion status */
283 afs_status_t tst2, tst = 0;
284 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
286 /* validate parameters and prepare host handle for bos functions */
288 if (!cfgutil_HostHandleValidate(cfg_host, &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)) {
298 /* remote configuration not yet supported in this function */
301 if (!cfg_host->is_local) {
302 tst = ADMCFGNOTSUPPORTED;
306 /* determine if bosserver is running */
309 /* Windows - bosserver is controlled via the BOS control service */
313 *isStartedP = *isBosProcP = 0;
315 if (!cfgutil_WindowsServiceQuery
316 (AFSREG_SVR_SVC_NAME, &svcState, &tst2)) {
318 } else if (svcState == SERVICE_RUNNING) {
324 /* function not yet implemented for Unix */
325 tst = ADMCFGNOTSUPPORTED;
327 #endif /* AFS_NT40_ENV */
330 /* query status of bos processes */
332 if (tst == 0 && *isStartedP) {
337 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
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];
347 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
348 /* no more processes (or failure) */
349 if (tst2 != ADMITERATORDONE) {
355 if (!bos_ProcessExecutionStateGet
356 (cfg_host->bosHandle, procName, &procState,
357 procAuxState, &tst2)) {
358 /* process removed (or failure) */
359 if (tst2 != BZNOENT) {
365 if (procState != BOS_PROCESS_STOPPED) {
372 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
379 /* indicate failure */
391 /* ---------------- Exported Database Server functions ------------------ */
396 * cfg_AuthServerStart() -- Start authentication server on host and wait
397 * for server to be ready to accept requests.
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.
404 cfg_AuthServerStart(void *hostHandle, /* host config handle */
406 { /* completion status */
408 afs_status_t tst2, tst = 0;
409 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
411 /* validate parameters and prepare host handle for bos functions */
413 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
415 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
419 /* create and start authentication server instance */
422 if (!SimpleProcessStart
423 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
429 /* wait for authentication server to achieve quorum */
432 time_t timeStart = time(NULL);
437 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
441 } else if (kaHasQuorum) {
442 /* quorum on authentication server */
446 /* quorum not yet achieved on authentication server */
447 if (difftime(time(NULL), timeStart) > 180) {
448 tst = ADMCFGQUORUMWAITTIMEOUT;
458 /* indicate failure */
469 * cfg_DbServersStart() -- Start the standard (required) database servers,
470 * and optionally the backup database server, on host.
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
479 cfg_DbServersStart(void *hostHandle, /* host config handle */
480 short startBkDb, /* start backup server */
482 { /* completion status */
484 afs_status_t tst2, tst = 0;
485 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
487 /* validate parameters and prepare host handle for bos functions */
489 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
491 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
495 /* create and start database server instances */
498 /* try all regardless of failures; last error code wins */
499 if (!SimpleProcessStart
500 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
504 if (!SimpleProcessStart
505 (cfg_host->bosHandle, PTSERVER_BOSNAME, PTSERVER_EXEPATH, NULL,
509 if (!SimpleProcessStart
510 (cfg_host->bosHandle, VLSERVER_BOSNAME, VLSERVER_EXEPATH, NULL,
515 && !SimpleProcessStart(cfg_host->bosHandle, BUSERVER_BOSNAME,
516 BUSERVER_EXEPATH, NULL, &tst2)) {
522 /* indicate failure */
533 * cfg_DbServersStop() -- Stop, and unconfigure, the database servers on host.
536 cfg_DbServersStop(void *hostHandle, /* host config handle */
538 { /* completion status */
540 afs_status_t tst2, tst = 0;
541 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
543 /* validate parameters and prepare host handle for bos functions */
545 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
547 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
551 /* stop and delete database server instances */
554 /* try all regardless of failures; last error code wins */
555 if (!BosProcessDelete(cfg_host->bosHandle, KASERVER_BOSNAME, &tst2)) {
558 if (!BosProcessDelete(cfg_host->bosHandle, PTSERVER_BOSNAME, &tst2)) {
561 if (!BosProcessDelete(cfg_host->bosHandle, VLSERVER_BOSNAME, &tst2)) {
564 if (!BosProcessDelete(cfg_host->bosHandle, BUSERVER_BOSNAME, &tst2)) {
570 /* indicate failure */
581 * cfg_DbServersQueryStatus() -- Query status of database servers on host.
583 * If detailed status information is not required, detailsP can be NULL.
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.
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 */
594 { /* completion status */
596 afs_status_t tst2, tst = 0;
597 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
598 short inCellServDb, isKaserver, isPtserver, isVlserver, isBuserver;
600 inCellServDb = isKaserver = isPtserver = isVlserver = isBuserver = 0;
602 /* validate parameters and prepare host handle for bos functions */
604 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
606 } else if (isStdDbP == NULL || isBkDbP == NULL) {
607 tst = ADMCFGDBSERVERCONFIGFLAGPNULL;
608 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
612 /* query host's server CellServDb to see if it lists itself */
615 char hostNameAlias[MAXHOSTCHARS];
617 if (!cfgutil_HostNameGetCellServDbAlias
618 (cfg_host->hostName, cfg_host->hostName, hostNameAlias, &tst2)) {
620 } else if (*hostNameAlias != '\0') {
621 /* host in its own CellServDb */
626 /* query bosserver to determine what database servers are configured */
629 bos_ProcessType_t procType;
630 bos_ProcessInfo_t procInfo;
632 if (bos_ProcessInfoGet
633 (cfg_host->bosHandle, KASERVER_BOSNAME, &procType, &procInfo,
636 } else if (tst2 != BZNOENT) {
641 if (bos_ProcessInfoGet
642 (cfg_host->bosHandle, PTSERVER_BOSNAME, &procType, &procInfo,
645 } else if (tst2 != BZNOENT) {
651 if (bos_ProcessInfoGet
652 (cfg_host->bosHandle, VLSERVER_BOSNAME, &procType, &procInfo,
655 } else if (tst2 != BZNOENT) {
661 if (bos_ProcessInfoGet
662 (cfg_host->bosHandle, BUSERVER_BOSNAME, &procType, &procInfo,
665 } else if (tst2 != BZNOENT) {
672 /* success; return results */
673 *isStdDbP = (inCellServDb && isKaserver && isPtserver && isVlserver);
674 *isBkDbP = (inCellServDb && isBuserver);
677 detailsP->inCellServDb = inCellServDb;
678 detailsP->isKaserver = isKaserver;
679 detailsP->isPtserver = isPtserver;
680 detailsP->isVlserver = isVlserver;
681 detailsP->isBuserver = isBuserver;
684 /* indicate failure */
695 * cfg_DbServersRestartAll() -- Restart all database servers in host's cell.
698 cfg_DbServersRestartAll(void *hostHandle, /* host config handle */
700 { /* completion status */
702 afs_status_t tst2, tst = 0;
703 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
705 /* validate parameters and prepare host handle for bos functions */
707 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
709 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
713 /* restart all database servers in host's cell */
718 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
721 /* iterate over server CellServDb, restarting db servers */
722 char dbhostName[BOS_MAX_NAME_LEN];
726 while (!dbhostDone) {
727 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
728 /* no more entries (or failure) */
729 if (tst2 != ADMITERATORDONE) {
736 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
738 /* failed to get bos handle; note error but keep going */
742 /* restart db servers; note errors, but keep going */
743 if (!bos_ProcessRestart
744 (dbhostHandle, KASERVER_BOSNAME, &tst2)) {
747 if (!bos_ProcessRestart
748 (dbhostHandle, PTSERVER_BOSNAME, &tst2)) {
751 if (!bos_ProcessRestart
752 (dbhostHandle, VLSERVER_BOSNAME, &tst2)) {
755 if (!bos_ProcessRestart
756 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
757 /* may not be running a backup server */
758 if (tst2 != BZNOENT) {
763 if (!bos_ServerClose(dbhostHandle, &tst2)) {
769 if (!bos_HostGetDone(dbIter, &tst2)) {
776 /* indicate failure */
779 /* should really utilize a callback (or some other mechanism) to
780 * indicate which restarts failed and why.
791 * cfg_DbServersWaitForQuorum() -- Wait for database servers in host's cell
794 * Timeout is the maximum time, in seconds, to wait for quorum.
796 * NOTE: Function does not check for backup server quorum since
797 * configuration does not require modifying the backup database.
800 cfg_DbServersWaitForQuorum(void *hostHandle, /* host config handle */
801 unsigned int timeout, /* timeout in sec. */
803 { /* completion status */
805 afs_status_t tst2, tst = 0;
806 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
808 /* validate parameters and prepare host handle for bos functions */
810 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
812 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
816 /* wait for the database servers in host's cell to achieve quorum */
819 time_t timeStart = time(NULL);
820 short kaHasQuorum, ptHasQuorum, vlHasQuorum;
822 kaHasQuorum = ptHasQuorum = vlHasQuorum = 0;
827 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
835 (cfg_host, PTSERVER_BOSNAME, &ptHasQuorum, &tst2)) {
843 (cfg_host, VLSERVER_BOSNAME, &vlHasQuorum, &tst2)) {
849 if (kaHasQuorum && ptHasQuorum && vlHasQuorum) {
850 /* quorum on all dbservers of interest */
853 /* quorum not yet achieved for one or more dbservers */
855 || (difftime(time(NULL), timeStart) > timeout)) {
856 tst = ADMCFGQUORUMWAITTIMEOUT;
866 /* indicate failure */
878 * cfg_DbServersStopAllBackup() -- Stop, and unconfigure, all backup servers
882 cfg_DbServersStopAllBackup(void *hostHandle, /* host config handle */
884 { /* completion status */
886 afs_status_t tst2, tst = 0;
887 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
889 /* validate parameters and prepare host handle for bos functions */
891 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
893 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
897 /* stop and delete all backup servers in host's cell */
902 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
905 /* iterate over server CellServDb, unconfiguring backup servers */
906 char dbhostName[BOS_MAX_NAME_LEN];
910 while (!dbhostDone) {
911 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
912 /* no more entries (or failure) */
913 if (tst2 != ADMITERATORDONE) {
920 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
922 /* failed to get bos handle; note error but keep going */
926 /* unconfig backup server; note errors, but keep going */
927 if (!BosProcessDelete
928 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
932 if (!bos_ServerClose(dbhostHandle, &tst2)) {
938 if (!bos_HostGetDone(dbIter, &tst2)) {
945 /* indicate failure */
948 /* should really utilize a callback (or some other mechanism) to
949 * indicate which stops failed and why.
962 /* ---------------- Exported File Server functions ------------------ */
966 * cfg_FileServerStart() -- Start the file server on host.
968 * The BOS instance name used is the string constant cfg_fileserverBosName.
971 cfg_FileServerStart(void *hostHandle, /* host config handle */
973 { /* completion status */
975 afs_status_t tst2, tst = 0;
976 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
978 /* validate parameters and prepare host handle for bos functions */
980 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
982 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
986 /* create and start file server instance */
990 (cfg_host->bosHandle, FILESERVER_BOSNAME, FILESERVER_EXEPATH,
991 VOLSERVER_EXEPATH, SALVAGER_EXEPATH, &tst2)) {
994 /* TO BE DONE: need a reliable "is started and ready" check */
1000 /* indicate failure */
1011 * cfg_FileServerStop() -- Stop, and unconfigure, the file server on host.
1014 cfg_FileServerStop(void *hostHandle, /* host config handle */
1016 { /* completion status */
1018 afs_status_t tst2, tst = 0;
1019 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1021 /* validate parameters and prepare host handle for bos functions */
1023 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1025 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1029 /* stop and delete file server instance */
1032 if (!BosProcessDelete(cfg_host->bosHandle, FILESERVER_BOSNAME, &tst2)) {
1035 /* file server instance deleted; remove its addresses from VLDB */
1037 afs_int32 *addrList = NULL;
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).
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,
1060 /* indicate failure */
1071 * cfg_FileServerQueryStatus() -- Query status of file server on host.
1074 cfg_FileServerQueryStatus(void *hostHandle, /* host config handle */
1075 short *isFsP, /* file server configured */
1077 { /* completion status */
1079 afs_status_t tst2, tst = 0;
1080 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1082 /* validate parameters and prepare host handle for bos functions */
1084 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1086 } else if (isFsP == NULL) {
1087 tst = ADMCFGFILESERVERCONFIGFLAGPNULL;
1088 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1092 /* query bosserver to determine if fileserver is configured */
1095 bos_ProcessType_t procType;
1096 bos_ProcessInfo_t procInfo;
1100 if (bos_ProcessInfoGet
1101 (cfg_host->bosHandle, FILESERVER_BOSNAME, &procType, &procInfo,
1103 /* instance exists; check type for good measure */
1104 if (procType == BOS_PROCESS_FS) {
1107 } else if (tst2 != BZNOENT) {
1113 /* indicate failure */
1125 /* ---------------- Exported Update Server functions ------------------ */
1130 * cfg_UpdateServerStart() -- Start the Update server on host.
1132 * Argument strings exportClear and exportCrypt each specify a set of
1133 * space-separated directories to export or are NULL.
1135 * The BOS instance name used is the string constant cfg_upserverBosName.
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 */
1142 { /* completion status */
1144 afs_status_t tst2, tst = 0;
1145 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1147 /* validate parameters and prepare host handle for bos functions */
1149 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1151 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1155 /* stop and delete existing update server instance, if any.
1156 * we do this because the set of exported directores might be changing.
1160 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1165 /* create and start update server instance */
1171 if (exportClear != NULL && *exportClear != '\0') {
1172 if (exportCrypt != NULL && *exportCrypt != '\0') {
1173 r = asprintf(&args, "-clear %s -crypt %s",
1174 exportClear, exportCrypt);
1176 r = asprintf(&args, "-clear %s", exportClear);
1179 if (exportCrypt != NULL && *exportCrypt != '\0') {
1180 r = asprintf(&args, "-crypt %s", exportCrypt);
1192 if (!SimpleProcessStart
1193 (cfg_host->bosHandle, UPSERVER_BOSNAME, UPSERVER_EXEPATH,
1202 /* indicate failure */
1213 * cfg_UpdateServerStop() -- Stop, and unconfigure, the Update server on host.
1216 cfg_UpdateServerStop(void *hostHandle, /* host config handle */
1218 { /* completion status */
1220 afs_status_t tst2, tst = 0;
1221 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1223 /* validate parameters and prepare host handle for bos functions */
1225 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1227 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1231 /* stop and delete upserver instance */
1234 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1240 /* indicate failure */
1251 * cfg_UpdateServerQueryStatus() -- Query status of Update server on host.
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 */
1259 { /* completion status */
1261 afs_status_t tst2, tst = 0;
1262 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1264 /* validate parameters and prepare host handle for bos functions */
1266 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1268 } else if (isUpserverP == NULL || isSysCtrlP == NULL
1269 || isBinDistP == NULL) {
1270 tst = ADMCFGUPSERVERCONFIGFLAGPNULL;
1271 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1275 /* query bosserver to determine if, and how, upserver is configured */
1280 *isUpserverP = *isSysCtrlP = *isBinDistP = 0;
1282 if (!bos_ProcessParameterGetBegin
1283 (cfg_host->bosHandle, UPSERVER_BOSNAME, &cmdIter, &tst2)) {
1286 char cmdString[BOS_MAX_NAME_LEN];
1288 if (!bos_ProcessParameterGetNext(cmdIter, cmdString, &tst2)) {
1289 /* no upserver instance (or error) */
1290 if (tst2 != BZNOENT) {
1294 /* parse upserver command line to determine how configured */
1295 short hasSysPath, hasBinPath;
1297 UpdateCommandParse(cmdString, &hasSysPath, &hasBinPath);
1309 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1316 /* indicate failure */
1327 * cfg_SysBinServerStart() -- Start Update server in System Control and/or
1328 * Binary Distribution machine configuration on host.
1330 * This function is a convenience wrapper for cfg_UpdateServerStart().
1333 cfg_SysBinServerStart(void *hostHandle, /* host config handle */
1334 short makeSysCtrl, /* config as sys control mach */
1335 short makeBinDist, /* config as binary dist mach */
1337 { /* completion status */
1338 char *cryptSysDir = NULL;
1339 char *clearBinDir = NULL;
1342 cryptSysDir = AFSDIR_CANONICAL_SERVER_ETC_DIRPATH;
1346 clearBinDir = AFSDIR_CANONICAL_SERVER_BIN_DIRPATH;
1349 return cfg_UpdateServerStart(hostHandle, clearBinDir, cryptSysDir, st);
1354 /* ---------------- Exported Update Client functions ------------------ */
1359 * cfg_UpdateClientStart() -- Start an Update client on host.
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.
1365 * The BOS instance name used is the concatenation of the string constant
1366 * cfg_upclientBosNamePrefix and the argument string bosSuffix.
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. */
1376 { /* completion status */
1378 afs_status_t tst2, tst = 0;
1379 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1380 char upclientInstance[BOS_MAX_NAME_LEN];
1382 /* validate parameters and prepare host handle for bos functions */
1384 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1386 } else if (bosSuffix == NULL) {
1387 tst = ADMCFGUPCLIENTSUFFIXNULL;
1388 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
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)) {
1399 /* stop and delete existing update client instance, if any.
1400 * we do this because the set of imported directores might be changing.
1404 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1406 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1411 /* create and start update client instance */
1418 r = asprintf(&args, "%s %s -t %u %s", upserver,
1419 crypt ? "-crypt" : "-clear", frequency, import);
1421 r = asprintf(&args, "%s %s %s", upserver,
1422 crypt ? "-crypt" : "-clear", import);
1428 /* create and start instance */
1429 if (!SimpleProcessStart
1430 (cfg_host->bosHandle, upclientInstance, UPCLIENT_EXEPATH,
1439 /* indicate failure */
1450 * cfg_UpdateClientStop() -- Stop, and unconfigure, an Update client on host.
1453 cfg_UpdateClientStop(void *hostHandle, /* host config handle */
1454 const char *bosSuffix, /* BOS instance suffix */
1456 { /* completion status */
1458 afs_status_t tst2, tst = 0;
1459 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1460 char upclientInstance[BOS_MAX_NAME_LEN];
1462 /* validate parameters and prepare host handle for bos functions */
1464 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1466 } else if (bosSuffix == NULL) {
1467 tst = ADMCFGUPCLIENTSUFFIXNULL;
1468 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1470 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1471 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1475 /* stop and delete specified update client instance */
1478 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1480 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1486 /* indicate failure */
1497 * cfg_UpdateClientStopAll() -- Stop, and unconfigure, all Update clients
1501 cfg_UpdateClientStopAll(void *hostHandle, /* host config handle */
1503 { /* completion status */
1505 afs_status_t tst2, tst = 0;
1506 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1508 /* validate parameters and prepare host handle for bos functions */
1510 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1512 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1516 /* find, stop, and delete all update client instances */
1521 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1524 /* iterate over process names, looking for update clients */
1525 char procName[BOS_MAX_NAME_LEN];
1529 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1530 /* no more processes (or failure) */
1531 if (tst2 != ADMITERATORDONE) {
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)) {
1549 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1556 /* indicate failure */
1567 * cfg_UpdateClientQueryStatus() -- Query status of Update clients on host.
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 */
1575 { /* completion status */
1577 afs_status_t tst2, tst = 0;
1578 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1580 /* validate parameters and prepare host handle for bos functions */
1582 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1584 } else if (isUpclientP == NULL || isSysP == NULL || isBinP == NULL) {
1585 tst = ADMCFGUPCLIENTCONFIGFLAGPNULL;
1586 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1590 /* determine if, and how, any upclients are configured */
1595 *isUpclientP = *isSysP = *isBinP = 0;
1597 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1600 /* iterate over process names, looking for update clients */
1601 char procName[BOS_MAX_NAME_LEN];
1605 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1606 /* no more processes (or failure) */
1607 if (tst2 != ADMITERATORDONE) {
1614 (UPCLIENT_BOSNAME, procName,
1615 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1616 /* upclient instance prefix; assume is upclient */
1621 if (!bos_ProcessParameterGetBegin
1622 (cfg_host->bosHandle, procName, &cmdIter, &tst2)) {
1625 char cmdString[BOS_MAX_NAME_LEN];
1627 if (!bos_ProcessParameterGetNext
1628 (cmdIter, cmdString, &tst2)) {
1629 /* instance deleted out from under us (or error) */
1630 if (tst2 != BZNOENT) {
1634 /* parse command line to determine how config */
1635 short hasSysPath, hasBinPath;
1637 UpdateCommandParse(cmdString, &hasSysPath,
1648 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1659 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1666 /* indicate failure */
1677 * cfg_SysControlClientStart() -- Start an Update client in System Control
1678 * client configuration on host.
1680 * This function is a convenience wrapper for cfg_UpdateClientStart().
1681 * The BOS instance suffix used is the constant cfg_upclientSysBosSuffix.
1684 cfg_SysControlClientStart(void *hostHandle, /* host config handle */
1685 const char *upserver, /* upserver to import from */
1687 { /* completion status */
1688 return cfg_UpdateClientStart(hostHandle, cfg_upclientSysBosSuffix,
1689 upserver, 1 /* crypt */ ,
1690 AFSDIR_CANONICAL_SERVER_ETC_DIRPATH,
1691 0 /* default frequency */ ,
1697 * cfg_BinDistClientStart() -- Start an Update client in Binary Distribution
1698 * client configuration on host.
1700 * This function is a convenience wrapper for cfg_UpdateClientStart().
1701 * The BOS instance suffix used is the constant cfg_upclientBinBosSuffix.
1704 cfg_BinDistClientStart(void *hostHandle, /* host config handle */
1705 const char *upserver, /* upserver to import from */
1707 { /* completion status */
1708 return cfg_UpdateClientStart(hostHandle, cfg_upclientBinBosSuffix,
1709 upserver, 0 /* crypt */ ,
1710 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
1711 0 /* default frequency */ ,
1717 /* ---------------- Local functions ------------------ */
1720 * SimpleProcessStart() -- create and start a simple bosserver instance.
1722 * RETURN CODES: 1 success, 0 failure (st indicates why)
1725 SimpleProcessStart(void *bosHandle, const char *instance,
1726 const char *executable, const char *args, afs_status_p st)
1729 afs_status_t tst2, tst = 0;
1733 cmd = strdup(executable);
1735 if (asprintf(&cmd, "%s %s", executable, args) < 0)
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) */
1748 if (!bos_ProcessExecutionStateSet
1749 (bosHandle, (char *)instance, BOS_PROCESS_RUNNING, &tst2)) {
1750 /* failed to set instance state to running */
1757 /* indicate failure */
1769 * FsProcessStart() -- create and start a fs bosserver instance.
1771 * RETURN CODES: 1 success, 0 failure (st indicates why)
1774 FsProcessStart(void *bosHandle, const char *instance,
1775 const char *fileserverExe, const char *volserverExe,
1776 const char *salvagerExe, afs_status_p st)
1779 afs_status_t tst2, tst = 0;
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) */
1787 if (!bos_ProcessExecutionStateSet
1788 (bosHandle, instance, BOS_PROCESS_RUNNING, &tst2)) {
1789 /* failed to set instance state to running */
1794 /* indicate failure */
1806 * BosProcessDelete() -- stop and delete a bosserver instance, if it exists.
1808 * RETURN CODES: 1 success, 0 failure (st indicates why)
1811 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st)
1814 afs_status_t tst2, tst = 0;
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) {
1823 } else if (!bos_ProcessAllWaitTransition(bosHandle, &tst2)) {
1824 /* failed to wait for process to stop */
1827 } else if (!bos_ProcessDelete(bosHandle, (char *)instance, &tst2)) {
1828 /* failed to delete instance (or does not exist) */
1829 if (tst2 != BZNOENT) {
1835 /* indicate failure */
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
1850 * NOTE: cmdString altered (made all lower case and forward slashes)
1853 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP)
1857 *hasSysPathP = *hasBinPathP = 0;
1859 /* make command string all lower case and forward slashes */
1861 for (argp = cmdString; *argp != '\0'; argp++) {
1862 if (isupper(*argp)) {
1863 *argp = tolower(*argp);
1864 } else if (*argp == '\\') {
1869 /* find end of update executable path (and hence beginning of arguments */
1873 while (isspace(*argp)) {
1876 while (*argp != '\0' && !isspace(*argp)) {
1880 /* search for well-known system control directory */
1882 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_ETC_DIRPATH);
1885 /* check that not a portition of a larger path */
1886 char oneBefore, oneAfter;
1889 oneBefore = *(dirp - 1);
1890 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH) - 1);
1892 if (oneAfter != '\0') {
1893 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH));
1896 if (isspace(oneBefore)) {
1897 if ((isspace(oneAfter)) || (oneAfter == '\0')
1899 && (isspace(twoAfter) || twoAfter == '\0'))) {
1905 /* search for well-known binary directory */
1907 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
1910 /* check that not a portition of a larger path */
1911 char oneBefore, oneAfter;
1914 oneBefore = *(dirp - 1);
1915 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH) - 1);
1917 if (oneAfter != '\0') {
1918 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH));
1921 if (isspace(oneBefore)) {
1922 if ((isspace(oneAfter)) || (oneAfter == '\0')
1924 && (isspace(twoAfter) || twoAfter == '\0'))) {
1934 * UbikQuorumCheck() -- Determine if Ubik has achieved quorum for a specified
1935 * database instance in host's cell.
1937 * RETURN CODES: 1 success, 0 failure (st indicates why)
1940 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance, short *hasQuorum,
1944 afs_status_t tst2, tst = 0;
1949 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
1952 /* iterate over server CellServDb, looking for dbserver sync site */
1953 char dbhostName[BOS_MAX_NAME_LEN];
1955 unsigned short dbhostPort = 0;
1957 int dbhostQueries = 0;
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;
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.
1986 if (!util_AdminServerAddressGetFromName
1987 (dbhostName, &dbhostAddr, &tst2)) {
1991 short isSyncSite = 0;
1992 short isWriteReady = 0;
1994 /* ignore errors fetching Ubik vote status; there might be
1995 * an unreachable dbserver yet a reachable sync site.
1999 if (UbikVoteStatusFetch
2000 (dbhostAddr, dbhostPort, &isSyncSite, &isWriteReady,
2002 /* have quorum if is sync site AND is ready for updates */
2013 if (!bos_HostGetDone(dbIter, &tst2)) {
2019 /* indicate failure */
2030 * UbikVoteStatusFetch() -- Fetch Ubik vote status parameters of interest from
2031 * specified server and port.
2033 * RETURN CODES: 1 success, 0 failure (st indicates why)
2036 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
2037 short *isSyncSite, short *isWriteReady, afs_status_p st)
2040 afs_status_t tst = 0;
2041 struct rx_securityClass *nullSecurity;
2042 struct rx_connection *serverConn;
2044 nullSecurity = rxnull_NewClientSecurityObject(); /* never fails */
2047 rx_GetCachedConnection(htonl(serverAddr), htons(serverPort),
2048 VOTE_SERVICE_ID, nullSecurity, 0)) == NULL) {
2049 tst = ADMCFGUBIKVOTENOCONNECTION;
2052 struct ubik_debug udebugInfo;
2054 if ((rpcCode = VOTE_Debug(serverConn, &udebugInfo)) == 0) {
2055 /* talking to a 3.5 or later server */
2056 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2060 /* as of 3.5 the database is writable if "labeled" or if all
2061 * prior recovery states have been achieved; see defect 9477.
2063 if (((udebugInfo.recoveryState & UBIK_RECLABELDB))
2064 || ((udebugInfo.recoveryState & UBIK_RECSYNCSITE)
2065 && (udebugInfo.recoveryState & UBIK_RECFOUNDDB)
2066 && (udebugInfo.recoveryState & UBIK_RECHAVEDB))) {
2071 } else if (rpcCode == RXGEN_OPCODE) {
2072 /* talking to old (pre 3.5) server */
2073 struct ubik_debug_old udebugInfo;
2075 if ((rpcCode = VOTE_DebugOld(serverConn, &udebugInfo)) == 0) {
2076 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2080 /* pre 3.5 the database is writable only if "labeled" */
2081 if (udebugInfo.recoveryState & UBIK_RECLABELDB) {
2088 (void)rx_ReleaseCachedConnection(serverConn);
2094 /* indicate failure */