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 */
1168 char argsBuf[AFSDIR_PATH_MAX], *args;
1171 if (exportClear != NULL && *exportClear != '\0') {
1172 argsLen += strlen("-clear ") + strlen(exportClear) + 1;
1174 if (exportCrypt != NULL && *exportCrypt != '\0') {
1175 argsLen += strlen("-crypt ") + strlen(exportCrypt) + 1;
1181 if (argsLen <= AFSDIR_PATH_MAX) {
1184 args = (char *)malloc(argsLen);
1190 if (exportClear == NULL) {
1191 sprintf(args, "-crypt %s", exportCrypt);
1192 } else if (exportCrypt == NULL) {
1193 sprintf(args, "-clear %s", exportClear);
1195 sprintf(args, "-clear %s -crypt %s", exportClear,
1202 if (!SimpleProcessStart
1203 (cfg_host->bosHandle, UPSERVER_BOSNAME, UPSERVER_EXEPATH,
1208 if (args != NULL && args != argsBuf) {
1215 /* indicate failure */
1226 * cfg_UpdateServerStop() -- Stop, and unconfigure, the Update server on host.
1229 cfg_UpdateServerStop(void *hostHandle, /* host config handle */
1231 { /* completion status */
1233 afs_status_t tst2, tst = 0;
1234 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1236 /* validate parameters and prepare host handle for bos functions */
1238 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1240 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1244 /* stop and delete upserver instance */
1247 if (!BosProcessDelete(cfg_host->bosHandle, UPSERVER_BOSNAME, &tst2)) {
1253 /* indicate failure */
1264 * cfg_UpdateServerQueryStatus() -- Query status of Update server on host.
1267 cfg_UpdateServerQueryStatus(void *hostHandle, /* host config handle */
1268 short *isUpserverP, /* update server configured */
1269 short *isSysCtrlP, /* system control configured */
1270 short *isBinDistP, /* binary dist configured */
1272 { /* completion status */
1274 afs_status_t tst2, tst = 0;
1275 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1277 /* validate parameters and prepare host handle for bos functions */
1279 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1281 } else if (isUpserverP == NULL || isSysCtrlP == NULL
1282 || isBinDistP == NULL) {
1283 tst = ADMCFGUPSERVERCONFIGFLAGPNULL;
1284 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1288 /* query bosserver to determine if, and how, upserver is configured */
1293 *isUpserverP = *isSysCtrlP = *isBinDistP = 0;
1295 if (!bos_ProcessParameterGetBegin
1296 (cfg_host->bosHandle, UPSERVER_BOSNAME, &cmdIter, &tst2)) {
1299 char cmdString[BOS_MAX_NAME_LEN];
1301 if (!bos_ProcessParameterGetNext(cmdIter, cmdString, &tst2)) {
1302 /* no upserver instance (or error) */
1303 if (tst2 != BZNOENT) {
1307 /* parse upserver command line to determine how configured */
1308 short hasSysPath, hasBinPath;
1310 UpdateCommandParse(cmdString, &hasSysPath, &hasBinPath);
1322 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1329 /* indicate failure */
1340 * cfg_SysBinServerStart() -- Start Update server in System Control and/or
1341 * Binary Distribution machine configuration on host.
1343 * This function is a convenience wrapper for cfg_UpdateServerStart().
1346 cfg_SysBinServerStart(void *hostHandle, /* host config handle */
1347 short makeSysCtrl, /* config as sys control mach */
1348 short makeBinDist, /* config as binary dist mach */
1350 { /* completion status */
1351 char *cryptSysDir = NULL;
1352 char *clearBinDir = NULL;
1355 cryptSysDir = AFSDIR_CANONICAL_SERVER_ETC_DIRPATH;
1359 clearBinDir = AFSDIR_CANONICAL_SERVER_BIN_DIRPATH;
1362 return cfg_UpdateServerStart(hostHandle, clearBinDir, cryptSysDir, st);
1367 /* ---------------- Exported Update Client functions ------------------ */
1372 * cfg_UpdateClientStart() -- Start an Update client on host.
1374 * Argument string import specifies a set of space-separated directories
1375 * to import. Argument frequency specifies the import interval in
1376 * seconds; if the value is zero (0) then the default frequency is used.
1378 * The BOS instance name used is the concatenation of the string constant
1379 * cfg_upclientBosNamePrefix and the argument string bosSuffix.
1382 cfg_UpdateClientStart(void *hostHandle, /* host config handle */
1383 const char *bosSuffix, /* BOS instance suffix */
1384 const char *upserver, /* upserver to import from */
1385 short crypt, /* import encrypted */
1386 const char *import, /* dirs to import */
1387 unsigned int frequency, /* import interval in sec. */
1389 { /* completion status */
1391 afs_status_t tst2, tst = 0;
1392 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1393 char upclientInstance[BOS_MAX_NAME_LEN];
1395 /* validate parameters and prepare host handle for bos functions */
1397 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1399 } else if (bosSuffix == NULL) {
1400 tst = ADMCFGUPCLIENTSUFFIXNULL;
1401 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1403 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1404 } else if (upserver == NULL || *upserver == '\0') {
1405 tst = ADMCFGUPCLIENTTARGETSERVERNULL;
1406 } else if (import == NULL || *import == '\0') {
1407 tst = ADMCFGUPCLIENTIMPORTDIRNULL;
1408 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1412 /* stop and delete existing update client instance, if any.
1413 * we do this because the set of imported directores might be changing.
1417 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1419 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1424 /* create and start update client instance */
1427 char argsBuf[AFSDIR_PATH_MAX], *args;
1430 argsLen += strlen(upserver) + 1;
1433 argsLen += strlen("-crypt ");
1435 argsLen += strlen("-clear ");
1438 if (frequency != 0) {
1439 argsLen += strlen("-t ") + 10 /* max uint */ + 1;
1442 argsLen += strlen(import) + 1;
1444 if (argsLen <= AFSDIR_PATH_MAX) {
1447 args = (char *)malloc(argsLen);
1453 /* set up argument buffer */
1455 sprintf(args, "%s -crypt ", upserver);
1457 sprintf(args, "%s -clear ", upserver);
1459 if (frequency != 0) {
1460 char *strp = args + strlen(args);
1461 sprintf(strp, "-t %u ", frequency);
1463 strcat(args, import);
1465 /* create and start instance */
1466 if (!SimpleProcessStart
1467 (cfg_host->bosHandle, upclientInstance, UPCLIENT_EXEPATH,
1472 if (args != argsBuf) {
1479 /* indicate failure */
1490 * cfg_UpdateClientStop() -- Stop, and unconfigure, an Update client on host.
1493 cfg_UpdateClientStop(void *hostHandle, /* host config handle */
1494 const char *bosSuffix, /* BOS instance suffix */
1496 { /* completion status */
1498 afs_status_t tst2, tst = 0;
1499 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1500 char upclientInstance[BOS_MAX_NAME_LEN];
1502 /* validate parameters and prepare host handle for bos functions */
1504 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1506 } else if (bosSuffix == NULL) {
1507 tst = ADMCFGUPCLIENTSUFFIXNULL;
1508 } else if ((strlen(UPCLIENT_BOSNAME) + strlen(bosSuffix) + 1) >
1510 tst = ADMCFGUPCLIENTSUFFIXTOOLONG;
1511 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1515 /* stop and delete specified update client instance */
1518 sprintf(upclientInstance, "%s%s", UPCLIENT_BOSNAME, bosSuffix);
1520 if (!BosProcessDelete(cfg_host->bosHandle, upclientInstance, &tst2)) {
1526 /* indicate failure */
1537 * cfg_UpdateClientStopAll() -- Stop, and unconfigure, all Update clients
1541 cfg_UpdateClientStopAll(void *hostHandle, /* host config handle */
1543 { /* completion status */
1545 afs_status_t tst2, tst = 0;
1546 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1548 /* validate parameters and prepare host handle for bos functions */
1550 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1552 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1556 /* find, stop, and delete all update client instances */
1561 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1564 /* iterate over process names, looking for update clients */
1565 char procName[BOS_MAX_NAME_LEN];
1569 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1570 /* no more processes (or failure) */
1571 if (tst2 != ADMITERATORDONE) {
1578 (UPCLIENT_BOSNAME, procName,
1579 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1580 /* upclient instance prefix; assume is upclient */
1581 if (!BosProcessDelete
1582 (cfg_host->bosHandle, procName, &tst2)) {
1589 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1596 /* indicate failure */
1607 * cfg_UpdateClientQueryStatus() -- Query status of Update clients on host.
1610 cfg_UpdateClientQueryStatus(void *hostHandle, /* host config handle */
1611 short *isUpclientP, /* an upclient is configured */
1612 short *isSysP, /* system control client */
1613 short *isBinP, /* binary dist. client */
1615 { /* completion status */
1617 afs_status_t tst2, tst = 0;
1618 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
1620 /* validate parameters and prepare host handle for bos functions */
1622 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
1624 } else if (isUpclientP == NULL || isSysP == NULL || isBinP == NULL) {
1625 tst = ADMCFGUPCLIENTCONFIGFLAGPNULL;
1626 } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) {
1630 /* determine if, and how, any upclients are configured */
1635 *isUpclientP = *isSysP = *isBinP = 0;
1637 if (!bos_ProcessNameGetBegin(cfg_host->bosHandle, &procIter, &tst2)) {
1640 /* iterate over process names, looking for update clients */
1641 char procName[BOS_MAX_NAME_LEN];
1645 if (!bos_ProcessNameGetNext(procIter, procName, &tst2)) {
1646 /* no more processes (or failure) */
1647 if (tst2 != ADMITERATORDONE) {
1654 (UPCLIENT_BOSNAME, procName,
1655 (sizeof(UPCLIENT_BOSNAME) - 1))) {
1656 /* upclient instance prefix; assume is upclient */
1661 if (!bos_ProcessParameterGetBegin
1662 (cfg_host->bosHandle, procName, &cmdIter, &tst2)) {
1665 char cmdString[BOS_MAX_NAME_LEN];
1667 if (!bos_ProcessParameterGetNext
1668 (cmdIter, cmdString, &tst2)) {
1669 /* instance deleted out from under us (or error) */
1670 if (tst2 != BZNOENT) {
1674 /* parse command line to determine how config */
1675 short hasSysPath, hasBinPath;
1677 UpdateCommandParse(cmdString, &hasSysPath,
1688 if (!bos_ProcessParameterGetDone(cmdIter, &tst2)) {
1699 if (!bos_ProcessNameGetDone(procIter, &tst2)) {
1706 /* indicate failure */
1717 * cfg_SysControlClientStart() -- Start an Update client in System Control
1718 * client configuration on host.
1720 * This function is a convenience wrapper for cfg_UpdateClientStart().
1721 * The BOS instance suffix used is the constant cfg_upclientSysBosSuffix.
1724 cfg_SysControlClientStart(void *hostHandle, /* host config handle */
1725 const char *upserver, /* upserver to import from */
1727 { /* completion status */
1728 return cfg_UpdateClientStart(hostHandle, cfg_upclientSysBosSuffix,
1729 upserver, 1 /* crypt */ ,
1730 AFSDIR_CANONICAL_SERVER_ETC_DIRPATH,
1731 0 /* default frequency */ ,
1737 * cfg_BinDistClientStart() -- Start an Update client in Binary Distribution
1738 * client configuration on host.
1740 * This function is a convenience wrapper for cfg_UpdateClientStart().
1741 * The BOS instance suffix used is the constant cfg_upclientBinBosSuffix.
1744 cfg_BinDistClientStart(void *hostHandle, /* host config handle */
1745 const char *upserver, /* upserver to import from */
1747 { /* completion status */
1748 return cfg_UpdateClientStart(hostHandle, cfg_upclientBinBosSuffix,
1749 upserver, 0 /* crypt */ ,
1750 AFSDIR_CANONICAL_SERVER_BIN_DIRPATH,
1751 0 /* default frequency */ ,
1757 /* ---------------- Local functions ------------------ */
1760 * SimpleProcessStart() -- create and start a simple bosserver instance.
1762 * RETURN CODES: 1 success, 0 failure (st indicates why)
1765 SimpleProcessStart(void *bosHandle, const char *instance,
1766 const char *executable, const char *args, afs_status_p st)
1769 afs_status_t tst2, tst = 0;
1770 char cmdBuf[AFSDIR_PATH_MAX], *cmd;
1773 cmdLen = strlen(executable) + 1 + (args == NULL ? 0 : (strlen(args) + 1));
1775 if (cmdLen <= AFSDIR_PATH_MAX) {
1778 cmd = (char *)malloc(cmdLen);
1785 strcpy(cmd, executable);
1787 sprintf(cmd, "%s %s", executable, args);
1790 if (!bos_ProcessCreate
1791 (bosHandle, (char *)instance, BOS_PROCESS_SIMPLE, cmd, NULL, NULL, &tst2)
1792 && tst2 != BZEXISTS) {
1793 /* failed to create instance (and not because existed) */
1796 if (!bos_ProcessExecutionStateSet
1797 (bosHandle, (char *)instance, BOS_PROCESS_RUNNING, &tst2)) {
1798 /* failed to set instance state to running */
1802 if (cmd != cmdBuf) {
1808 /* indicate failure */
1820 * FsProcessStart() -- create and start a fs bosserver instance.
1822 * RETURN CODES: 1 success, 0 failure (st indicates why)
1825 FsProcessStart(void *bosHandle, const char *instance,
1826 const char *fileserverExe, const char *volserverExe,
1827 const char *salvagerExe, afs_status_p st)
1830 afs_status_t tst2, tst = 0;
1832 if (!bos_FSProcessCreate
1833 (bosHandle, (char *)instance, (char *)fileserverExe, (char *)volserverExe, (char *)salvagerExe, NULL,
1834 &tst2) && tst2 != BZEXISTS) {
1835 /* failed to create instance (and not because existed) */
1838 if (!bos_ProcessExecutionStateSet
1839 (bosHandle, instance, BOS_PROCESS_RUNNING, &tst2)) {
1840 /* failed to set instance state to running */
1845 /* indicate failure */
1857 * BosProcessDelete() -- stop and delete a bosserver instance, if it exists.
1859 * RETURN CODES: 1 success, 0 failure (st indicates why)
1862 BosProcessDelete(void *bosHandle, const char *instance, afs_status_p st)
1865 afs_status_t tst2, tst = 0;
1867 if (!bos_ProcessExecutionStateSet
1868 (bosHandle, instance, BOS_PROCESS_STOPPED, &tst2)) {
1869 /* failed to set instance state to stopped (or does not exist) */
1870 if (tst2 != BZNOENT) {
1874 } else if (!bos_ProcessAllWaitTransition(bosHandle, &tst2)) {
1875 /* failed to wait for process to stop */
1878 } else if (!bos_ProcessDelete(bosHandle, (char *)instance, &tst2)) {
1879 /* failed to delete instance (or does not exist) */
1880 if (tst2 != BZNOENT) {
1886 /* indicate failure */
1897 * UpdateCommandParse() -- Parse an upserver or upclient command to determine:
1898 * 1) if it explicitly exports/imports the system control directory
1899 * 2) if it explicitly exports/imports the binary directory
1901 * NOTE: cmdString altered (made all lower case and forward slashes)
1904 UpdateCommandParse(char *cmdString, short *hasSysPathP, short *hasBinPathP)
1908 *hasSysPathP = *hasBinPathP = 0;
1910 /* make command string all lower case and forward slashes */
1912 for (argp = cmdString; *argp != '\0'; argp++) {
1913 if (isupper(*argp)) {
1914 *argp = tolower(*argp);
1915 } else if (*argp == '\\') {
1920 /* find end of update executable path (and hence beginning of arguments */
1924 while (isspace(*argp)) {
1927 while (*argp != '\0' && !isspace(*argp)) {
1931 /* search for well-known system control directory */
1933 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_ETC_DIRPATH);
1936 /* check that not a portition of a larger path */
1937 char oneBefore, oneAfter;
1940 oneBefore = *(dirp - 1);
1941 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH) - 1);
1943 if (oneAfter != '\0') {
1944 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_ETC_DIRPATH));
1947 if (isspace(oneBefore)) {
1948 if ((isspace(oneAfter)) || (oneAfter == '\0')
1950 && (isspace(twoAfter) || twoAfter == '\0'))) {
1956 /* search for well-known binary directory */
1958 dirp = strstr(argp, AFSDIR_CANONICAL_SERVER_BIN_DIRPATH);
1961 /* check that not a portition of a larger path */
1962 char oneBefore, oneAfter;
1965 oneBefore = *(dirp - 1);
1966 oneAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH) - 1);
1968 if (oneAfter != '\0') {
1969 twoAfter = *(dirp + sizeof(AFSDIR_CANONICAL_SERVER_BIN_DIRPATH));
1972 if (isspace(oneBefore)) {
1973 if ((isspace(oneAfter)) || (oneAfter == '\0')
1975 && (isspace(twoAfter) || twoAfter == '\0'))) {
1985 * UbikQuorumCheck() -- Determine if Ubik has achieved quorum for a specified
1986 * database instance in host's cell.
1988 * RETURN CODES: 1 success, 0 failure (st indicates why)
1991 UbikQuorumCheck(cfg_host_p cfg_host, const char *dbInstance, short *hasQuorum,
1995 afs_status_t tst2, tst = 0;
2000 if (!bos_HostGetBegin(cfg_host->bosHandle, &dbIter, &tst2)) {
2003 /* iterate over server CellServDb, looking for dbserver sync site */
2004 char dbhostName[BOS_MAX_NAME_LEN];
2006 unsigned short dbhostPort = 0;
2008 int dbhostQueries = 0;
2010 if (!strcmp(dbInstance, KASERVER_BOSNAME)) {
2011 dbhostPort = AFSCONF_KAUTHPORT;
2012 } else if (!strcmp(dbInstance, PTSERVER_BOSNAME)) {
2013 dbhostPort = AFSCONF_PROTPORT;
2014 } else if (!strcmp(dbInstance, VLSERVER_BOSNAME)) {
2015 dbhostPort = AFSCONF_VLDBPORT;
2016 } else if (!strcmp(dbInstance, BUSERVER_BOSNAME)) {
2017 dbhostPort = AFSCONF_BUDBPORT;
2020 while (!dbhostDone) {
2021 if (!bos_HostGetNext(dbIter, dbhostName, &tst2)) {
2022 /* no more entries (or failure) */
2023 if (tst2 == ADMITERATORDONE) {
2024 if (dbhostQueries == 0) {
2025 /* consider quorum to have been achieved when no
2026 * database servers in cell; otherwise higher-level
2027 * functions will timeout and fail.
2037 if (!util_AdminServerAddressGetFromName
2038 (dbhostName, &dbhostAddr, &tst2)) {
2042 short isSyncSite = 0;
2043 short isWriteReady = 0;
2045 /* ignore errors fetching Ubik vote status; there might be
2046 * an unreachable dbserver yet a reachable sync site.
2050 if (UbikVoteStatusFetch
2051 (dbhostAddr, dbhostPort, &isSyncSite, &isWriteReady,
2053 /* have quorum if is sync site AND is ready for updates */
2064 if (!bos_HostGetDone(dbIter, &tst2)) {
2070 /* indicate failure */
2081 * UbikVoteStatusFetch() -- Fetch Ubik vote status parameters of interest from
2082 * specified server and port.
2084 * RETURN CODES: 1 success, 0 failure (st indicates why)
2087 UbikVoteStatusFetch(int serverAddr, unsigned short serverPort,
2088 short *isSyncSite, short *isWriteReady, afs_status_p st)
2091 afs_status_t tst = 0;
2092 struct rx_securityClass *nullSecurity;
2093 struct rx_connection *serverConn;
2095 nullSecurity = rxnull_NewClientSecurityObject(); /* never fails */
2098 rx_GetCachedConnection(htonl(serverAddr), htons(serverPort),
2099 VOTE_SERVICE_ID, nullSecurity, 0)) == NULL) {
2100 tst = ADMCFGUBIKVOTENOCONNECTION;
2103 struct ubik_debug udebugInfo;
2105 if ((rpcCode = VOTE_Debug(serverConn, &udebugInfo)) == 0) {
2106 /* talking to a 3.5 or later server */
2107 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2111 /* as of 3.5 the database is writeable if "labeled" or if all
2112 * prior recovery states have been achieved; see defect 9477.
2114 if (((udebugInfo.recoveryState & UBIK_RECLABELDB))
2115 || ((udebugInfo.recoveryState & UBIK_RECSYNCSITE)
2116 && (udebugInfo.recoveryState & UBIK_RECFOUNDDB)
2117 && (udebugInfo.recoveryState & UBIK_RECHAVEDB))) {
2122 } else if (rpcCode == RXGEN_OPCODE) {
2123 /* talking to old (pre 3.5) server */
2124 struct ubik_debug_old udebugInfo;
2126 if ((rpcCode = VOTE_DebugOld(serverConn, &udebugInfo)) == 0) {
2127 *isSyncSite = (udebugInfo.amSyncSite ? 1 : 0);
2131 /* pre 3.5 the database is writeable only if "labeled" */
2132 if (udebugInfo.recoveryState & UBIK_RECLABELDB) {
2139 (void)rx_ReleaseCachedConnection(serverConn);
2145 /* indicate failure */