6766e791f0042d7adbdab5f1472075ae50dce139
[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         for (int i = 0; *psz; psz += strlen(psz) + 1)
231                 i++;
232
233         if (i == 1) {
234                 ASSERT(lstrcmp(g_CfgData.szHostname, A2S(pszCellServDB)) == 0);
235                 g_LogFile.Write("This machine IS the last DB server in the cell.\r\n");
236                 bLast = TRUE;
237         } else
238                 g_LogFile.Write("This machine is NOT the last DB server in the cell.\r\n");
239
240         return TRUE;
241 }
242
243 static afs_status_t IsFSConfigured(BOOL& bConfigured)
244 {
245         g_LogFile.Write("Is this machine a file server: ");
246         
247         bConfigured = FALSE;
248
249         short isStarted;
250         afs_status_t nStatus;
251
252         int nResult = cfg_FileServerQueryStatus(g_hServer, &isStarted, &nStatus);
253         if (!nResult)
254                 return nStatus;
255
256         bConfigured = isStarted;        
257         
258         g_LogFile.WriteBoolResult(bConfigured);
259
260         return 0;
261 }
262
263 static afs_status_t IsDBConfigured(BOOL& bConfigured)
264 {
265         g_LogFile.Write("Is this machine a db (or bak) server: ");
266
267         bConfigured = FALSE;
268
269         short isStarted, isBakStarted;
270         afs_status_t nStatus;
271
272         int nResult = cfg_DbServersQueryStatus(g_hServer, &isStarted, &isBakStarted, 0, &nStatus);
273         if (!nResult)
274                 return nStatus;
275
276         bConfigured = isStarted;
277         bBakConfigured = isBakStarted;
278
279         g_LogFile.Write(bConfigured ? "Yes DB" : "No DB");
280         g_LogFile.Write(", %s.\r\n", bBakConfigured ? "Yes Bak" : "No Bak");
281
282         return 0;
283 }
284
285 static afs_status_t IsBakConfigured(BOOL& bConfigured)
286 {
287         bConfigured = bBakConfigured;
288         
289         return 0;
290 }
291
292 static afs_status_t DoesAPartitionExist(BOOL& bExists)
293 {
294         g_LogFile.Write("Does a partition exist on this machine: ");
295
296         bExists = FALSE;
297
298         afs_status_t nStatus;
299
300         int nResult = ReadPartitionTable(&nStatus);
301         if (!nResult)
302                 return nStatus;
303
304         int nNumPartitions = 0;
305
306         cfg_partitionEntry_t *pTable = GetPartitionTable(nNumPartitions);
307
308         bExists = nNumPartitions > 0;
309         if (bExists) {
310                 g_CfgData.chDeviceName = pTable->deviceName[0];
311                 lstrcpy(g_CfgData.szPartitionName, ((TCHAR *)A2S(pTable->partitionName)) + lstrlen(TEXT("/vicep")));
312         }
313
314         g_LogFile.WriteBoolResult(bExists);
315
316         return 0;
317 }
318
319 afs_status_t DoRootVolumesExist(BOOL& bExists)
320 {
321         bExists = FALSE;
322
323         afs_status_t nStatus;
324
325         g_LogFile.Write("Do the root volumes exist: ");
326
327         // Does root.afs exist?  If it does not, the call will fail with the VL_NOENT
328         // status.  Any other error causes this function to fail.
329         int nResult = vos_VLDBGet(g_hCell, 0, 0, "root.afs", &vldbRootAfsEntry, &nStatus);
330         if (nResult) {
331                 g_CfgData.bRootAfsExists = TRUE;
332         g_CfgData.nRootAfsID = vldbRootAfsEntry.volumeId[0];
333         } else if (nStatus != VL_NOENT)
334                 return nStatus;
335
336         // Does root.cell exist?
337         nResult = vos_VLDBGet(g_hCell, 0, 0, "root.cell", &vldbRootCellEntry, &nStatus);
338         if (nResult) {
339                 g_CfgData.bRootCellExists = TRUE;
340         g_CfgData.nRootCellID = vldbRootCellEntry.volumeId[0];
341         } else if (nStatus != VL_NOENT)
342                 return nStatus;
343
344         bExists = g_CfgData.bRootAfsExists && g_CfgData.bRootCellExists;
345
346         g_LogFile.WriteBoolResult(bExists);
347
348         return 0;
349 }
350
351 static BOOL IsVolumeReplicated(vos_vldbEntry_t& vldbEntry)
352 {
353         if (vldbEntry.numServers <= 1)
354                 return FALSE;
355
356         for (int i = 0; i < vldbEntry.numServers; i++) {
357                 if ((vldbEntry.volumeSites[i].serverFlags & VOS_VLDB_READ_ONLY) ||
358                         (vldbEntry.volumeSites[i].serverFlags & VOS_VLDB_NEW_REPSITE))
359                                 return TRUE;
360         }
361
362         return FALSE;
363 }
364
365 afs_status_t AreRootVolumesReplicated(BOOL& bReplicated)
366 {
367         g_LogFile.Write("Are the root volumes replicated: ");
368
369         // Is root.afs replicated?
370         g_CfgData.bRootAfsReplicated = IsVolumeReplicated(vldbRootAfsEntry);
371
372         // Is root.cell replicated?
373         g_CfgData.bRootCellReplicated = IsVolumeReplicated(vldbRootCellEntry);
374
375         bReplicated = g_CfgData.bRootAfsReplicated && g_CfgData.bRootCellReplicated;
376
377         g_LogFile.WriteBoolResult(bReplicated);
378
379         return 0;
380 }
381
382 static afs_status_t IsSCSConfigured(BOOL& bConfigured)
383 {
384         g_LogFile.Write("Is this machine a System Control Server: ");
385         
386         bConfigured = FALSE;
387
388         short isUpserver, isSC, isBin;
389         afs_status_t nStatus;
390
391         int nResult = cfg_UpdateServerQueryStatus(g_hServer, &isUpserver, &isSC, &isBin, &nStatus);
392         if (!nResult)
393                 return nStatus;
394
395         bConfigured = isUpserver && isSC;
396
397         g_LogFile.WriteBoolResult(bConfigured);
398
399         return 0;
400 }
401
402 static afs_status_t IsSCCConfigured(BOOL& bConfigured)
403 {
404         g_LogFile.Write("Is this machine a System Control Client: ");
405         
406         bConfigured = FALSE;
407
408         short isUpclient, isSCC, isBin;
409         afs_status_t nStatus;
410
411         int nResult = cfg_UpdateClientQueryStatus(g_hServer, &isUpclient, &isSCC, &isBin, &nStatus);
412         if (!nResult)
413                 return nStatus;
414
415         bConfigured = isUpclient && isSCC;
416
417         g_LogFile.WriteBoolResult(bConfigured);
418
419         return 0;
420 }
421
422 static void ShowMsg(UINT uiMsgID)
423 {
424         TCHAR szMsg[cchRESOURCE];
425
426         GetString(szMsg, uiMsgID);
427         
428         pProg->SetOperation(szMsg);
429 }
430
431 static void NextStep(UINT uiMsgID)
432 {
433         static nCurStep = 1;
434
435         if (bCancel)
436                 return;
437         
438         ShowMsg(uiMsgID);
439
440         pProg->SetProgress(nCurStep++);
441
442         Sleep(50);
443 }
444
445 static BOOL CheckConfigState(afs_status_t (*ConfigCheckFunc)(BOOL&), CONFIG_STATE& state, afs_status_t& nStatus, UINT uiMsgID)
446 {
447         BOOL bState = FALSE;
448
449         if (bCancel)
450                 return FALSE;
451
452         NextStep(uiMsgID);
453
454         nStatus = ConfigCheckFunc(bState);
455         if (nStatus) {
456                 g_LogFile.WriteError("Config check failed", nStatus);
457                 return FALSE;
458         }
459
460         state = bState ? CS_ALREADY_CONFIGURED : CS_NULL;
461
462         return TRUE;
463 }
464                 
465 static DWORD CALLBACK GetCurrentConfigState(LPPROGRESSDISPLAY ppd, LPARAM lp)
466 {
467         afs_status_t nStatus = 0;
468
469         ASSERT(pProg);
470
471         g_LogFile.Write("Checking this machine's current configuration...\r\n");
472
473         if (!IsClientConfigured(g_CfgData.bValidClientInfo, nStatus))
474                 return nStatus;
475
476         if (!IsConfigInfoValid(g_CfgData.bValidServerInfo, nStatus))
477                 return nStatus;
478
479     // If the server and client have good config info, and the client is in a 
480     // different cell than the server, then the config routines will want to
481     // reconfigure the client.  To do so they need information that we already
482     // know and don't have to ask the user for.  Prefill this information here.
483     if (g_CfgData.bValidClientInfo && g_CfgData.bValidServerInfo && 
484         (lstrcmp(g_CfgData.szCellName, g_CfgData.szClientCellName) != 0))
485     {
486         lstrcpy(g_CfgData.szCellServDbHostname, g_CfgData.szHostname);
487     }
488
489         if (!GetLibHandles(&nStatus))
490                 return nStatus;
491
492         if (!CheckConfigState(DoesAPartitionExist, g_CfgData.configPartition, nStatus, IDS_CHECK_PARTITION))
493                 return nStatus;
494
495         if (g_CfgData.bValidServerInfo) {
496                 // Must check if bos server is running, and start it if it isn't.  We can't determine
497                 // if the services are running except by asking the bosserver.
498                 if (!StartBosServer(nStatus))
499                         return nStatus;
500
501                 if (!CheckConfigState(IsFSConfigured, g_CfgData.configFS, nStatus, IDS_CHECK_FS_CONFIG))
502                         return nStatus;
503
504                 if (!CheckConfigState(IsDBConfigured, g_CfgData.configDB, nStatus, IDS_CHECK_DB_CONFIG))
505                         return nStatus;
506
507                 if (g_CfgData.configDB == CS_ALREADY_CONFIGURED) {
508                         if (!AreWeLastDBServer(g_CfgData.bLastDBServer, nStatus))
509                                 return nStatus;
510                 }
511
512                 if (!CheckConfigState(IsBakConfigured, g_CfgData.configBak, nStatus, IDS_CHECK_BAK_CONFIG))
513                         return nStatus;
514
515                 if (!CheckConfigState(DoRootVolumesExist, g_CfgData.configRootVolumes, nStatus, IDS_CHECK_ROOT_AFS))
516             return nStatus;
517
518         g_CfgData.bRootVolumesExistanceKnown = TRUE;
519
520                 if (!CheckConfigState(AreRootVolumesReplicated, g_CfgData.configRep, nStatus, IDS_CHECK_REP))
521             return nStatus;
522         
523         g_CfgData.bRootVolumesReplicationKnown = TRUE;
524
525                 if (!CheckConfigState(IsSCSConfigured, g_CfgData.configSCS, nStatus, IDS_CHECK_SCS))
526                         return nStatus;
527
528                 if (!CheckConfigState(IsSCCConfigured, g_CfgData.configSCC, nStatus, IDS_CHECK_SCC))
529                         return nStatus;
530         }
531
532         if (!bCancel)
533                 pProg->SetProgress(MAX_STEPS);
534         
535         return 0;
536 }
537