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