07ad67647daa1b6e70f6b40c174d0b99e25213e6
[openafs.git] / src / WINNT / afssvrcfg / get_cur_config.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * INCLUDES _________________________________________________________________
12  *
13  */
14 extern "C" {
15 #include <afs/param.h>
16 #include <afs/stds.h>
17 }
18
19 #include "afscfg.h"
20 #include "partition_utils.h"
21 #include "resource.h"
22
23 extern "C" {
24 #include "afs_vosAdmin.h"
25 #include "afs\vlserver.h"
26 }
27
28
29 /*
30  * DEFINITIONS _________________________________________________________________
31  *
32  */
33 static LPPROGRESSDISPLAY pProg;
34 static const int MAX_STEPS = 10;
35 static BOOL bCancel;
36 static BOOL bBakConfigured;
37 static vos_vldbEntry_t vldbRootAfsEntry;
38 static vos_vldbEntry_t vldbRootCellEntry;
39
40
41 /*
42  * PROTOTYPES _________________________________________________________________
43  *
44  */
45 BOOL CALLBACK GetCurConfigDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
46 static DWORD CALLBACK GetCurrentConfigState(LPPROGRESSDISPLAY ppd, LPARAM lp);
47 static void ShowMsg(UINT uiMsgID);
48 static void NextStep(UINT uiMsgID);
49
50
51 /*
52  * EXPORTED FUNCTIONS _________________________________________________________________
53  *
54  */
55 int GetCurrentConfig(HWND hParent, BOOL& bCanceled)
56 {
57         pProg = 0;
58         bCancel = FALSE;
59         bBakConfigured = FALSE;
60
61         pProg = New2 (PROGRESSDISPLAY,(hParent, IDD_GET_CURRENT_CONFIG, (DLGPROC)GetCurConfigDlgProc));
62         pProg->SetProgressRange(0, MAX_STEPS);
63
64         HWND hLogo = GetDlgItem(pProg->GetWindow(), IDC_LOGO);
65         AfsAppLib_StartAnimation(hLogo);
66
67         pProg->Show(GetCurrentConfigState, 0);
68
69         AfsAppLib_StopAnimation(hLogo);
70
71         int dwResult = pProg->GetStatus();
72
73         pProg->Close();
74
75         bCanceled = bCancel;
76
77         return dwResult;
78 }
79
80
81 /*
82  * STATIC FUNCTIONS _________________________________________________________________
83  *
84  */
85
86
87 /*
88  * Dialog Proc _________________________________________________________________
89  *
90  */
91 static BOOL CALLBACK GetCurConfigDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp)
92 {
93         BOOL bOn = FALSE;
94         
95         switch (msg) {
96                 case WM_INITDIALOG:
97                         bCancel = FALSE;
98                         break;
99
100                 case WM_COMMAND:
101                         switch (LOWORD(wp))
102                         {
103                                 case IDCANCEL:  if (QueryCancelWiz()) {
104                                                                         bCancel = TRUE;
105                                                                         ShowMsg(IDS_CANCEL_GET_CONFIG);
106                                                                 }
107                                                                 break;
108                         }
109                 break;
110         }
111
112         return FALSE;
113 }
114
115 static BOOL IsClientConfigured(BOOL& bConfigured, afs_status_t& nStatus)
116 {
117         if (bCancel)
118                 return FALSE;
119
120         bConfigured = FALSE;
121
122         NextStep(IDS_CHECK_AFS_CLIENT);
123
124         short isInstalled;
125         afs_status_t configStatus;
126         char *pszCellName = 0;
127
128         g_LogFile.Write("Is the AFS Client installed on this machine: ");
129         if (!cfg_ClientQueryStatus(GetHostnameA(), &isInstalled, &g_CfgData.nClientVersion, &configStatus, &pszCellName, &nStatus)) {
130                 ImmediateErrorDialog(nStatus, IDS_ERROR_AFS_CLIENT_CHECK);
131                 return FALSE;
132         }
133
134         g_LogFile.WriteBoolResult((BOOL)isInstalled);
135
136         bConfigured = (BOOL)(configStatus == 0);
137         if (bConfigured)
138                 lstrncpy(g_CfgData.szClientCellName, A2S(pszCellName), MAX_CELL_NAME_LEN);
139         else
140                 g_LogFile.WriteError("The client configuration information on this host is not valid", configStatus);
141
142         if (!isInstalled) {
143                 g_LogFile.Write("ERROR:  AFS Client is not installed.  The AFS Server requires the AFS Client.\r\n");
144                 ImmediateErrorDialog(0, IDS_ERROR_AFS_CLIENT_NOT_INSTALLED);
145                 nStatus = -1;   // Just need something nonzero
146                 return FALSE;
147         }
148
149         return TRUE;
150 }
151
152 /*
153  *      NOTE:   This function has an important side effect.  If this machine
154  *                      is not the first in a new cell, then this function will get the
155  *                      cell name from the config info.  The cell name may be needed in 
156  *                      config calls that come later, and so this function must be called
157  *                      before they are.
158  */
159 static int IsConfigInfoValid(BOOL& bValid, afs_status_t& nStatus)
160 {
161         if (bCancel)
162                 return FALSE;
163         
164         afs_status_t configStatus;
165         char *pszCellName = 0;
166
167         NextStep(IDS_CHECK_CONFIG_INFO);
168
169         bValid = FALSE;
170
171         g_LogFile.Write("Is there valid configuration information on this machine: ");
172         int nResult = cfg_HostQueryStatus(GetHostnameA(), &configStatus, &pszCellName, &nStatus);
173         if (!nResult)
174                 return FALSE;
175
176         g_LogFile.WriteBoolResult((configStatus == 0));
177
178         if (configStatus == 0)
179                 lstrncpy(g_CfgData.szCellName, A2S(pszCellName), MAX_CELL_NAME_LEN);
180         else
181                 g_LogFile.WriteError("The configuration information on this host is not valid", configStatus);
182
183         bValid = (BOOL)(configStatus == 0);
184
185         return TRUE;
186 }
187
188 static int StartBosServer(afs_status_t& nStatus)
189 {
190         short isStarted;
191         short isBosProc;
192
193         g_LogFile.Write("Checking if bos server is running.\r\n");
194         int nResult = cfg_BosServerQueryStatus(g_hServer, &isStarted, &isBosProc, &nStatus);
195         if (!nResult)
196                 return nResult;
197
198         if (!isStarted) {
199                 g_LogFile.Write("Starting the bos server in %s mode.\r\n", g_CfgData.bValidServerInfo ? "auth" : "no auth");
200                 nResult = cfg_BosServerStart(g_hServer, !g_CfgData.bValidServerInfo, BOSSERVER_START_TIMEOUT, &nStatus);
201         }
202
203         return nResult;
204 }
205
206 static BOOL AreWeLastDBServer(BOOL& bLast, afs_status_t& nStatus)
207 {
208         ASSERT(g_CfgData.szHostname[0]);
209
210         char *pszCellname = 0;
211         char *pszCellServDB = 0;
212
213         bLast = FALSE;
214
215         g_LogFile.Write("Checking if this machine is the last DB server in the cell.\r\n");
216
217         g_LogFile.Write("Getting CellServDB from host %s.\r\n", GetHostnameA());
218         int nResult = cfg_CellServDbEnumerate(GetHostnameA(), &pszCellname, &pszCellServDB, &nStatus);
219         if (!nResult)
220                 return FALSE;   
221
222         if (!pszCellServDB) {
223                 g_LogFile.Write("There are no DB servers in CellServDB!!!!!");
224                 ASSERT(FALSE);          // This should not be possible
225                 return FALSE;
226         }
227
228         char *psz = pszCellServDB;
229
230         int i;
231         for (i = 0; *psz; psz += strlen(psz) + 1)
232                 i++;
233
234         if (i == 1) {
235                 ASSERT(lstrcmp(g_CfgData.szHostname, A2S(pszCellServDB)) == 0);
236                 g_LogFile.Write("This machine IS the last DB server in the cell.\r\n");
237                 bLast = TRUE;
238         } else
239                 g_LogFile.Write("This machine is NOT the last DB server in the cell.\r\n");
240
241         return TRUE;
242 }
243
244 static afs_status_t IsFSConfigured(BOOL& bConfigured)
245 {
246         g_LogFile.Write("Is this machine a file server: ");
247         
248         bConfigured = FALSE;
249
250         short isStarted;
251         afs_status_t nStatus;
252
253         int nResult = cfg_FileServerQueryStatus(g_hServer, &isStarted, &nStatus);
254         if (!nResult)
255                 return nStatus;
256
257         bConfigured = isStarted;        
258         
259         g_LogFile.WriteBoolResult(bConfigured);
260
261         return 0;
262 }
263
264 static afs_status_t IsDBConfigured(BOOL& bConfigured)
265 {
266         g_LogFile.Write("Is this machine a db (or bak) server: ");
267
268         bConfigured = FALSE;
269
270         short isStarted, isBakStarted;
271         afs_status_t nStatus;
272
273         int nResult = cfg_DbServersQueryStatus(g_hServer, &isStarted, &isBakStarted, 0, &nStatus);
274         if (!nResult)
275                 return nStatus;
276
277         bConfigured = isStarted;
278         bBakConfigured = isBakStarted;
279
280         g_LogFile.Write(bConfigured ? "Yes DB" : "No DB");
281         g_LogFile.Write(", %s.\r\n", bBakConfigured ? "Yes Bak" : "No Bak");
282
283         return 0;
284 }
285
286 static afs_status_t IsBakConfigured(BOOL& bConfigured)
287 {
288         bConfigured = bBakConfigured;
289         
290         return 0;
291 }
292
293 static afs_status_t DoesAPartitionExist(BOOL& bExists)
294 {
295         g_LogFile.Write("Does a partition exist on this machine: ");
296
297         bExists = FALSE;
298
299         afs_status_t nStatus;
300
301         int nResult = ReadPartitionTable(&nStatus);
302         if (!nResult)
303                 return nStatus;
304
305         int nNumPartitions = 0;
306
307         cfg_partitionEntry_t *pTable = GetPartitionTable(nNumPartitions);
308
309         bExists = nNumPartitions > 0;
310         if (bExists) {
311                 g_CfgData.chDeviceName = pTable->deviceName[0];
312                 lstrcpy(g_CfgData.szPartitionName, ((TCHAR *)A2S(pTable->partitionName)) + lstrlen(TEXT("/vicep")));
313         }
314
315         g_LogFile.WriteBoolResult(bExists);
316
317         return 0;
318 }
319
320 afs_status_t DoRootVolumesExist(BOOL& bExists)
321 {
322         bExists = FALSE;
323
324         afs_status_t nStatus;
325
326         g_LogFile.Write("Do the root volumes exist: ");
327
328         // Does root.afs exist?  If it does not, the call will fail with the VL_NOENT
329         // status.  Any other error causes this function to fail.
330         int nResult = vos_VLDBGet(g_hCell, 0, 0, "root.afs", &vldbRootAfsEntry, &nStatus);
331         if (nResult) {
332                 g_CfgData.bRootAfsExists = TRUE;
333         g_CfgData.nRootAfsID = vldbRootAfsEntry.volumeId[0];
334         } else if (nStatus != VL_NOENT)
335                 return nStatus;
336
337         // Does root.cell exist?
338         nResult = vos_VLDBGet(g_hCell, 0, 0, "root.cell", &vldbRootCellEntry, &nStatus);
339         if (nResult) {
340                 g_CfgData.bRootCellExists = TRUE;
341         g_CfgData.nRootCellID = vldbRootCellEntry.volumeId[0];
342         } else if (nStatus != VL_NOENT)
343                 return nStatus;
344
345         bExists = g_CfgData.bRootAfsExists && g_CfgData.bRootCellExists;
346
347         g_LogFile.WriteBoolResult(bExists);
348
349         return 0;
350 }
351
352 static BOOL IsVolumeReplicated(vos_vldbEntry_t& vldbEntry)
353 {
354         if (vldbEntry.numServers <= 1)
355                 return FALSE;
356
357         for (int i = 0; i < vldbEntry.numServers; i++) {
358                 if ((vldbEntry.volumeSites[i].serverFlags & VOS_VLDB_READ_ONLY) ||
359                         (vldbEntry.volumeSites[i].serverFlags & VOS_VLDB_NEW_REPSITE))
360                                 return TRUE;
361         }
362
363         return FALSE;
364 }
365
366 afs_status_t AreRootVolumesReplicated(BOOL& bReplicated)
367 {
368         g_LogFile.Write("Are the root volumes replicated: ");
369
370         // Is root.afs replicated?
371         g_CfgData.bRootAfsReplicated = IsVolumeReplicated(vldbRootAfsEntry);
372
373         // Is root.cell replicated?
374         g_CfgData.bRootCellReplicated = IsVolumeReplicated(vldbRootCellEntry);
375
376         bReplicated = g_CfgData.bRootAfsReplicated && g_CfgData.bRootCellReplicated;
377
378         g_LogFile.WriteBoolResult(bReplicated);
379
380         return 0;
381 }
382
383 static afs_status_t IsSCSConfigured(BOOL& bConfigured)
384 {
385         g_LogFile.Write("Is this machine a System Control Server: ");
386         
387         bConfigured = FALSE;
388
389         short isUpserver, isSC, isBin;
390         afs_status_t nStatus;
391
392         int nResult = cfg_UpdateServerQueryStatus(g_hServer, &isUpserver, &isSC, &isBin, &nStatus);
393         if (!nResult)
394                 return nStatus;
395
396         bConfigured = isUpserver && isSC;
397
398         g_LogFile.WriteBoolResult(bConfigured);
399
400         return 0;
401 }
402
403 static afs_status_t IsSCCConfigured(BOOL& bConfigured)
404 {
405         g_LogFile.Write("Is this machine a System Control Client: ");
406         
407         bConfigured = FALSE;
408
409         short isUpclient, isSCC, isBin;
410         afs_status_t nStatus;
411
412         int nResult = cfg_UpdateClientQueryStatus(g_hServer, &isUpclient, &isSCC, &isBin, &nStatus);
413         if (!nResult)
414                 return nStatus;
415
416         bConfigured = isUpclient && isSCC;
417
418         g_LogFile.WriteBoolResult(bConfigured);
419
420         return 0;
421 }
422
423 static void ShowMsg(UINT uiMsgID)
424 {
425         TCHAR szMsg[cchRESOURCE];
426
427         GetString(szMsg, uiMsgID);
428         
429         pProg->SetOperation(szMsg);
430 }
431
432 static void NextStep(UINT uiMsgID)
433 {
434         static int nCurStep = 1;
435
436         if (bCancel)
437                 return;
438         
439         ShowMsg(uiMsgID);
440
441         pProg->SetProgress(nCurStep++);
442
443         Sleep(50);
444 }
445
446 static BOOL CheckConfigState(afs_status_t (*ConfigCheckFunc)(BOOL&), CONFIG_STATE& state, afs_status_t& nStatus, UINT uiMsgID)
447 {
448         BOOL bState = FALSE;
449
450         if (bCancel)
451                 return FALSE;
452
453         NextStep(uiMsgID);
454
455         nStatus = ConfigCheckFunc(bState);
456         if (nStatus) {
457                 g_LogFile.WriteError("Config check failed", nStatus);
458                 return FALSE;
459         }
460
461         state = bState ? CS_ALREADY_CONFIGURED : CS_NULL;
462
463         return TRUE;
464 }
465                 
466 static DWORD CALLBACK GetCurrentConfigState(LPPROGRESSDISPLAY ppd, LPARAM lp)
467 {
468         afs_status_t nStatus = 0;
469
470         ASSERT(pProg);
471
472         g_LogFile.Write("Checking this machine's current configuration...\r\n");
473
474         if (!IsClientConfigured(g_CfgData.bValidClientInfo, nStatus))
475                 return nStatus;
476
477         if (!IsConfigInfoValid(g_CfgData.bValidServerInfo, nStatus))
478                 return nStatus;
479
480     // If the server and client have good config info, and the client is in a 
481     // different cell than the server, then the config routines will want to
482     // reconfigure the client.  To do so they need information that we already
483     // know and don't have to ask the user for.  Prefill this information here.
484     if (g_CfgData.bValidClientInfo && g_CfgData.bValidServerInfo && 
485         (lstrcmp(g_CfgData.szCellName, g_CfgData.szClientCellName) != 0))
486     {
487         lstrcpy(g_CfgData.szCellServDbHostname, g_CfgData.szHostname);
488     }
489
490         if (!GetLibHandles(&nStatus))
491                 return nStatus;
492
493         if (!CheckConfigState(DoesAPartitionExist, g_CfgData.configPartition, nStatus, IDS_CHECK_PARTITION))
494                 return nStatus;
495
496         if (g_CfgData.bValidServerInfo) {
497                 // Must check if bos server is running, and start it if it isn't.  We can't determine
498                 // if the services are running except by asking the bosserver.
499                 if (!StartBosServer(nStatus))
500                         return nStatus;
501
502                 if (!CheckConfigState(IsFSConfigured, g_CfgData.configFS, nStatus, IDS_CHECK_FS_CONFIG))
503                         return nStatus;
504
505                 if (!CheckConfigState(IsDBConfigured, g_CfgData.configDB, nStatus, IDS_CHECK_DB_CONFIG))
506                         return nStatus;
507
508                 if (g_CfgData.configDB == CS_ALREADY_CONFIGURED) {
509                         if (!AreWeLastDBServer(g_CfgData.bLastDBServer, nStatus))
510                                 return nStatus;
511                 }
512
513                 if (!CheckConfigState(IsBakConfigured, g_CfgData.configBak, nStatus, IDS_CHECK_BAK_CONFIG))
514                         return nStatus;
515
516                 if (!CheckConfigState(DoRootVolumesExist, g_CfgData.configRootVolumes, nStatus, IDS_CHECK_ROOT_AFS))
517             return nStatus;
518
519         g_CfgData.bRootVolumesExistanceKnown = TRUE;
520
521                 if (!CheckConfigState(AreRootVolumesReplicated, g_CfgData.configRep, nStatus, IDS_CHECK_REP))
522             return nStatus;
523         
524         g_CfgData.bRootVolumesReplicationKnown = TRUE;
525
526                 if (!CheckConfigState(IsSCSConfigured, g_CfgData.configSCS, nStatus, IDS_CHECK_SCS))
527                         return nStatus;
528
529                 if (!CheckConfigState(IsSCCConfigured, g_CfgData.configSCC, nStatus, IDS_CHECK_SCC))
530                         return nStatus;
531         }
532
533         if (!bCancel)
534                 pProg->SetProgress(MAX_STEPS);
535         
536         return 0;
537 }
538