8a7fa054df528bcf9bf737bc542d469ae4f53698
[openafs.git] / src / WINNT / afssvrcfg / partitions_page.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 "resource.h"
21 #include "create_partition_dlg.h"
22 #include "partition_utils.h"
23 #include "salvage_results_dlg.h"
24 extern "C" {
25 #include <afs\afs_vosAdmin.h>
26 #include <afs\afs_clientAdmin.h>
27 }
28
29
30 // TODO:  Add context menu to fastlist
31
32
33 /*
34  * DEFINITIONS _________________________________________________________________
35  *
36  */
37 #define MAX_PARTITIONS  26
38
39 static HWND hDlg = 0;
40 static HWND hPartitionList = 0;
41 static HLISTITEM hSelectedItem;
42
43 static TCHAR szYes[cchRESOURCE];
44 static TCHAR szNo[cchRESOURCE];
45
46 static const UINT DISK_DRIVE_IMAGE = 0;
47 static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
48
49 // Remember the config state of the FS so we can detect when it changes.
50 // When it changes we must redisplay the partition info.
51 static CONFIG_STATE configFS;
52
53
54
55 /*
56  * PROTOTYPES _________________________________________________________________
57  *
58  */
59 BOOL ShowSalvageDlg(HWND hParent, LPCTSTR pszPartitionName);
60
61 static void OnCreatePartitions();
62 static void OnInitDialog(HWND hwndDlg);
63 static void SetupListCols();
64 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags = FLCF_JUSTIFY_LEFT);
65 static void ShowPartitions();
66 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries);
67 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions);
68 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms);
69 static void SetupImageLists();
70 static void OnRemove();
71 static BOOL CheckShowPartitions();
72 static void OnSalvage();
73 static void CheckEnableSalvage();
74
75
76 /*
77  * EXPORTED FUNCTIONS _________________________________________________________________
78  *
79  */
80 /*
81  * Dialog Proc _________________________________________________________________
82  *
83  */
84 BOOL CALLBACK PartitionsPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
85 {
86         if (AfsAppLib_HandleHelp(IDD_PARTITIONS_PAGE, hwndDlg, uMsg, wParam, lParam))
87                 return TRUE;
88
89         switch (uMsg) {
90                 case WM_INITDIALOG:     OnInitDialog(hwndDlg);
91                                                         break;
92         
93                 case WM_COMMAND:        switch (LOWORD(wParam)) {
94                                                                 case IDINIT:            CheckShowPartitions();
95                                                                                                         break;
96
97                                                                 case IDC_CREATE_PARTITIONS:     
98                                                                                                         OnCreatePartitions();
99                                                                                                         break;
100                                                         
101                                                                 case IDC_REMOVE:        OnRemove();
102                                                                                                         break;
103
104                                                                 case IDC_SALVAGE:       OnSalvage();
105                                                                                                         break;
106                                                         }
107                                                         break;
108
109                 case WM_NOTIFY:         if ((((LPNMHDR)lParam)->code) == FLN_ITEMSELECT)
110                                                                 OnListSelection((LPFLN_ITEMSELECT_PARAMS)lParam);
111                                                         break;
112         }
113
114         return FALSE;
115 }
116
117 void UpdatePartitionList()
118 {
119         ShowPartitions();
120         CheckEnableSalvage();
121 }
122
123
124 /*
125  * STATIC FUNCTIONS _________________________________________________________________
126  *
127  */
128
129 /*
130  * Event Handler Functions _________________________________________________________________
131  *
132  */
133 static void OnInitDialog(HWND hwndDlg)
134 {
135         hDlg = hwndDlg;
136
137 //      PropSheet_CancelToClose(GetParent(hDlg));
138
139         hSelectedItem = 0;
140
141         hPartitionList = GetDlgItem(hDlg, IDC_PARTITION_LIST);
142         _ASSERTE(hPartitionList);
143
144         SetupImageLists();
145
146         GetString(szYes, IDS_YES);
147         GetString(szNo, IDS_NO);
148
149         SetupListCols();
150
151         configFS = g_CfgData.configFS;
152
153         ShowPartitions();
154
155         CheckEnableSalvage();
156 }
157
158 static void OnCreatePartitions()
159 {
160         if (CreatePartition(hDlg))
161                 ShowPartitions();
162 }
163
164 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms)
165 {
166         ASSERT(pItemParms);
167
168         hSelectedItem = pItemParms->hItem;
169
170         ENABLE_STATE es = pItemParms->hItem ? ES_ENABLE : ES_DISABLE;
171
172         SetEnable(hDlg, IDC_REMOVE, es);
173         SetEnable(hDlg, IDC_REMOVE_MSG, es);
174 }
175
176 static void OnRemove()
177 {
178         ASSERT(hSelectedItem);
179         ASSERT(g_hServer);
180         
181         afs_status_t nStatus;
182
183         BOOL bExported = (BOOL)FastList_GetItemParam(hPartitionList, hSelectedItem);
184         if (bExported) {
185                 MsgBox(hDlg, IDS_CANT_DELETE_EXPORTED_PARTITION, GetAppTitleID(), MB_OK | MB_ICONSTOP);
186                 return;
187         }
188
189         LPCTSTR pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
190         ASSERT(pszPartitionName);
191
192         int nResult = Message(MB_ICONQUESTION | MB_YESNO, GetAppTitleID(), IDS_DELETE_PARTITION_PROMPT, TEXT("%s"), pszPartitionName);
193         if (nResult == IDNO)
194                 return;
195
196         g_LogFile.Write("Removing partition '%s'.\r\n", (char *)S2A(pszPartitionName));
197         nResult = cfg_HostPartitionTableRemoveEntry(g_hServer, S2A(pszPartitionName), &nStatus);
198         if (!nResult) {
199                 ShowError(hDlg, nStatus, IDS_REMOVE_PARTITION_ERROR);
200                 return;
201         }
202
203         FastList_RemoveItem(hPartitionList, hSelectedItem);
204
205         CheckEnableSalvage();
206 }
207
208 static void OnSalvage()
209 {
210     // Can't salvage if the file server is not configured
211     if (!Configured(g_CfgData.configFS)) {
212         ShowError(hDlg, 0, IDS_CANT_SALVAGE_WHEN_FS_NOT_CONFIGURED);
213         return;
214     }
215
216         LPCTSTR pszPartitionName = TEXT("");
217
218         if (hSelectedItem) {
219                 pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
220                 ASSERT(pszPartitionName);
221         }       
222
223         if (!ShowSalvageDlg(hDlg, pszPartitionName))
224         return;
225
226     ShowSalvageResults(hDlg);
227
228     // Since a salvage was performed, there may be partitions exported that were
229     // not exported before the salvage.  Salvage may stop and restart the file
230     // server, which will pick up the previously unexported partitions.  We will
231     // update our partition list in case this has happened.
232     UpdatePartitionList();
233 }
234
235
236 /*
237  * Utility Functions _________________________________________________________________
238  *
239  */
240 static BOOL CheckShowPartitions()
241 {
242         if (configFS != g_CfgData.configFS) {
243                 configFS = g_CfgData.configFS;
244         UpdatePartitionList();
245                 return TRUE;
246         }
247
248         return FALSE;
249 }
250
251 static void SetupImageLists()
252 {
253         HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
254
255         AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
256         AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
257
258         FastList_SetImageLists(hPartitionList, hiList, 0);
259 }
260
261 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags)
262 {
263         static int nCol = 1;
264         FASTLISTCOLUMN col;
265         
266         col.dwFlags = dwFlags;
267         col.cxWidth = nWidth;
268         lstrcpy(col.szText, pszTitle);
269         
270         FastList_SetColumn(hPartitionList, nCol++, &col);
271 }
272
273 static void SetupListCols()
274 {
275         TCHAR szMsg[cchRESOURCE];
276
277         AddColumn(75, GetResString(IDS_NAME, szMsg));
278         AddColumn(55, GetResString(IDS_DRIVE, szMsg));
279         AddColumn(60, GetResString(IDS_EXPORTED, szMsg));
280         AddColumn(75, GetResString(IDS_TOTAL, szMsg), FLCF_JUSTIFY_RIGHT);
281         AddColumn(75, GetResString(IDS_FREE, szMsg), FLCF_JUSTIFY_RIGHT);
282 }
283
284 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries)
285 {
286         afs_status_t nStatus;
287  
288         // Read the parition table out of the registry
289         int nResult = ReadPartitionTable(&nStatus);
290         if (!nResult) {
291                 ShowError(hDlg, nStatus, IDS_READ_PARTITIONS_ERROR);
292                 return 0;
293         }
294
295         return GetPartitionTable(cEntries);
296 }
297
298 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions)
299 {
300         ASSERT(g_hCell);
301         ASSERT(g_CfgData.szHostname[0]);
302
303         nNumPartitions = 0;
304
305         if (g_CfgData.configFS != CS_ALREADY_CONFIGURED)
306                 return 0;
307
308         static vos_partitionEntry_t aPartitions[MAX_PARTITIONS];
309         afs_status_t nStatus, nIgnore;
310         void *hServer = 0;
311         int nNumParts = 0;
312
313         // Open this server
314         g_LogFile.Write("Opening server %s.\r\n", GetHostnameA());
315         int nResult = vos_ServerOpen(g_hCell, GetHostnameA(), &hServer, &nStatus);
316         if (nResult) {
317                 
318                 // Read the partition info
319                 g_LogFile.Write("Reading paritition information for this server.\r\n");
320                 void *iterID;
321
322                 nResult = vos_PartitionGetBegin(g_hCell, hServer, 0, &iterID, &nStatus);
323                 if (nResult) {
324                         while (nNumParts < MAX_PARTITIONS) {
325                                 nResult = vos_PartitionGetNext(iterID, &aPartitions[nNumParts], &nStatus);
326                                 if (!nResult) {
327                                         if (nStatus == ADMITERATORDONE) {
328                                                 nResult = 1;
329                                                 nStatus = 0;
330                                         }
331                                         break;
332                                 }
333
334                                 nNumParts++;
335                         }
336                         vos_PartitionGetDone(iterID, &nIgnore);
337                 }
338                 vos_ServerClose(hServer, &nIgnore);
339         }
340         
341         if (!nResult) {
342                 ShowError(hDlg, nStatus, IDS_GET_PARTITION_LIST_ERROR);
343                 return 0;
344         }
345
346         nNumPartitions = nNumParts;
347
348         return aPartitions;
349 }
350
351 // Convert a disk space value in Kbytes into a string
352 static LPTSTR DiskSpaceToString(int nSpace)
353 {
354         const float oneMB = 1024;       // in K bytes
355         const double oneGB = oneMB * 1024;
356         const double oneTB = oneGB * 1024;
357
358         static TCHAR szSpace[64];
359         double space;
360         LPTSTR pszUnits;
361
362         space = nSpace; 
363
364         if (space >= oneTB) {
365                 space /= oneTB;
366                 pszUnits = TEXT(" TB");
367         } else if (space >= oneGB) {
368                 space /= oneGB;
369                 pszUnits = TEXT(" GB");
370     } else if (space >= oneMB) {
371                 space /= oneMB;
372                 pszUnits = TEXT(" MB");
373         } else
374                 pszUnits = TEXT(" KB");
375
376         int nNumDecimals = 0;
377         if (space - double(int(space)) > 0)
378                 nNumDecimals = 2;
379
380         _stprintf(szSpace, TEXT("%3.*f%s"), nNumDecimals, space, pszUnits);
381
382         return szSpace;
383 }
384
385 static void ShowPartitions()
386 {
387         FastList_RemoveAll(hPartitionList);
388
389         int cRegParts = 0, cVosParts = 0;
390
391     // If we got nothing from the registry, then leave the list empty
392         cfg_partitionEntry_t *pRegParts = GetPartitionTableFromRegistry(cRegParts);
393     if (!pRegParts)
394         return;
395
396     // If we failed to get vos info, then only show the registry info
397         vos_partitionEntry_t *pVosParts = GetPartitionTableFromVos(cVosParts);
398     if (!pVosParts)
399         cVosParts = 0;
400
401         // We have two partition tables, one from the registry and one from the vos
402         // library.  The one from the vos library tells us the partitions that are
403         // currently exported.  The one from the registry tells us the partitions
404         // that will be exported after the file server restarts.  The registry list
405         // should always be at least as big as the vos list.  The vos list can be
406         // smaller if one of the disks could not be exported.  To add a new partition,
407         // an entry must be added to the registry table and then the file server must
408         // be restarted.  To remove an entry, the partition must not be exported (due
409         // to an error) or the file server must not be running, in which case nothing
410         // will be exported.
411
412         // To display the partitions to the user, we use the list from the registry,
413         // looking up each of its entries in the vos list to see if it is exported,
414         // and if it is, to get its size info.
415
416
417         for (int nCurRegPart = 0; nCurRegPart < cRegParts; nCurRegPart++) {
418         LPTSTR pPartNameAsString = AnsiToString(pRegParts[nCurRegPart].partitionName);
419
420         // Show the partition in the list
421                 FASTLISTADDITEM ai = { 0, DISK_DRIVE_IMAGE, IMAGE_NOIMAGE, pPartNameAsString, 0, 0 };
422                 HLISTITEM hItem = FastList_AddItem(hPartitionList, &ai);
423
424         FreeString(pPartNameAsString);
425
426                 FastList_SetItemText(hPartitionList, hItem, 1, pRegParts[nCurRegPart].deviceName);
427                 
428                 // For the rest of the info we need to know if this guy is exported.
429                 // Look him up in the vos table.
430                 BOOL bExported = FALSE;
431                 int nTotalSpace = 0;
432                 int nFreeSpace = 0;
433                 
434                 for (int nCurVosPart = 0; nCurVosPart < cVosParts; nCurVosPart++) {
435                         if (stricmp(pVosParts[nCurVosPart].name, pRegParts[nCurRegPart].partitionName) == 0) {
436                                 bExported = TRUE;
437                                 nTotalSpace = pVosParts[nCurVosPart].totalSpace;
438                                 nFreeSpace = pVosParts[nCurVosPart].totalFreeSpace;
439                                 break;
440                         }
441                 }
442
443                 FastList_SetItemText(hPartitionList, hItem, 2, bExported ? szYes : szNo);
444                 FastList_SetItemText(hPartitionList, hItem, 3, bExported ? DiskSpaceToString(nTotalSpace) : TEXT(""));
445                 FastList_SetItemText(hPartitionList, hItem, 4, bExported ? DiskSpaceToString(nFreeSpace) : TEXT(""));
446                 
447                 // Set the item param to indicate that this partition is exported or not
448                 FastList_SetItemParam(hPartitionList, hItem, bExported);
449         
450         
451     }
452 }
453
454 static void CheckEnableSalvage()
455 {
456         ENABLE_STATE es = (FastList_GetItemCount(hPartitionList) > 0) ? ES_ENABLE : ES_DISABLE;
457
458         SetEnable(hDlg, IDC_SALVAGE, es);
459         SetEnable(hDlg, IDC_SALVAGE_MSG, es);
460 }
461