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>
34 #include <WINNT/afsreg.h>
35 #endif /* AFS_NT40_ENV */
39 #include <afs/afs_Admin.h>
40 #include <afs/afs_AdminErrors.h>
41 #include <afs/afs_bosAdmin.h>
42 #include <afs/afs_clientAdmin.h>
43 #include <afs/afs_utilAdmin.h>
44 #include <afs/afs_vosAdmin.h>
46 #include <afs/dirpath.h>
47 #include <afs/bnode.h>
48 #include <afs/cellconfig.h>
49 #include <afs/bubasics.h>
50 #include <rx/rx_null.h>
52 #define UBIK_INTERNALS /* need "internal" symbols from ubik.h */
55 #include "cfginternal.h"
56 #include "afs_cfgAdmin.h"
59 /* Local declarations and definitions */
61 #define KASERVER_BOSNAME "kaserver"
62 #define KASERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/kaserver"
64 #define PTSERVER_BOSNAME "ptserver"
65 #define PTSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/ptserver"
67 #define VLSERVER_BOSNAME "vlserver"
68 #define VLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/vlserver"
70 #define BUSERVER_BOSNAME "buserver"
71 #define BUSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/buserver"
73 #define UPSERVER_BOSNAME "upserver"
74 #define UPSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upserver"
76 #define UPCLIENT_BOSNAME "upclient"
77 #define UPCLIENT_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upclient"
79 #define FILESERVER_BOSNAME "fs"
80 #define FILESERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/fileserver"
81 #define VOLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/volserver"
82 #define SALVAGER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/salvager"
86 SimpleProcessStart(void *bosHandle,
88 const char *executable,
93 FsProcessStart(void *bosHandle,
95 const char *fileserverExe,
96 const char *volserverExe,
97 const char *salvagerExe,
101 BosProcessDelete(void *bosHandle,
102 const char *instance,
106 UpdateCommandParse(char *cmdString,
111 UbikQuorumCheck(cfg_host_p cfg_host,
112 const char *dbInstance,
117 UbikVoteStatusFetch(int serverAddr,
118 unsigned short serverPort,
128 /* ---------------- Exported constants ---------------- */
130 const char *cfg_kaserverBosName = KASERVER_BOSNAME;
131 const char *cfg_ptserverBosName = PTSERVER_BOSNAME;
132 const char *cfg_vlserverBosName = VLSERVER_BOSNAME;
133 const char *cfg_buserverBosName = BUSERVER_BOSNAME;
134 const char *cfg_fileserverBosName = FILESERVER_BOSNAME;
135 const char *cfg_upserverBosName = UPSERVER_BOSNAME;
137 const char *cfg_upclientBosNamePrefix = UPCLIENT_BOSNAME;
138 const char *cfg_upclientSysBosSuffix = "etc";
139 const char *cfg_upclientBinBosSuffix = "bin";
143 /* ---------------- Exported BOS Server functions ------------------ */
147 * cfg_BosServerStart() -- Start the BOS server on host.
149 * Timeout is the maximum time, in seconds, to wait for BOS to start.
152 cfg_BosServerStart(void *hostHandle, /* host config handle */
153 short noAuth, /* start in NoAuth mode */
154 unsigned int timeout, /* timeout (in seconds) */
155 afs_status_p st) /* completion status */
158 afs_status_t tst2, tst = 0;
159 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
160 short wasRunning = 0;
162 /* validate parameters */
164 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
168 /* remote configuration not yet supported in this function */
171 if (!cfg_host->is_local) {
172 tst = ADMCFGNOTSUPPORTED;
176 /* start bosserver (if not already running) */
179 /* Windows - bosserver is controlled via the BOS control service */
182 LPCTSTR auxArgBuf[1], *auxArgv;
187 auxArgBuf[0] = "-noauth";
193 if (!cfgutil_WindowsServiceStart(AFSREG_SVR_SVC_NAME,
199 /* failed to start BOS control service */
206 /* function not yet implemented for Unix */
207 tst = ADMCFGNOTSUPPORTED;
209 #endif /* AFS_NT40_ENV */
211 /* put bosserver into requested auth mode if was already running */
213 if (tst == 0 && wasRunning) {
214 if (!cfgutil_HostSetNoAuthFlag(cfg_host, noAuth, &tst2)) {
220 /* indicate failure */
232 * cfg_BosServerStop() -- Stop the BOS server on host.
234 * Timeout is the maximum time, in seconds, to wait for BOS to stop.
237 cfg_BosServerStop(void *hostHandle, /* host config handle */
238 unsigned int timeout, /* timeout (in seconds) */
239 afs_status_p st) /* completion status */
242 afs_status_t tst2, tst = 0;
243 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
245 /* validate parameters */
247 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
251 /* remote configuration not yet supported in this function */
254 if (!cfg_host->is_local) {
255 tst = ADMCFGNOTSUPPORTED;
259 /* stop the bosserver (if running) */
262 /* Windows - bosserver is controlled via the BOS control service */
266 if (!cfgutil_WindowsServiceStop(AFSREG_SVR_SVC_NAME,
270 /* failed to stop BOS control service */
276 /* function not yet implemented for Unix */
277 tst = ADMCFGNOTSUPPORTED;
279 #endif /* AFS_NT40_ENV */
282 /* indicate failure */
293 * cfg_BosServerQueryStatus() -- Query status of BOS server on host.
295 * The argument *isBosProcP is set to TRUE only if BOS processes
296 * are currently executing (as opposed to configured but stopped).
299 cfg_BosServerQueryStatus(void *hostHandle, /* host config handle */
300 short *isStartedP, /* BOS server is started */
301 short *isBosProcP, /* BOS processes running */
302 afs_status_p st) /* completion status */
305 afs_status_t tst2, tst = 0;
306 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
308 /* validate parameters and prepare host handle for bos functions */
310 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
312 } else if (isStartedP == NULL) {
313 tst = ADMCFGSTARTEDFLAGPNULL;
314 } else if (isBosProcP == NULL) {
315 tst = ADMCFGBOSSERVERPROCSFLAGPNULL;
316 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
320 /* remote configuration not yet supported in this function */
323 if (!cfg_host->is_local) {
324 tst = ADMCFGNOTSUPPORTED;
328 /* determine if bosserver is running */
331 /* Windows - bosserver is controlled via the BOS control service */
335 *isStartedP = *isBosProcP = 0;
337 if (!cfgutil_WindowsServiceQuery(AFSREG_SVR_SVC_NAME,
341 } else if (svcState == SERVICE_RUNNING) {
347 /* function not yet implemented for Unix */
348 tst = ADMCFGNOTSUPPORTED;
350 #endif /* AFS_NT40_ENV */
353 /* query status of bos processes */
355 if (tst == 0 && *isStartedP) {
360 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle,
365 /* iterate over process names, checking status of each */
366 char procName[BOS_MAX_NAME_LEN];
367 bos_ProcessExecutionState_t procState;
368 char procAuxState[BOS_MAX_NAME_LEN];
372 if (!bos_ProcessNameGetNext(procIter,
374 /* no more processes (or failure) */
375 if (tst2 != ADMITERATORDONE) {
380 } else if (!bos_ProcessExecutionStateGet(cfg_host->bosHandle,
385 /* process removed (or failure) */
386 if (tst2 != BZNOENT) {
392 if (procState != BOS_PROCESS_STOPPED) {
399 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
406 /* indicate failure */
418 /* ---------------- Exported Database Server functions ------------------ */
423 * cfg_AuthServerStart() -- Start authentication server on host and wait
424 * for server to be ready to accept requests.
426 * This function is intended to be used when configuring the first
427 * machine in a cell; it enables the AFS server principal to be created
428 * and configured before starting the remaining database servers.
431 cfg_AuthServerStart(void *hostHandle, /* host config handle */
432 afs_status_p st) /* completion status */
435 afs_status_t tst2, tst = 0;
436 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
438 /* validate parameters and prepare host handle for bos functions */
440 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
442 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
446 /* create and start authentication server instance */
449 if (!SimpleProcessStart(cfg_host->bosHandle,
451 KASERVER_EXEPATH, NULL, &tst2)) {
456 /* wait for authentication server to achieve quorum */
459 time_t timeStart = time(NULL);
463 if (!UbikQuorumCheck(cfg_host,
464 KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
468 } else if (kaHasQuorum) {
469 /* quorum on authentication server */
473 /* quorum not yet achieved on authentication server */
474 if (difftime(time(NULL), timeStart) > 180) {
475 tst = ADMCFGQUORUMWAITTIMEOUT;
485 /* indicate failure */
496 * cfg_DbServersStart() -- Start the standard (required) database servers,
497 * and optionally the backup database server, on host.
499 * The BOS instance names used are the string constants:
500 * cfg_kaserverBosName - authentication server
501 * cfg_ptserverBosName - protection server
502 * cfg_vlserverBosName - volume location server
503 * cfg_buserverBosName - backup server
506 cfg_DbServersStart(void *hostHandle, /* host config handle */
507 short startBkDb, /* start backup server */
508 afs_status_p st) /* completion status */
511 afs_status_t tst2, tst = 0;
512 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
514 /* validate parameters and prepare host handle for bos functions */
516 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
518 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
522 /* create and start database server instances */
525 /* try all regardless of failures; last error code wins */
526 if (!SimpleProcessStart(cfg_host->bosHandle,
528 KASERVER_EXEPATH, NULL, &tst2)) {
531 if (!SimpleProcessStart(cfg_host->bosHandle,
533 PTSERVER_EXEPATH, NULL, &tst2)) {
536 if (!SimpleProcessStart(cfg_host->bosHandle,
538 VLSERVER_EXEPATH, NULL, &tst2)) {
542 !SimpleProcessStart(cfg_host->bosHandle,
544 BUSERVER_EXEPATH, NULL, &tst2)) {
550 /* indicate failure */
561 * cfg_DbServersStop() -- Stop, and unconfigure, the database servers on host.
564 cfg_DbServersStop(void *hostHandle, /* host config handle */
565 afs_status_p st) /* completion status */
568 afs_status_t tst2, tst = 0;
569 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
571 /* validate parameters and prepare host handle for bos functions */
573 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
575 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
579 /* stop and delete database server instances */
582 /* try all regardless of failures; last error code wins */
583 if (!BosProcessDelete(cfg_host->bosHandle, KASERVER_BOSNAME, &tst2)) {
586 if (!BosProcessDelete(cfg_host->bosHandle, PTSERVER_BOSNAME, &tst2)) {
589 if (!BosProcessDelete(cfg_host->bosHandle, VLSERVER_BOSNAME, &tst2)) {
592 if (!BosProcessDelete(cfg_host->bosHandle, BUSERVER_BOSNAME, &tst2)) {
598 /* indicate failure */
609 * cfg_DbServersQueryStatus() -- Query status of database servers on host.
611 * If detailed status information is not required, detailsP can be NULL.
613 * If *isStdDbP is FALSE and *isBkDbP is TRUE then the host is in an
614 * inconsistent state; the remaining database servers should be configured.
617 cfg_DbServersQueryStatus(void *hostHandle, /* host config handle */
618 short *isStdDbP, /* std DB servers configured */
619 short *isBkDbP, /* backup DB server configured */
620 cfg_dbServersStatus_t *detailsP, /* config details */
621 afs_status_p st) /* completion status */
624 afs_status_t tst2, tst = 0;
625 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
626 short inCellServDb, isKaserver, isPtserver, isVlserver, isBuserver;
628 inCellServDb = isKaserver = isPtserver = isVlserver = isBuserver = 0;
630 /* validate parameters and prepare host handle for bos functions */
632 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
634 } else if (isStdDbP == NULL || isBkDbP == NULL) {
635 tst = ADMCFGDBSERVERCONFIGFLAGPNULL;
636 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
640 /* query host's server CellServDb to see if it lists itself */
643 char hostNameAlias[MAXHOSTCHARS];
645 if (!cfgutil_HostNameGetCellServDbAlias(cfg_host->hostName,
650 } else if (*hostNameAlias != '\0') {
651 /* host in its own CellServDb */
656 /* query bosserver to determine what database servers are configured */
659 bos_ProcessType_t procType;
660 bos_ProcessInfo_t procInfo;
662 if (bos_ProcessInfoGet(cfg_host->bosHandle,
664 &procType, &procInfo, &tst2)) {
666 } else if (tst2 != BZNOENT) {
671 if (bos_ProcessInfoGet(cfg_host->bosHandle,
673 &procType, &procInfo, &tst2)) {
675 } else if (tst2 != BZNOENT) {
681 if (bos_ProcessInfoGet(cfg_host->bosHandle,
683 &procType, &procInfo, &tst2)) {
685 } else if (tst2 != BZNOENT) {
691 if (bos_ProcessInfoGet(cfg_host->bosHandle,
693 &procType, &procInfo, &tst2)) {
695 } else if (tst2 != BZNOENT) {
702 /* success; return results */
703 *isStdDbP = (inCellServDb && isKaserver && isPtserver && isVlserver);
704 *isBkDbP = (inCellServDb && isBuserver);
707 detailsP->inCellServDb = inCellServDb;
708 detailsP->isKaserver = isKaserver;
709 detailsP->isPtserver = isPtserver;
710 detailsP->isVlserver = isVlserver;
711 detailsP->isBuserver = isBuserver;
714 /* indicate failure */
725 * cfg_DbServersRestartAll() -- Restart all database servers in host's cell.
728 cfg_DbServersRestartAll(void *hostHandle, /* host config handle */
729 afs_status_p st) /* completion status */
732 afs_status_t tst2, tst = 0;
733 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
735 /* validate parameters and prepare host handle for bos functions */
737 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
739 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
743 /* restart all database servers in host's cell */
748 if (!bos_HostGetBegin(cfg_host->bosHandle,
753 /* iterate over server CellServDb, restarting db servers */
754 char dbhostName[BOS_MAX_NAME_LEN];
758 while (!dbhostDone) {
759 if (!bos_HostGetNext(dbIter,
760 dbhostName, &tst2)) {
761 /* no more entries (or failure) */
762 if (tst2 != ADMITERATORDONE) {
767 } else if (!bos_ServerOpen(cfg_host->cellHandle,
771 /* failed to get bos handle; note error but keep going */
775 /* restart db servers; note errors, but keep going */
776 if (!bos_ProcessRestart(dbhostHandle,
777 KASERVER_BOSNAME, &tst2)) {
780 if (!bos_ProcessRestart(dbhostHandle,
781 PTSERVER_BOSNAME, &tst2)) {
784 if (!bos_ProcessRestart(dbhostHandle,
785 VLSERVER_BOSNAME, &tst2)) {
788 if (!bos_ProcessRestart(dbhostHandle,
789 BUSERVER_BOSNAME, &tst2)) {
790 /* may not be running a backup server */
791 if (tst2 != BZNOENT) {
796 if (!bos_ServerClose(dbhostHandle, &tst2)) {
802 if (!bos_HostGetDone(dbIter, &tst2)) {
809 /* indicate failure */
812 /* should really utilize a callback (or some other mechanism) to
813 * indicate which restarts failed and why.
824 * cfg_DbServersWaitForQuorum() -- Wait for database servers in host's cell
827 * Timeout is the maximum time, in seconds, to wait for quorum.
829 * NOTE: Function does not check for backup server quorum since
830 * configuration does not require modifying the backup database.
833 cfg_DbServersWaitForQuorum(void *hostHandle, /* host config handle */
834 unsigned int timeout, /* timeout in sec. */
835 afs_status_p st) /* completion status */
838 afs_status_t tst2, tst = 0;
839 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
841 /* validate parameters and prepare host handle for bos functions */
843 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
845 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
849 /* wait for the database servers in host's cell to achieve quorum */
852 time_t timeStart = time(NULL);
853 short kaHasQuorum, ptHasQuorum, vlHasQuorum;
855 kaHasQuorum = ptHasQuorum = vlHasQuorum = 0;
859 if (!UbikQuorumCheck(cfg_host,
860 KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
867 if (!UbikQuorumCheck(cfg_host,
868 PTSERVER_BOSNAME, &ptHasQuorum, &tst2)) {
875 if (!UbikQuorumCheck(cfg_host,
876 VLSERVER_BOSNAME, &vlHasQuorum, &tst2)) {
882 if (kaHasQuorum && ptHasQuorum && vlHasQuorum) {
883 /* quorum on all dbservers of interest */
886 /* quorum not yet achieved for one or more dbservers */
887 if ((timeout == 0) ||
888 (difftime(time(NULL), timeStart) > timeout)) {
889 tst = ADMCFGQUORUMWAITTIMEOUT;
899 /* indicate failure */
911 * cfg_DbServersStopAllBackup() -- Stop, and unconfigure, all backup servers
915 cfg_DbServersStopAllBackup(void *hostHandle, /* host config handle */
916 afs_status_p st) /* completion status */
919 afs_status_t tst2, tst = 0;
920 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
922 /* validate parameters and prepare host handle for bos functions */
924 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
926 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
930 /* stop and delete all backup servers in host's cell */
935 if (!bos_HostGetBegin(cfg_host->bosHandle,
940 /* iterate over server CellServDb, unconfiguring backup servers */
941 char dbhostName[BOS_MAX_NAME_LEN];
945 while (!dbhostDone) {
946 if (!bos_HostGetNext(dbIter,
947 dbhostName, &tst2)) {
948 /* no more entries (or failure) */
949 if (tst2 != ADMITERATORDONE) {
954 } else if (!bos_ServerOpen(cfg_host->cellHandle,
958 /* failed to get bos handle; note error but keep going */
962 /* unconfig backup server; note errors, but keep going */
963 if (!BosProcessDelete(dbhostHandle,
964 BUSERVER_BOSNAME, &tst2)) {
968 if (!bos_ServerClose(dbhostHandle, &tst2)) {
974 if (!bos_HostGetDone(dbIter, &tst2)) {
981 /* indicate failure */
984 /* should really utilize a callback (or some other mechanism) to
985 * indicate which stops failed and why.
998 /* ---------------- Exported File Server functions ------------------ */
1002 * cfg_FileServerStart() -- Start the file server on host.
1004 * The BOS instance name used is the string constant cfg_fileserverBosName.
1007 cfg_FileServerStart(void *hostHandle, /* host config handle */
1008 afs_status_p st) /* completion status */
1011 afs_status_t tst2, tst = 0;
1012 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1014 /* validate parameters and prepare host handle for bos functions */
1016 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1018 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1022 /* create and start file server instance */
1025 if (!FsProcessStart(cfg_host->bosHandle,
1033 /* TO BE DONE: need a reliable "is started and ready" check */
1039 /* indicate failure */
1050 * cfg_FileServerStop() -- Stop, and unconfigure, the file server on host.
1053 cfg_FileServerStop(void *hostHandle, /* host config handle */
1054 afs_status_p st) /* completion status */
1057 afs_status_t tst2, tst = 0;
1058 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1060 /* validate parameters and prepare host handle for bos functions */
1062 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1064 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1068 /* stop and delete file server instance */
1071 if (!BosProcessDelete(cfg_host->bosHandle,
1072 FILESERVER_BOSNAME, &tst2)) {
1075 /* file server instance deleted; remove its addresses from VLDB */
1077 afs_int32 *addrList;
1079 /* note: ignore any errors since address removal is optional;
1080 * e.g., a common source of errors will be attempting to remove
1081 * an address while volumes tied to that address are still listed
1082 * in the VLDB (in which case the address is not removed).
1084 if (cfgutil_HostAddressFetchAll(cfg_host->hostName,
1085 &addrCount, &addrList, &tst2)) {
1086 for (i = 0; i < addrCount; i++) {
1087 (void)vos_FileServerAddressRemove(cfg_host->cellHandle,
1089 addrList[i], &tst2);
1097 /* indicate failure */
1108 * cfg_FileServerQueryStatus() -- Query status of file server on host.
1111 cfg_FileServerQueryStatus(void *hostHandle, /* host config handle */
1112 short *isFsP, /* file server configured */
1113 afs_status_p st) /* completion status */
1116 afs_status_t tst2, tst = 0;
1117 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1119 /* validate parameters and prepare host handle for bos functions */
1121 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1123 } else if (isFsP == NULL) {
1124 tst = ADMCFGFILESERVERCONFIGFLAGPNULL;
1125 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1129 /* query bosserver to determine if fileserver is configured */
1132 bos_ProcessType_t procType;
1133 bos_ProcessInfo_t procInfo;
1137 if (bos_ProcessInfoGet(cfg_host->bosHandle,
1139 &procType, &procInfo, &tst2)) {
1140 /* instance exists; check type for good measure */
1141 if (procType == BOS_PROCESS_FS) {
1144 } else if (tst2 != BZNOENT) {
1150 /* indicate failure */
1162 /* ---------------- Exported Update Server functions ------------------ */
1167 * cfg_UpdateServerStart() -- Start the Update server on host.
1169 * Argument strings exportClear and exportCrypt each specify a set of
1170 * space-separated directories to export or are NULL.
1172 * The BOS instance name used is the string constant cfg_upserverBosName.
1175 cfg_UpdateServerStart(void *hostHandle, /* host config handle */
1176 const char *exportClear, /* dirs to export in clear */
1177 const char *exportCrypt, /* dirs to export encrypted */
1178 afs_status_p st) /* completion status */
1181 afs_status_t tst2, tst = 0;
1182 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1184 /* validate parameters and prepare host handle for bos functions */
1186 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1188 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1192 /* stop and delete existing update server instance, if any.
1193 * we do this because the set of exported directores might be changing.
1197 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1202 /* create and start update server instance */
1205 char argsBuf[AFSDIR_PATH_MAX], *args;
1208 if (exportClear != NULL && *exportClear != '\0') {
1209 argsLen += strlen("-clear ") + strlen(exportClear) + 1;
1211 if (exportCrypt != NULL && *exportCrypt != '\0') {
1212 argsLen += strlen("-crypt ") + strlen(exportCrypt) + 1;
1218 if (argsLen <= AFSDIR_PATH_MAX) {
1221 args = (char *)malloc(argsLen);
1227 if (exportClear == NULL) {
1228 sprintf(args, "-crypt %s", exportCrypt);
1229 } else if (exportCrypt == NULL) {
1230 sprintf(args, "-clear %s", exportClear);
1233 "-clear %s -crypt %s", exportClear, exportCrypt);
1239 if (!SimpleProcessStart(cfg_host->bosHandle,
1241 UPSERVER_EXEPATH, args, &tst2)) {
1245 if (args != NULL && args != argsBuf) {
1252 /* indicate failure */
1263 * cfg_UpdateServerStop() -- Stop, and unconfigure, the Update server on host.
1266 cfg_UpdateServerStop(void *hostHandle, /* host config handle */
1267 afs_status_p st) /* completion status */
1270 afs_status_t tst2, tst = 0;
1271 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1273 /* validate parameters and prepare host handle for bos functions */
1275 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1277 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1281 /* stop and delete upserver instance */
1284 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1290 /* indicate failure */
1301 * cfg_UpdateServerQueryStatus() -- Query status of Update server on host.
1304 cfg_UpdateServerQueryStatus(void *hostHandle, /* host config handle */
1305 short *isUpserverP, /* update server configured */
1306 short *isSysCtrlP, /* system control configured */
1307 short *isBinDistP, /* binary dist configured */
1308 afs_status_p st) /* completion status */
1311 afs_status_t tst2, tst = 0;
1312 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1314 /* validate parameters and prepare host handle for bos functions */
1316 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1318 } else if (isUpserverP == NULL ||
1319 isSysCtrlP == NULL || isBinDistP == NULL) {
1320 tst = ADMCFGUPSERVERCONFIGFLAGPNULL;
1321 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1325 /* query bosserver to determine if, and how, upserver is configured */
1330 *isUpserverP = *isSysCtrlP = *isBinDistP = 0;
1332 if (!bos_ProcessParameterGetBegin(cfg_host->bosHandle,
1337 char cmdString[BOS_MAX_NAME_LEN];
1339 if (!bos_ProcessParameterGetNext(cmdIter, cmdString, &tst2)) {
1340 /* no upserver instance (or error) */
1341 if (tst2 != BZNOENT) {
1345 /* parse upserver command line to determine how configured */
1346 short hasSysPath, hasBinPath;
1348 UpdateCommandParse(cmdString, &hasSysPath, &hasBinPath);
1360 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1367 /* indicate failure */
1378 * cfg_SysBinServerStart() -- Start Update server in System Control and/or
1379 * Binary Distribution machine configuration on host.
1381 * This function is a convenience wrapper for cfg_UpdateServerStart().
1384 cfg_SysBinServerStart(void *hostHandle, /* host config handle */
1385 short makeSysCtrl, /* config as sys control mach */
1386 short makeBinDist, /* config as binary dist mach */
1387 afs_status_p st) /* completion status */
1389 char *cryptSysDir = NULL;
1390 char *clearBinDir = NULL;
1393 cryptSysDir = AFSDIR_CANONICAL_SERVER_ETC_DIRPATH;
1397 clearBinDir = AFSDIR_CANONICAL_SERVER_BIN_DIRPATH;
1400 return cfg_UpdateServerStart(hostHandle, clearBinDir, cryptSysDir, st);
1405 /* ---------------- Exported Update Client functions ------------------ */
1410 * cfg_UpdateClientStart() -- Start an Update client on host.
1412 * Argument string import specifies a set of space-separated directories
1413 * to import. Argument frequency specifies the import interval in
1414 * seconds; if the value is zero (0) then the default frequency is used.
1416 * The BOS instance name used is the concatenation of the string constant
1417 * cfg_upclientBosNamePrefix and the argument string bosSuffix.
1420 cfg_UpdateClientStart(void *hostHandle, /* host config handle */
1421 const char *bosSuffix, /* BOS instance suffix */
1422 const char *upserver, /* upserver to import from */
1423 short crypt, /* import encrypted */
1424 const char *import, /* dirs to import */
1425 unsigned int frequency, /* import interval in sec. */
1426 afs_status_p st) /* completion status */
1429 afs_status_t tst2, tst = 0;
1430 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1431 char upclientInstance[BOS_MAX_NAME_LEN];
1433 /* validate parameters and prepare host handle for bos functions */
1435 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1437 } else if (bosSuffix == NULL) {
1438 tst = ADMCFGUPCLIENTSUFFIXNULL;
1439 } else if ((strlen(UPCLIENT_BOSNAME) +
1440 strlen(bosSuffix) + 1) > BOS_MAX_NAME_LEN) {
1441 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1442 } else if (upserver == NULL || *upserver == '\0') {
1443 tst = ADMCFGUPCLIENTTARGETSERVERNULL;
1444 } else if (import == NULL || *import == '\0') {
1445 tst = ADMCFGUPCLIENTIMPORTDIRNULL;
1446 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1450 /* stop and delete existing update client instance, if any.
1451 * we do this because the set of imported directores might be changing.
1455 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1457 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1462 /* create and start update client instance */
1465 char argsBuf[AFSDIR_PATH_MAX], *args;
1468 argsLen += strlen(upserver) + 1;
1471 argsLen += strlen("-crypt ");
1473 argsLen += strlen("-clear ");
1476 if (frequency != 0) {
1477 argsLen += strlen("-t ") + 10 /* max uint */ + 1;
1480 argsLen += strlen(import) + 1;
1482 if (argsLen <= AFSDIR_PATH_MAX) {
1485 args = (char *)malloc(argsLen);
1491 /* set up argument buffer */
1493 sprintf(args, "%s -crypt ", upserver);
1495 sprintf(args, "%s -clear ", upserver);
1497 if (frequency != 0) {
1498 char *strp = args + strlen(args);
1499 sprintf(strp, "-t %u ", frequency);
1501 strcat(args, import);
1503 /* create and start instance */
1504 if (!SimpleProcessStart(cfg_host->bosHandle,
1506 UPCLIENT_EXEPATH, args, &tst2)) {
1510 if (args != argsBuf) {
1517 /* indicate failure */
1528 * cfg_UpdateClientStop() -- Stop, and unconfigure, an Update client on host.
1531 cfg_UpdateClientStop(void *hostHandle, /* host config handle */
1532 const char *bosSuffix, /* BOS instance suffix */
1533 afs_status_p st) /* completion status */
1536 afs_status_t tst2, tst = 0;
1537 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1538 char upclientInstance[BOS_MAX_NAME_LEN];
1540 /* validate parameters and prepare host handle for bos functions */
1542 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1544 } else if (bosSuffix == NULL) {
1545 tst = ADMCFGUPCLIENTSUFFIXNULL;
1546 } else if ((strlen(UPCLIENT_BOSNAME) +
1547 strlen(bosSuffix) + 1) > BOS_MAX_NAME_LEN) {
1548 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1549 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1553 /* stop and delete specified update client instance */
1556 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1558 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1564 /* indicate failure */
1575 * cfg_UpdateClientStopAll() -- Stop, and unconfigure, all Update clients
1579 cfg_UpdateClientStopAll(void *hostHandle, /* host config handle */
1580 afs_status_p st) /* completion status */
1583 afs_status_t tst2, tst = 0;
1584 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1586 /* validate parameters and prepare host handle for bos functions */
1588 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1590 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1594 /* find, stop, and delete all update client instances */
1599 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle,
1604 /* iterate over process names, looking for update clients */
1605 char procName[BOS_MAX_NAME_LEN];
1609 if (!bos_ProcessNameGetNext(procIter,
1611 /* no more processes (or failure) */
1612 if (tst2 != ADMITERATORDONE) {
1617 } else if (!strncmp(UPCLIENT_BOSNAME,
1619 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1620 /* upclient instance prefix; assume is upclient */
1621 if (!BosProcessDelete(cfg_host->bosHandle,
1630 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1637 /* indicate failure */
1648 * cfg_UpdateClientQueryStatus() -- Query status of Update clients on host.
1651 cfg_UpdateClientQueryStatus(void *hostHandle, /* host config handle */
1652 short *isUpclientP, /* an upclient is configured */
1653 short *isSysP, /* system control client */
1654 short *isBinP, /* binary dist. client */
1655 afs_status_p st) /* completion status */
1658 afs_status_t tst2, tst = 0;
1659 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
1661 /* validate parameters and prepare host handle for bos functions */
1663 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1665 } else if (isUpclientP == NULL || isSysP == NULL || isBinP == NULL) {
1666 tst = ADMCFGUPCLIENTCONFIGFLAGPNULL;
1667 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1671 /* determine if, and how, any upclients are configured */
1676 *isUpclientP = *isSysP = *isBinP = 0;
1678 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle,
1683 /* iterate over process names, looking for update clients */
1684 char procName[BOS_MAX_NAME_LEN];
1688 if (!bos_ProcessNameGetNext(procIter,
1690 /* no more processes (or failure) */
1691 if (tst2 != ADMITERATORDONE) {
1696 } else if (!strncmp(UPCLIENT_BOSNAME,
1698 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1699 /* upclient instance prefix; assume is upclient */
1704 if (!bos_ProcessParameterGetBegin(cfg_host->bosHandle,
1709 char cmdString[BOS_MAX_NAME_LEN];
1711 if (!bos_ProcessParameterGetNext(cmdIter,
1712 cmdString, &tst2)) {
1713 /* instance deleted out from under us (or error) */
1714 if (tst2 != BZNOENT) {
1718 /* parse command line to determine how config */
1719 short hasSysPath, hasBinPath;
1721 UpdateCommandParse(cmdString,
1722 &hasSysPath, &hasBinPath);
1732 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1743 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1750 /* indicate failure */
1761 * cfg_SysControlClientStart() -- Start an Update client in System Control
1762 * client configuration on host.
1764 * This function is a convenience wrapper for cfg_UpdateClientStart().
1765 * The BOS instance suffix used is the constant cfg_upclientSysBosSuffix.
1768 cfg_SysControlClientStart(void *hostHandle, /* host config handle */
1769 const char *upserver, /* upserver to import from */
1770 afs_status_p st) /* completion status */
1772 return cfg_UpdateClientStart(hostHandle,
1773 cfg_upclientSysBosSuffix,
1776 AFSDIR_CANONICAL_SERVER_ETC_DIRPATH,
1777 0 /* default frequency */,
1783 * cfg_BinDistClientStart() -- Start an Update client in Binary Distribution
1784 * client configuration on host.
1786 * This function is a convenience wrapper for cfg_UpdateClientStart().
1787 * The BOS instance suffix used is the constant cfg_upclientBinBosSuffix.
1790 cfg_BinDistClientStart(void *hostHandle, /* host config handle */
1791 const char *upserver, /* upserver to import from */
1792 afs_status_p st) /* completion status */
1794 return cfg_UpdateClientStart(hostHandle,
1795 cfg_upclientBinBosSuffix,
1798 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
1799 0 /* default frequency */,
1805 /* ---------------- Local functions ------------------ */
1808 * SimpleProcessStart() -- create and start a simple bosserver instance.
1810 * RETURN CODES: 1 success, 0 failure (st indicates why)
1813 SimpleProcessStart(void *bosHandle,
1814 const char *instance,
1815 const char *executable,
1820 afs_status_t tst2, tst = 0;
1821 char cmdBuf[AFSDIR_PATH_MAX], *cmd;
1824 cmdLen = strlen(executable) + 1 + (args == NULL ? 0 : (strlen(args) + 1));
1826 if (cmdLen <= AFSDIR_PATH_MAX) {
1829 cmd = (char *)malloc(cmdLen);
1836 strcpy(cmd, executable);
1838 sprintf(cmd, "%s %s", executable, args);
1841 if (!bos_ProcessCreate(bosHandle,
1845 NULL, NULL, &tst2) &&
1847 /* failed to create instance (and not because existed) */
1849 } else if (!bos_ProcessExecutionStateSet(bosHandle,
1851 BOS_PROCESS_RUNNING,
1853 /* failed to set instance state to running */
1857 if (cmd != cmdBuf) {
1863 /* indicate failure */
1875 * FsProcessStart() -- create and start a fs bosserver instance.
1877 * RETURN CODES: 1 success, 0 failure (st indicates why)
1880 FsProcessStart(void *bosHandle,
1881 const char *instance,
1882 const char *fileserverExe,
1883 const char *volserverExe,
1884 const char *salvagerExe,
1888 afs_status_t tst2, tst = 0;
1890 if (!bos_FSProcessCreate(bosHandle,
1892 fileserverExe, volserverExe, salvagerExe,
1895 /* failed to create instance (and not because existed) */
1897 } else if (!bos_ProcessExecutionStateSet(bosHandle,
1899 BOS_PROCESS_RUNNING,
1901 /* failed to set instance state to running */
1906 /* indicate failure */
1918 * BosProcessDelete() -- stop and delete a bosserver instance, if it exists.
1920 * RETURN CODES: 1 success, 0 failure (st indicates why)
1923 BosProcessDelete(void *bosHandle,
1924 const char *instance,
1928 afs_status_t tst2, tst = 0;
1930 if (!bos_ProcessExecutionStateSet(bosHandle,
1932 BOS_PROCESS_STOPPED,
1934 /* failed to set instance state to stopped (or does not exist) */
1935 if (tst2 != BZNOENT) {
1939 } else if (!bos_ProcessAllWaitTransition(bosHandle, &tst2)) {
1940 /* failed to wait for process to stop */
1943 } else if (!bos_ProcessDelete(bosHandle, instance, &tst2)) {
1944 /* failed to delete instance (or does not exist) */
1945 if (tst2 != BZNOENT) {
1951 /* indicate failure */
1962 * UpdateCommandParse() -- Parse an upserver or upclient command to determine:
1963 * 1) if it explicitly exports/imports the system control directory
1964 * 2) if it explicitly exports/imports the binary directory
1966 * NOTE: cmdString altered (made all lower case and forward slashes)
1969 UpdateCommandParse(char *cmdString,
1975 *hasSysPathP = *hasBinPathP = 0;
1977 /* make command string all lower case and forward slashes */
1979 for (argp = cmdString; *argp != '\0'; argp++) {
1980 if (isupper(*argp)) {
1981 *argp = tolower(*argp);
1982 } else if (*argp == '\\') {
1987 /* find end of update executable path (and hence beginning of arguments */
1991 while (isspace(*argp)) {
1994 while (*argp != '\0' && !isspace(*argp)) {
1998 /* search for well-known system control directory */
2000 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_ETC_DIRPATH);
2003 /* check that not a portition of a larger path */
2004 char oneBefore, oneAfter, twoAfter;
2006 oneBefore = *(dirp - 1);
2007 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH) - 1);
2009 if (oneAfter != '\0') {
2010 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH));
2013 if (isspace(oneBefore)) {
2014 if ((isspace(oneAfter)) ||
2015 (oneAfter == '\0') ||
2016 (oneAfter == '/' && (isspace(twoAfter) || twoAfter == '\0'))) {
2022 /* search for well-known binary directory */
2024 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
2027 /* check that not a portition of a larger path */
2028 char oneBefore, oneAfter, twoAfter;
2030 oneBefore = *(dirp - 1);
2031 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH) - 1);
2033 if (oneAfter != '\0') {
2034 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH));
2037 if (isspace(oneBefore)) {
2038 if ((isspace(oneAfter)) ||
2039 (oneAfter == '\0') ||
2040 (oneAfter == '/' && (isspace(twoAfter) || twoAfter == '\0'))) {
2050 * UbikQuorumCheck() -- Determine if Ubik has achieved quorum for a specified
2051 * database instance in host's cell.
2053 * RETURN CODES: 1 success, 0 failure (st indicates why)
2056 UbikQuorumCheck(cfg_host_p cfg_host,
2057 const char *dbInstance,
2062 afs_status_t tst2, tst = 0;
2067 if (!bos_HostGetBegin(cfg_host->bosHandle,
2072 /* iterate over server CellServDb, looking for dbserver sync site */
2073 char dbhostName[BOS_MAX_NAME_LEN];
2075 unsigned short dbhostPort = 0;
2077 int dbhostQueries = 0;
2079 if (!strcmp(dbInstance, KASERVER_BOSNAME)) {
2080 dbhostPort = AFSCONF_KAUTHPORT;
2081 } else if (!strcmp(dbInstance, PTSERVER_BOSNAME)) {
2082 dbhostPort = AFSCONF_PROTPORT;
2083 } else if (!strcmp(dbInstance, VLSERVER_BOSNAME)) {
2084 dbhostPort = AFSCONF_VLDBPORT;
2085 } else if (!strcmp(dbInstance, BUSERVER_BOSNAME)) {
2086 dbhostPort = AFSCONF_BUDBPORT;
2089 while (!dbhostDone) {
2090 if (!bos_HostGetNext(dbIter,
2091 dbhostName, &tst2)) {
2092 /* no more entries (or failure) */
2093 if (tst2 == ADMITERATORDONE) {
2094 if (dbhostQueries == 0) {
2095 /* consider quorum to have been achieved when no
2096 * database servers in cell; otherwise higher-level
2097 * functions will timeout and fail.
2106 } else if (!util_AdminServerAddressGetFromName(dbhostName,
2112 short isSyncSite, isWriteReady;
2114 /* ignore errors fetching Ubik vote status; there might be
2115 * an unreachable dbserver yet a reachable sync site.
2119 if (UbikVoteStatusFetch(dbhostAddr,
2124 /* have quorum if is sync site AND is ready for updates */
2135 if (!bos_HostGetDone(dbIter, &tst2)) {
2141 /* indicate failure */
2152 * UbikVoteStatusFetch() -- Fetch Ubik vote status parameters of interest from
2153 * specified server and port.
2155 * RETURN CODES: 1 success, 0 failure (st indicates why)
2158 UbikVoteStatusFetch(int serverAddr,
2159 unsigned short serverPort,
2161 short *isWriteReady,
2165 afs_status_t tst = 0;
2166 struct rx_securityClass *nullSecurity;
2167 struct rx_connection *serverConn;
2169 nullSecurity = rxnull_NewClientSecurityObject(); /* never fails */
2171 if ((serverConn = rx_GetCachedConnection(htonl(serverAddr),
2176 tst = ADMCFGUBIKVOTENOCONNECTION;
2179 struct ubik_debug udebugInfo;
2180 extern int VOTE_Debug(), VOTE_DebugOld();
2182 if ((rpcCode = VOTE_Debug(serverConn, &udebugInfo)) == 0) {
2183 /* talking to a 3.5 or later server */
2184 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2188 /* as of 3.5 the database is writeable if "labeled" or if all
2189 * prior recovery states have been achieved; see defect 9477.
2191 if (((udebugInfo.recoveryState & UBIK_RECLABELDB )) ||
2193 ((udebugInfo.recoveryState & UBIK_RECSYNCSITE) &&
2194 (udebugInfo.recoveryState & UBIK_RECFOUNDDB ) &&
2195 (udebugInfo.recoveryState & UBIK_RECHAVEDB ))) {
2200 } else if (rpcCode == RXGEN_OPCODE) {
2201 /* talking to old (pre 3.5) server */
2202 struct ubik_debug_old udebugInfo;
2204 if ((rpcCode = VOTE_DebugOld(serverConn, &udebugInfo)) == 0) {
2205 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2209 /* pre 3.5 the database is writeable only if "labeled" */
2210 if (udebugInfo.recoveryState & UBIK_RECLABELDB) {
2217 (void) rx_ReleaseCachedConnection(serverConn);
2223 /* indicate failure */