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 */
40 #include <rx/rxstat.h>
42 #include <afs/afs_Admin.h>
43 #include <afs/afs_AdminErrors.h>
44 #include <afs/afs_bosAdmin.h>
45 #include <afs/afs_clientAdmin.h>
46 #include <afs/afs_utilAdmin.h>
47 #include <afs/afs_vosAdmin.h>
49 #include <afs/dirpath.h>
50 #include <afs/bnode.h>
51 #include <afs/cellconfig.h>
52 #include <afs/bubasics.h>
53 #include <rx/rx_null.h>
55 #define UBIK_INTERNALS /* need "internal" symbols from ubik.h */
58 #include "cfginternal.h"
59 #include "afs_cfgAdmin.h"
62 /* Local declarations and definitions */
64 #define KASERVER_BOSNAME "kaserver"
65 #define KASERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/kaserver"
67 #define PTSERVER_BOSNAME "ptserver"
68 #define PTSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/ptserver"
70 #define VLSERVER_BOSNAME "vlserver"
71 #define VLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/vlserver"
73 #define BUSERVER_BOSNAME "buserver"
74 #define BUSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/buserver"
76 #define UPSERVER_BOSNAME "upserver"
77 #define UPSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upserver"
79 #define UPCLIENT_BOSNAME "upclient"
80 #define UPCLIENT_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/upclient"
82 #define FILESERVER_BOSNAME "fs"
83 #define FILESERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/fileserver"
84 #define VOLSERVER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/volserver"
85 #define SALVAGER_EXEPATH AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/salvager"
89 SimpleProcessStart(void *bosHandle, const char *instance,
90 const char *executable, const char *args,
94 FsProcessStart(void *bosHandle, const char *instance,
95 const char *fileserverExe, const char *volserverExe,
96 const char *salvagerExe, afs_status_p st);
99 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st);
102 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP);
105 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance,
106 short *hasQuorum, afs_status_p st);
109 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
110 short *isSyncSite, short *isWriteReady,
118 /* ---------------- Exported constants ---------------- */
120 const char *cfg_kaserverBosName = KASERVER_BOSNAME;
121 const char *cfg_ptserverBosName = PTSERVER_BOSNAME;
122 const char *cfg_vlserverBosName = VLSERVER_BOSNAME;
123 const char *cfg_buserverBosName = BUSERVER_BOSNAME;
124 const char *cfg_fileserverBosName = FILESERVER_BOSNAME;
125 const char *cfg_upserverBosName = UPSERVER_BOSNAME;
127 const char *cfg_upclientBosNamePrefix = UPCLIENT_BOSNAME;
128 const char *cfg_upclientSysBosSuffix = "etc";
129 const char *cfg_upclientBinBosSuffix = "bin";
133 /* ---------------- Exported BOS Server functions ------------------ */
137 * cfg_BosServerStart() -- Start the BOS server on host.
139 * Timeout is the maximum time, in seconds, to wait for BOS to start.
142 cfg_BosServerStart(void *hostHandle, /* host config handle */
143 short noAuth, /* start in NoAuth mode */
144 unsigned int timeout, /* timeout (in seconds) */
146 { /* completion status */
148 afs_status_t tst2, tst = 0;
149 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
150 short wasRunning = 0;
152 /* validate parameters */
154 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
158 /* remote configuration not yet supported in this function */
161 if (!cfg_host->is_local) {
162 tst = ADMCFGNOTSUPPORTED;
166 /* start bosserver (if not already running) */
169 /* Windows - bosserver is controlled via the BOS control service */
172 LPCTSTR auxArgBuf[1], *auxArgv;
177 auxArgBuf[0] = "-noauth";
183 if (!cfgutil_WindowsServiceStart
184 (AFSREG_SVR_SVC_NAME, auxArgc, auxArgv, timeout, &wasRunning,
186 /* failed to start BOS control service */
192 /* function not yet implemented for Unix */
193 tst = ADMCFGNOTSUPPORTED;
195 #endif /* AFS_NT40_ENV */
197 /* put bosserver into requested auth mode if was already running */
199 if (tst == 0 && wasRunning) {
200 if (!cfgutil_HostSetNoAuthFlag(cfg_host, noAuth, &tst2)) {
206 /* indicate failure */
218 * cfg_BosServerStop() -- Stop the BOS server on host.
220 * Timeout is the maximum time, in seconds, to wait for BOS to stop.
223 cfg_BosServerStop(void *hostHandle, /* host config handle */
224 unsigned int timeout, /* timeout (in seconds) */
226 { /* completion status */
228 afs_status_t tst2, tst = 0;
229 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
231 /* validate parameters */
233 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
237 /* remote configuration not yet supported in this function */
240 if (!cfg_host->is_local) {
241 tst = ADMCFGNOTSUPPORTED;
245 /* stop the bosserver (if running) */
248 /* Windows - bosserver is controlled via the BOS control service */
252 if (!cfgutil_WindowsServiceStop
253 (AFSREG_SVR_SVC_NAME, timeout, &wasStopped, &tst2)) {
254 /* failed to stop BOS control service */
260 /* function not yet implemented for Unix */
261 tst = ADMCFGNOTSUPPORTED;
263 #endif /* AFS_NT40_ENV */
266 /* indicate failure */
277 * cfg_BosServerQueryStatus() -- Query status of BOS server on host.
279 * The argument *isBosProcP is set to TRUE only if BOS processes
280 * are currently executing (as opposed to configured but stopped).
283 cfg_BosServerQueryStatus(void *hostHandle, /* host config handle */
284 short *isStartedP, /* BOS server is started */
285 short *isBosProcP, /* BOS processes running */
287 { /* completion status */
289 afs_status_t tst2, tst = 0;
290 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
292 /* validate parameters and prepare host handle for bos functions */
294 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
296 } else if (isStartedP == NULL) {
297 tst = ADMCFGSTARTEDFLAGPNULL;
298 } else if (isBosProcP == NULL) {
299 tst = ADMCFGBOSSERVERPROCSFLAGPNULL;
300 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
304 /* remote configuration not yet supported in this function */
307 if (!cfg_host->is_local) {
308 tst = ADMCFGNOTSUPPORTED;
312 /* determine if bosserver is running */
315 /* Windows - bosserver is controlled via the BOS control service */
319 *isStartedP = *isBosProcP = 0;
321 if (!cfgutil_WindowsServiceQuery
322 (AFSREG_SVR_SVC_NAME, &svcState, &tst2)) {
324 } else if (svcState == SERVICE_RUNNING) {
330 /* function not yet implemented for Unix */
331 tst = ADMCFGNOTSUPPORTED;
333 #endif /* AFS_NT40_ENV */
336 /* query status of bos processes */
338 if (tst == 0 && *isStartedP) {
343 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
346 /* iterate over process names, checking status of each */
347 char procName[BOS_MAX_NAME_LEN];
348 bos_ProcessExecutionState_t procState;
349 char procAuxState[BOS_MAX_NAME_LEN];
353 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
354 /* no more processes (or failure) */
355 if (tst2 != ADMITERATORDONE) {
361 if (!bos_ProcessExecutionStateGet
362 (cfg_host->bosHandle, procName, &procState,
363 procAuxState, &tst2)) {
364 /* process removed (or failure) */
365 if (tst2 != BZNOENT) {
371 if (procState != BOS_PROCESS_STOPPED) {
378 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
385 /* indicate failure */
397 /* ---------------- Exported Database Server functions ------------------ */
402 * cfg_AuthServerStart() -- Start authentication server on host and wait
403 * for server to be ready to accept requests.
405 * This function is intended to be used when configuring the first
406 * machine in a cell; it enables the AFS server principal to be created
407 * and configured before starting the remaining database servers.
410 cfg_AuthServerStart(void *hostHandle, /* host config handle */
412 { /* completion status */
414 afs_status_t tst2, tst = 0;
415 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
417 /* validate parameters and prepare host handle for bos functions */
419 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
421 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
425 /* create and start authentication server instance */
428 if (!SimpleProcessStart
429 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
435 /* wait for authentication server to achieve quorum */
438 time_t timeStart = time(NULL);
443 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
447 } else if (kaHasQuorum) {
448 /* quorum on authentication server */
452 /* quorum not yet achieved on authentication server */
453 if (difftime(time(NULL), timeStart) > 180) {
454 tst = ADMCFGQUORUMWAITTIMEOUT;
464 /* indicate failure */
475 * cfg_DbServersStart() -- Start the standard (required) database servers,
476 * and optionally the backup database server, on host.
478 * The BOS instance names used are the string constants:
479 * cfg_kaserverBosName - authentication server
480 * cfg_ptserverBosName - protection server
481 * cfg_vlserverBosName - volume location server
482 * cfg_buserverBosName - backup server
485 cfg_DbServersStart(void *hostHandle, /* host config handle */
486 short startBkDb, /* start backup server */
488 { /* completion status */
490 afs_status_t tst2, tst = 0;
491 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
493 /* validate parameters and prepare host handle for bos functions */
495 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
497 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
501 /* create and start database server instances */
504 /* try all regardless of failures; last error code wins */
505 if (!SimpleProcessStart
506 (cfg_host->bosHandle, KASERVER_BOSNAME, KASERVER_EXEPATH, NULL,
510 if (!SimpleProcessStart
511 (cfg_host->bosHandle, PTSERVER_BOSNAME, PTSERVER_EXEPATH, NULL,
515 if (!SimpleProcessStart
516 (cfg_host->bosHandle, VLSERVER_BOSNAME, VLSERVER_EXEPATH, NULL,
521 && !SimpleProcessStart(cfg_host->bosHandle, BUSERVER_BOSNAME,
522 BUSERVER_EXEPATH, NULL, &tst2)) {
528 /* indicate failure */
539 * cfg_DbServersStop() -- Stop, and unconfigure, the database servers on host.
542 cfg_DbServersStop(void *hostHandle, /* host config handle */
544 { /* completion status */
546 afs_status_t tst2, tst = 0;
547 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
549 /* validate parameters and prepare host handle for bos functions */
551 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
553 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
557 /* stop and delete database server instances */
560 /* try all regardless of failures; last error code wins */
561 if (!BosProcessDelete(cfg_host->bosHandle, KASERVER_BOSNAME, &tst2)) {
564 if (!BosProcessDelete(cfg_host->bosHandle, PTSERVER_BOSNAME, &tst2)) {
567 if (!BosProcessDelete(cfg_host->bosHandle, VLSERVER_BOSNAME, &tst2)) {
570 if (!BosProcessDelete(cfg_host->bosHandle, BUSERVER_BOSNAME, &tst2)) {
576 /* indicate failure */
587 * cfg_DbServersQueryStatus() -- Query status of database servers on host.
589 * If detailed status information is not required, detailsP can be NULL.
591 * If *isStdDbP is FALSE and *isBkDbP is TRUE then the host is in an
592 * inconsistent state; the remaining database servers should be configured.
595 cfg_DbServersQueryStatus(void *hostHandle, /* host config handle */
596 short *isStdDbP, /* std DB servers configured */
597 short *isBkDbP, /* backup DB server configured */
598 cfg_dbServersStatus_t * detailsP, /* config details */
600 { /* completion status */
602 afs_status_t tst2, tst = 0;
603 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
604 short inCellServDb, isKaserver, isPtserver, isVlserver, isBuserver;
606 inCellServDb = isKaserver = isPtserver = isVlserver = isBuserver = 0;
608 /* validate parameters and prepare host handle for bos functions */
610 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
612 } else if (isStdDbP == NULL || isBkDbP == NULL) {
613 tst = ADMCFGDBSERVERCONFIGFLAGPNULL;
614 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
618 /* query host's server CellServDb to see if it lists itself */
621 char hostNameAlias[MAXHOSTCHARS];
623 if (!cfgutil_HostNameGetCellServDbAlias
624 (cfg_host->hostName, cfg_host->hostName, hostNameAlias, &tst2)) {
626 } else if (*hostNameAlias != '\0') {
627 /* host in its own CellServDb */
632 /* query bosserver to determine what database servers are configured */
635 bos_ProcessType_t procType;
636 bos_ProcessInfo_t procInfo;
638 if (bos_ProcessInfoGet
639 (cfg_host->bosHandle, KASERVER_BOSNAME, &procType, &procInfo,
642 } else if (tst2 != BZNOENT) {
647 if (bos_ProcessInfoGet
648 (cfg_host->bosHandle, PTSERVER_BOSNAME, &procType, &procInfo,
651 } else if (tst2 != BZNOENT) {
657 if (bos_ProcessInfoGet
658 (cfg_host->bosHandle, VLSERVER_BOSNAME, &procType, &procInfo,
661 } else if (tst2 != BZNOENT) {
667 if (bos_ProcessInfoGet
668 (cfg_host->bosHandle, BUSERVER_BOSNAME, &procType, &procInfo,
671 } else if (tst2 != BZNOENT) {
678 /* success; return results */
679 *isStdDbP = (inCellServDb && isKaserver && isPtserver && isVlserver);
680 *isBkDbP = (inCellServDb && isBuserver);
683 detailsP->inCellServDb = inCellServDb;
684 detailsP->isKaserver = isKaserver;
685 detailsP->isPtserver = isPtserver;
686 detailsP->isVlserver = isVlserver;
687 detailsP->isBuserver = isBuserver;
690 /* indicate failure */
701 * cfg_DbServersRestartAll() -- Restart all database servers in host's cell.
704 cfg_DbServersRestartAll(void *hostHandle, /* host config handle */
706 { /* completion status */
708 afs_status_t tst2, tst = 0;
709 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
711 /* validate parameters and prepare host handle for bos functions */
713 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
715 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
719 /* restart all database servers in host's cell */
724 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
727 /* iterate over server CellServDb, restarting db servers */
728 char dbhostName[BOS_MAX_NAME_LEN];
732 while (!dbhostDone) {
733 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
734 /* no more entries (or failure) */
735 if (tst2 != ADMITERATORDONE) {
742 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
744 /* failed to get bos handle; note error but keep going */
748 /* restart db servers; note errors, but keep going */
749 if (!bos_ProcessRestart
750 (dbhostHandle, KASERVER_BOSNAME, &tst2)) {
753 if (!bos_ProcessRestart
754 (dbhostHandle, PTSERVER_BOSNAME, &tst2)) {
757 if (!bos_ProcessRestart
758 (dbhostHandle, VLSERVER_BOSNAME, &tst2)) {
761 if (!bos_ProcessRestart
762 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
763 /* may not be running a backup server */
764 if (tst2 != BZNOENT) {
769 if (!bos_ServerClose(dbhostHandle, &tst2)) {
775 if (!bos_HostGetDone(dbIter, &tst2)) {
782 /* indicate failure */
785 /* should really utilize a callback (or some other mechanism) to
786 * indicate which restarts failed and why.
797 * cfg_DbServersWaitForQuorum() -- Wait for database servers in host's cell
800 * Timeout is the maximum time, in seconds, to wait for quorum.
802 * NOTE: Function does not check for backup server quorum since
803 * configuration does not require modifying the backup database.
806 cfg_DbServersWaitForQuorum(void *hostHandle, /* host config handle */
807 unsigned int timeout, /* timeout in sec. */
809 { /* completion status */
811 afs_status_t tst2, tst = 0;
812 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
814 /* validate parameters and prepare host handle for bos functions */
816 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
818 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
822 /* wait for the database servers in host's cell to achieve quorum */
825 time_t timeStart = time(NULL);
826 short kaHasQuorum, ptHasQuorum, vlHasQuorum;
828 kaHasQuorum = ptHasQuorum = vlHasQuorum = 0;
833 (cfg_host, KASERVER_BOSNAME, &kaHasQuorum, &tst2)) {
841 (cfg_host, PTSERVER_BOSNAME, &ptHasQuorum, &tst2)) {
849 (cfg_host, VLSERVER_BOSNAME, &vlHasQuorum, &tst2)) {
855 if (kaHasQuorum && ptHasQuorum && vlHasQuorum) {
856 /* quorum on all dbservers of interest */
859 /* quorum not yet achieved for one or more dbservers */
861 || (difftime(time(NULL), timeStart) > timeout)) {
862 tst = ADMCFGQUORUMWAITTIMEOUT;
872 /* indicate failure */
884 * cfg_DbServersStopAllBackup() -- Stop, and unconfigure, all backup servers
888 cfg_DbServersStopAllBackup(void *hostHandle, /* host config handle */
890 { /* completion status */
892 afs_status_t tst2, tst = 0;
893 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
895 /* validate parameters and prepare host handle for bos functions */
897 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
899 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
903 /* stop and delete all backup servers in host's cell */
908 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
911 /* iterate over server CellServDb, unconfiguring backup servers */
912 char dbhostName[BOS_MAX_NAME_LEN];
916 while (!dbhostDone) {
917 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
918 /* no more entries (or failure) */
919 if (tst2 != ADMITERATORDONE) {
926 (cfg_host->cellHandle, dbhostName, &dbhostHandle,
928 /* failed to get bos handle; note error but keep going */
932 /* unconfig backup server; note errors, but keep going */
933 if (!BosProcessDelete
934 (dbhostHandle, BUSERVER_BOSNAME, &tst2)) {
938 if (!bos_ServerClose(dbhostHandle, &tst2)) {
944 if (!bos_HostGetDone(dbIter, &tst2)) {
951 /* indicate failure */
954 /* should really utilize a callback (or some other mechanism) to
955 * indicate which stops failed and why.
968 /* ---------------- Exported File Server functions ------------------ */
972 * cfg_FileServerStart() -- Start the file server on host.
974 * The BOS instance name used is the string constant cfg_fileserverBosName.
977 cfg_FileServerStart(void *hostHandle, /* host config handle */
979 { /* completion status */
981 afs_status_t tst2, tst = 0;
982 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
984 /* validate parameters and prepare host handle for bos functions */
986 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
988 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
992 /* create and start file server instance */
996 (cfg_host->bosHandle, FILESERVER_BOSNAME, FILESERVER_EXEPATH,
997 VOLSERVER_EXEPATH, SALVAGER_EXEPATH, &tst2)) {
1000 /* TO BE DONE: need a reliable "is started and ready" check */
1006 /* indicate failure */
1017 * cfg_FileServerStop() -- Stop, and unconfigure, the file server on host.
1020 cfg_FileServerStop(void *hostHandle, /* host config handle */
1022 { /* completion status */
1024 afs_status_t tst2, tst = 0;
1025 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1027 /* validate parameters and prepare host handle for bos functions */
1029 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1031 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1035 /* stop and delete file server instance */
1038 if (!BosProcessDelete(cfg_host->bosHandle, FILESERVER_BOSNAME, &tst2)) {
1041 /* file server instance deleted; remove its addresses from VLDB */
1043 afs_int32 *addrList = NULL;
1045 /* note: ignore any errors since address removal is optional;
1046 * e.g., a common source of errors will be attempting to remove
1047 * an address while volumes tied to that address are still listed
1048 * in the VLDB (in which case the address is not removed).
1050 if (cfgutil_HostAddressFetchAll
1051 (cfg_host->hostName, &addrCount, &addrList, &tst2)) {
1052 for (i = 0; i < addrCount; i++) {
1053 (void)vos_FileServerAddressRemove(cfg_host->cellHandle,
1066 /* indicate failure */
1077 * cfg_FileServerQueryStatus() -- Query status of file server on host.
1080 cfg_FileServerQueryStatus(void *hostHandle, /* host config handle */
1081 short *isFsP, /* file server configured */
1083 { /* completion status */
1085 afs_status_t tst2, tst = 0;
1086 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1088 /* validate parameters and prepare host handle for bos functions */
1090 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1092 } else if (isFsP == NULL) {
1093 tst = ADMCFGFILESERVERCONFIGFLAGPNULL;
1094 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1098 /* query bosserver to determine if fileserver is configured */
1101 bos_ProcessType_t procType;
1102 bos_ProcessInfo_t procInfo;
1106 if (bos_ProcessInfoGet
1107 (cfg_host->bosHandle, FILESERVER_BOSNAME, &procType, &procInfo,
1109 /* instance exists; check type for good measure */
1110 if (procType == BOS_PROCESS_FS) {
1113 } else if (tst2 != BZNOENT) {
1119 /* indicate failure */
1131 /* ---------------- Exported Update Server functions ------------------ */
1136 * cfg_UpdateServerStart() -- Start the Update server on host.
1138 * Argument strings exportClear and exportCrypt each specify a set of
1139 * space-separated directories to export or are NULL.
1141 * The BOS instance name used is the string constant cfg_upserverBosName.
1144 cfg_UpdateServerStart(void *hostHandle, /* host config handle */
1145 const char *exportClear, /* dirs to export in clear */
1146 const char *exportCrypt, /* dirs to export encrypted */
1148 { /* completion status */
1150 afs_status_t tst2, tst = 0;
1151 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1153 /* validate parameters and prepare host handle for bos functions */
1155 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1157 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1161 /* stop and delete existing update server instance, if any.
1162 * we do this because the set of exported directores might be changing.
1166 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1171 /* create and start update server instance */
1174 char argsBuf[AFSDIR_PATH_MAX], *args;
1177 if (exportClear != NULL && *exportClear != '\0') {
1178 argsLen += strlen("-clear ") + strlen(exportClear) + 1;
1180 if (exportCrypt != NULL && *exportCrypt != '\0') {
1181 argsLen += strlen("-crypt ") + strlen(exportCrypt) + 1;
1187 if (argsLen <= AFSDIR_PATH_MAX) {
1190 args = (char *)malloc(argsLen);
1196 if (exportClear == NULL) {
1197 sprintf(args, "-crypt %s", exportCrypt);
1198 } else if (exportCrypt == NULL) {
1199 sprintf(args, "-clear %s", exportClear);
1201 sprintf(args, "-clear %s -crypt %s", exportClear,
1208 if (!SimpleProcessStart
1209 (cfg_host->bosHandle, UPSERVER_BOSNAME, UPSERVER_EXEPATH,
1214 if (args != NULL && args != argsBuf) {
1221 /* indicate failure */
1232 * cfg_UpdateServerStop() -- Stop, and unconfigure, the Update server on host.
1235 cfg_UpdateServerStop(void *hostHandle, /* host config handle */
1237 { /* completion status */
1239 afs_status_t tst2, tst = 0;
1240 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1242 /* validate parameters and prepare host handle for bos functions */
1244 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1246 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1250 /* stop and delete upserver instance */
1253 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1259 /* indicate failure */
1270 * cfg_UpdateServerQueryStatus() -- Query status of Update server on host.
1273 cfg_UpdateServerQueryStatus(void *hostHandle, /* host config handle */
1274 short *isUpserverP, /* update server configured */
1275 short *isSysCtrlP, /* system control configured */
1276 short *isBinDistP, /* binary dist configured */
1278 { /* completion status */
1280 afs_status_t tst2, tst = 0;
1281 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1283 /* validate parameters and prepare host handle for bos functions */
1285 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1287 } else if (isUpserverP == NULL || isSysCtrlP == NULL
1288 || isBinDistP == NULL) {
1289 tst = ADMCFGUPSERVERCONFIGFLAGPNULL;
1290 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1294 /* query bosserver to determine if, and how, upserver is configured */
1299 *isUpserverP = *isSysCtrlP = *isBinDistP = 0;
1301 if (!bos_ProcessParameterGetBegin
1302 (cfg_host->bosHandle, UPSERVER_BOSNAME, &cmdIter, &tst2)) {
1305 char cmdString[BOS_MAX_NAME_LEN];
1307 if (!bos_ProcessParameterGetNext(cmdIter, cmdString, &tst2)) {
1308 /* no upserver instance (or error) */
1309 if (tst2 != BZNOENT) {
1313 /* parse upserver command line to determine how configured */
1314 short hasSysPath, hasBinPath;
1316 UpdateCommandParse(cmdString, &hasSysPath, &hasBinPath);
1328 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1335 /* indicate failure */
1346 * cfg_SysBinServerStart() -- Start Update server in System Control and/or
1347 * Binary Distribution machine configuration on host.
1349 * This function is a convenience wrapper for cfg_UpdateServerStart().
1352 cfg_SysBinServerStart(void *hostHandle, /* host config handle */
1353 short makeSysCtrl, /* config as sys control mach */
1354 short makeBinDist, /* config as binary dist mach */
1356 { /* completion status */
1357 char *cryptSysDir = NULL;
1358 char *clearBinDir = NULL;
1361 cryptSysDir = AFSDIR_CANONICAL_SERVER_ETC_DIRPATH;
1365 clearBinDir = AFSDIR_CANONICAL_SERVER_BIN_DIRPATH;
1368 return cfg_UpdateServerStart(hostHandle, clearBinDir, cryptSysDir, st);
1373 /* ---------------- Exported Update Client functions ------------------ */
1378 * cfg_UpdateClientStart() -- Start an Update client on host.
1380 * Argument string import specifies a set of space-separated directories
1381 * to import. Argument frequency specifies the import interval in
1382 * seconds; if the value is zero (0) then the default frequency is used.
1384 * The BOS instance name used is the concatenation of the string constant
1385 * cfg_upclientBosNamePrefix and the argument string bosSuffix.
1388 cfg_UpdateClientStart(void *hostHandle, /* host config handle */
1389 const char *bosSuffix, /* BOS instance suffix */
1390 const char *upserver, /* upserver to import from */
1391 short crypt, /* import encrypted */
1392 const char *import, /* dirs to import */
1393 unsigned int frequency, /* import interval in sec. */
1395 { /* completion status */
1397 afs_status_t tst2, tst = 0;
1398 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1399 char upclientInstance[BOS_MAX_NAME_LEN];
1401 /* validate parameters and prepare host handle for bos functions */
1403 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1405 } else if (bosSuffix == NULL) {
1406 tst = ADMCFGUPCLIENTSUFFIXNULL;
1407 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1409 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1410 } else if (upserver == NULL || *upserver == '\0') {
1411 tst = ADMCFGUPCLIENTTARGETSERVERNULL;
1412 } else if (import == NULL || *import == '\0') {
1413 tst = ADMCFGUPCLIENTIMPORTDIRNULL;
1414 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1418 /* stop and delete existing update client instance, if any.
1419 * we do this because the set of imported directores might be changing.
1423 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1425 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1430 /* create and start update client instance */
1433 char argsBuf[AFSDIR_PATH_MAX], *args;
1436 argsLen += strlen(upserver) + 1;
1439 argsLen += strlen("-crypt ");
1441 argsLen += strlen("-clear ");
1444 if (frequency != 0) {
1445 argsLen += strlen("-t ") + 10 /* max uint */ + 1;
1448 argsLen += strlen(import) + 1;
1450 if (argsLen <= AFSDIR_PATH_MAX) {
1453 args = (char *)malloc(argsLen);
1459 /* set up argument buffer */
1461 sprintf(args, "%s -crypt ", upserver);
1463 sprintf(args, "%s -clear ", upserver);
1465 if (frequency != 0) {
1466 char *strp = args + strlen(args);
1467 sprintf(strp, "-t %u ", frequency);
1469 strcat(args, import);
1471 /* create and start instance */
1472 if (!SimpleProcessStart
1473 (cfg_host->bosHandle, upclientInstance, UPCLIENT_EXEPATH,
1478 if (args != argsBuf) {
1485 /* indicate failure */
1496 * cfg_UpdateClientStop() -- Stop, and unconfigure, an Update client on host.
1499 cfg_UpdateClientStop(void *hostHandle, /* host config handle */
1500 const char *bosSuffix, /* BOS instance suffix */
1502 { /* completion status */
1504 afs_status_t tst2, tst = 0;
1505 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1506 char upclientInstance[BOS_MAX_NAME_LEN];
1508 /* validate parameters and prepare host handle for bos functions */
1510 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1512 } else if (bosSuffix == NULL) {
1513 tst = ADMCFGUPCLIENTSUFFIXNULL;
1514 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1516 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1517 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1521 /* stop and delete specified update client instance */
1524 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1526 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1532 /* indicate failure */
1543 * cfg_UpdateClientStopAll() -- Stop, and unconfigure, all Update clients
1547 cfg_UpdateClientStopAll(void *hostHandle, /* host config handle */
1549 { /* completion status */
1551 afs_status_t tst2, tst = 0;
1552 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1554 /* validate parameters and prepare host handle for bos functions */
1556 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1558 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1562 /* find, stop, and delete all update client instances */
1567 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1570 /* iterate over process names, looking for update clients */
1571 char procName[BOS_MAX_NAME_LEN];
1575 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1576 /* no more processes (or failure) */
1577 if (tst2 != ADMITERATORDONE) {
1584 (UPCLIENT_BOSNAME, procName,
1585 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1586 /* upclient instance prefix; assume is upclient */
1587 if (!BosProcessDelete
1588 (cfg_host->bosHandle, procName, &tst2)) {
1595 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1602 /* indicate failure */
1613 * cfg_UpdateClientQueryStatus() -- Query status of Update clients on host.
1616 cfg_UpdateClientQueryStatus(void *hostHandle, /* host config handle */
1617 short *isUpclientP, /* an upclient is configured */
1618 short *isSysP, /* system control client */
1619 short *isBinP, /* binary dist. client */
1621 { /* completion status */
1623 afs_status_t tst2, tst = 0;
1624 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1626 /* validate parameters and prepare host handle for bos functions */
1628 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1630 } else if (isUpclientP == NULL || isSysP == NULL || isBinP == NULL) {
1631 tst = ADMCFGUPCLIENTCONFIGFLAGPNULL;
1632 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1636 /* determine if, and how, any upclients are configured */
1641 *isUpclientP = *isSysP = *isBinP = 0;
1643 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1646 /* iterate over process names, looking for update clients */
1647 char procName[BOS_MAX_NAME_LEN];
1651 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1652 /* no more processes (or failure) */
1653 if (tst2 != ADMITERATORDONE) {
1660 (UPCLIENT_BOSNAME, procName,
1661 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1662 /* upclient instance prefix; assume is upclient */
1667 if (!bos_ProcessParameterGetBegin
1668 (cfg_host->bosHandle, procName, &cmdIter, &tst2)) {
1671 char cmdString[BOS_MAX_NAME_LEN];
1673 if (!bos_ProcessParameterGetNext
1674 (cmdIter, cmdString, &tst2)) {
1675 /* instance deleted out from under us (or error) */
1676 if (tst2 != BZNOENT) {
1680 /* parse command line to determine how config */
1681 short hasSysPath, hasBinPath;
1683 UpdateCommandParse(cmdString, &hasSysPath,
1694 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1705 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1712 /* indicate failure */
1723 * cfg_SysControlClientStart() -- Start an Update client in System Control
1724 * client configuration on host.
1726 * This function is a convenience wrapper for cfg_UpdateClientStart().
1727 * The BOS instance suffix used is the constant cfg_upclientSysBosSuffix.
1730 cfg_SysControlClientStart(void *hostHandle, /* host config handle */
1731 const char *upserver, /* upserver to import from */
1733 { /* completion status */
1734 return cfg_UpdateClientStart(hostHandle, cfg_upclientSysBosSuffix,
1735 upserver, 1 /* crypt */ ,
1736 AFSDIR_CANONICAL_SERVER_ETC_DIRPATH,
1737 0 /* default frequency */ ,
1743 * cfg_BinDistClientStart() -- Start an Update client in Binary Distribution
1744 * client configuration on host.
1746 * This function is a convenience wrapper for cfg_UpdateClientStart().
1747 * The BOS instance suffix used is the constant cfg_upclientBinBosSuffix.
1750 cfg_BinDistClientStart(void *hostHandle, /* host config handle */
1751 const char *upserver, /* upserver to import from */
1753 { /* completion status */
1754 return cfg_UpdateClientStart(hostHandle, cfg_upclientBinBosSuffix,
1755 upserver, 0 /* crypt */ ,
1756 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
1757 0 /* default frequency */ ,
1763 /* ---------------- Local functions ------------------ */
1766 * SimpleProcessStart() -- create and start a simple bosserver instance.
1768 * RETURN CODES: 1 success, 0 failure (st indicates why)
1771 SimpleProcessStart(void *bosHandle, const char *instance,
1772 const char *executable, const char *args, afs_status_p st)
1775 afs_status_t tst2, tst = 0;
1776 char cmdBuf[AFSDIR_PATH_MAX], *cmd;
1779 cmdLen = strlen(executable) + 1 + (args == NULL ? 0 : (strlen(args) + 1));
1781 if (cmdLen <= AFSDIR_PATH_MAX) {
1784 cmd = (char *)malloc(cmdLen);
1791 strcpy(cmd, executable);
1793 sprintf(cmd, "%s %s", executable, args);
1796 if (!bos_ProcessCreate
1797 (bosHandle, (char *)instance, BOS_PROCESS_SIMPLE, cmd, NULL, NULL, &tst2)
1798 && tst2 != BZEXISTS) {
1799 /* failed to create instance (and not because existed) */
1802 if (!bos_ProcessExecutionStateSet
1803 (bosHandle, (char *)instance, BOS_PROCESS_RUNNING, &tst2)) {
1804 /* failed to set instance state to running */
1808 if (cmd != cmdBuf) {
1814 /* indicate failure */
1826 * FsProcessStart() -- create and start a fs bosserver instance.
1828 * RETURN CODES: 1 success, 0 failure (st indicates why)
1831 FsProcessStart(void *bosHandle, const char *instance,
1832 const char *fileserverExe, const char *volserverExe,
1833 const char *salvagerExe, afs_status_p st)
1836 afs_status_t tst2, tst = 0;
1838 if (!bos_FSProcessCreate
1839 (bosHandle, (char *)instance, (char *)fileserverExe, (char *)volserverExe, (char *)salvagerExe, NULL,
1840 &tst2) && tst2 != BZEXISTS) {
1841 /* failed to create instance (and not because existed) */
1844 if (!bos_ProcessExecutionStateSet
1845 (bosHandle, instance, BOS_PROCESS_RUNNING, &tst2)) {
1846 /* failed to set instance state to running */
1851 /* indicate failure */
1863 * BosProcessDelete() -- stop and delete a bosserver instance, if it exists.
1865 * RETURN CODES: 1 success, 0 failure (st indicates why)
1868 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st)
1871 afs_status_t tst2, tst = 0;
1873 if (!bos_ProcessExecutionStateSet
1874 (bosHandle, instance, BOS_PROCESS_STOPPED, &tst2)) {
1875 /* failed to set instance state to stopped (or does not exist) */
1876 if (tst2 != BZNOENT) {
1880 } else if (!bos_ProcessAllWaitTransition(bosHandle, &tst2)) {
1881 /* failed to wait for process to stop */
1884 } else if (!bos_ProcessDelete(bosHandle, (char *)instance, &tst2)) {
1885 /* failed to delete instance (or does not exist) */
1886 if (tst2 != BZNOENT) {
1892 /* indicate failure */
1903 * UpdateCommandParse() -- Parse an upserver or upclient command to determine:
1904 * 1) if it explicitly exports/imports the system control directory
1905 * 2) if it explicitly exports/imports the binary directory
1907 * NOTE: cmdString altered (made all lower case and forward slashes)
1910 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP)
1914 *hasSysPathP = *hasBinPathP = 0;
1916 /* make command string all lower case and forward slashes */
1918 for (argp = cmdString; *argp != '\0'; argp++) {
1919 if (isupper(*argp)) {
1920 *argp = tolower(*argp);
1921 } else if (*argp == '\\') {
1926 /* find end of update executable path (and hence beginning of arguments */
1930 while (isspace(*argp)) {
1933 while (*argp != '\0' && !isspace(*argp)) {
1937 /* search for well-known system control directory */
1939 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_ETC_DIRPATH);
1942 /* check that not a portition of a larger path */
1943 char oneBefore, oneAfter;
1946 oneBefore = *(dirp - 1);
1947 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH) - 1);
1949 if (oneAfter != '\0') {
1950 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH));
1953 if (isspace(oneBefore)) {
1954 if ((isspace(oneAfter)) || (oneAfter == '\0')
1956 && (isspace(twoAfter) || twoAfter == '\0'))) {
1962 /* search for well-known binary directory */
1964 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
1967 /* check that not a portition of a larger path */
1968 char oneBefore, oneAfter;
1971 oneBefore = *(dirp - 1);
1972 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH) - 1);
1974 if (oneAfter != '\0') {
1975 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH));
1978 if (isspace(oneBefore)) {
1979 if ((isspace(oneAfter)) || (oneAfter == '\0')
1981 && (isspace(twoAfter) || twoAfter == '\0'))) {
1991 * UbikQuorumCheck() -- Determine if Ubik has achieved quorum for a specified
1992 * database instance in host's cell.
1994 * RETURN CODES: 1 success, 0 failure (st indicates why)
1997 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance, short *hasQuorum,
2001 afs_status_t tst2, tst = 0;
2006 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
2009 /* iterate over server CellServDb, looking for dbserver sync site */
2010 char dbhostName[BOS_MAX_NAME_LEN];
2012 unsigned short dbhostPort = 0;
2014 int dbhostQueries = 0;
2016 if (!strcmp(dbInstance, KASERVER_BOSNAME)) {
2017 dbhostPort = AFSCONF_KAUTHPORT;
2018 } else if (!strcmp(dbInstance, PTSERVER_BOSNAME)) {
2019 dbhostPort = AFSCONF_PROTPORT;
2020 } else if (!strcmp(dbInstance, VLSERVER_BOSNAME)) {
2021 dbhostPort = AFSCONF_VLDBPORT;
2022 } else if (!strcmp(dbInstance, BUSERVER_BOSNAME)) {
2023 dbhostPort = AFSCONF_BUDBPORT;
2026 while (!dbhostDone) {
2027 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
2028 /* no more entries (or failure) */
2029 if (tst2 == ADMITERATORDONE) {
2030 if (dbhostQueries == 0) {
2031 /* consider quorum to have been achieved when no
2032 * database servers in cell; otherwise higher-level
2033 * functions will timeout and fail.
2043 if (!util_AdminServerAddressGetFromName
2044 (dbhostName, &dbhostAddr, &tst2)) {
2048 short isSyncSite = 0;
2049 short isWriteReady = 0;
2051 /* ignore errors fetching Ubik vote status; there might be
2052 * an unreachable dbserver yet a reachable sync site.
2056 if (UbikVoteStatusFetch
2057 (dbhostAddr, dbhostPort, &isSyncSite, &isWriteReady,
2059 /* have quorum if is sync site AND is ready for updates */
2070 if (!bos_HostGetDone(dbIter, &tst2)) {
2076 /* indicate failure */
2087 * UbikVoteStatusFetch() -- Fetch Ubik vote status parameters of interest from
2088 * specified server and port.
2090 * RETURN CODES: 1 success, 0 failure (st indicates why)
2093 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
2094 short *isSyncSite, short *isWriteReady, afs_status_p st)
2097 afs_status_t tst = 0;
2098 struct rx_securityClass *nullSecurity;
2099 struct rx_connection *serverConn;
2101 nullSecurity = rxnull_NewClientSecurityObject(); /* never fails */
2104 rx_GetCachedConnection(htonl(serverAddr), htons(serverPort),
2105 VOTE_SERVICE_ID, nullSecurity, 0)) == NULL) {
2106 tst = ADMCFGUBIKVOTENOCONNECTION;
2109 struct ubik_debug udebugInfo;
2111 if ((rpcCode = VOTE_Debug(serverConn, &udebugInfo)) == 0) {
2112 /* talking to a 3.5 or later server */
2113 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2117 /* as of 3.5 the database is writeable if "labeled" or if all
2118 * prior recovery states have been achieved; see defect 9477.
2120 if (((udebugInfo.recoveryState & UBIK_RECLABELDB))
2121 || ((udebugInfo.recoveryState & UBIK_RECSYNCSITE)
2122 && (udebugInfo.recoveryState & UBIK_RECFOUNDDB)
2123 && (udebugInfo.recoveryState & UBIK_RECHAVEDB))) {
2128 } else if (rpcCode == RXGEN_OPCODE) {
2129 /* talking to old (pre 3.5) server */
2130 struct ubik_debug_old udebugInfo;
2132 if ((rpcCode = VOTE_DebugOld(serverConn, &udebugInfo)) == 0) {
2133 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2137 /* pre 3.5 the database is writeable only if "labeled" */
2138 if (udebugInfo.recoveryState & UBIK_RECLABELDB) {
2145 (void)rx_ReleaseCachedConnection(serverConn);
2151 /* indicate failure */