From 7883f650a9e4bd9f691493f002e533739dcd00c7 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Sat, 6 Aug 2011 15:42:35 +0530 Subject: Renamed project/package com.gluster.storage.management.gui to com.gluster.storage.management.console --- .../.classpath | 7 + .../.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../META-INF/MANIFEST.MF | 29 + .../build.properties | 15 + .../icons/tango/16x16/arrow-down.png | Bin 0 -> 703 bytes .../icons/tango/16x16/arrow-up.png | Bin 0 -> 712 bytes .../icons/tango/16x16/bricks.png | Bin 0 -> 807 bytes .../icons/tango/16x16/close_task.png | Bin 0 -> 588 bytes .../icons/tango/16x16/cluster.png | Bin 0 -> 622 bytes .../icons/tango/16x16/disk-available.png | Bin 0 -> 769 bytes .../icons/tango/16x16/disk-error.png | Bin 0 -> 801 bytes .../icons/tango/16x16/disk-initialisation.png | Bin 0 -> 817 bytes .../icons/tango/16x16/disk-inuse.png | Bin 0 -> 798 bytes .../icons/tango/16x16/disk-uninitialized.png | Bin 0 -> 809 bytes .../icons/tango/16x16/disk.png | Bin 0 -> 717 bytes .../icons/tango/16x16/gluster_icon.png | Bin 0 -> 3131 bytes .../icons/tango/16x16/help.png | Bin 0 -> 932 bytes .../icons/tango/16x16/logs.png | Bin 0 -> 796 bytes .../icons/tango/16x16/offline-brick.png | Bin 0 -> 621 bytes .../icons/tango/16x16/online-brick.png | Bin 0 -> 532 bytes .../icons/tango/16x16/pause.png | Bin 0 -> 729 bytes .../icons/tango/16x16/question.png | Bin 0 -> 766 bytes .../icons/tango/16x16/running-task.png | Bin 0 -> 858 bytes .../icons/tango/16x16/server.png | Bin 0 -> 725 bytes .../icons/tango/16x16/servers.png | Bin 0 -> 393 bytes .../icons/tango/16x16/settings.png | Bin 0 -> 588 bytes .../icons/tango/16x16/start.png | Bin 0 -> 734 bytes .../icons/tango/16x16/status-offline.png | Bin 0 -> 945 bytes .../icons/tango/16x16/status-online.png | Bin 0 -> 689 bytes .../icons/tango/16x16/stop.png | Bin 0 -> 690 bytes .../icons/tango/16x16/task-completed.png | Bin 0 -> 767 bytes .../icons/tango/16x16/task-error.png | Bin 0 -> 768 bytes .../icons/tango/16x16/view-refresh.png | Bin 0 -> 912 bytes .../icons/tango/16x16/volume-create.png | Bin 0 -> 635 bytes .../icons/tango/16x16/volume-options.png | Bin 0 -> 713 bytes .../icons/tango/16x16/volume.png | Bin 0 -> 774 bytes .../icons/tango/16x16/volumes.png | Bin 0 -> 830 bytes .../icons/tango/22x22/disk-initialisation.png | Bin 0 -> 1100 bytes .../icons/tango/22x22/high-memory-usage.png | Bin 0 -> 834 bytes .../icons/tango/22x22/low-diskspace.png | Bin 0 -> 1042 bytes .../icons/tango/22x22/offline-brick.png | Bin 0 -> 880 bytes .../icons/tango/22x22/offline-server.png | Bin 0 -> 1276 bytes .../icons/tango/22x22/replace-brick.png | Bin 0 -> 1213 bytes .../icons/tango/22x22/server-warning.png | Bin 0 -> 806 bytes .../icons/tango/22x22/system-search.png | Bin 0 -> 1267 bytes .../icons/tango/22x22/volume-rebalance.png | Bin 0 -> 955 bytes .../icons/tango/32x32/add-brick.png | Bin 0 -> 2105 bytes .../icons/tango/32x32/add-server.png | Bin 0 -> 2137 bytes .../icons/tango/32x32/clear-task.png | Bin 0 -> 1424 bytes .../icons/tango/32x32/commit-task.png | Bin 0 -> 1294 bytes .../icons/tango/32x32/create-volume-disabled.png | Bin 0 -> 1929 bytes .../icons/tango/32x32/create-volume.png | Bin 0 -> 1788 bytes .../icons/tango/32x32/disk.png | Bin 0 -> 1155 bytes .../icons/tango/32x32/download-log.png | Bin 0 -> 2065 bytes .../icons/tango/32x32/help.png | Bin 0 -> 2231 bytes .../icons/tango/32x32/logs.png | Bin 0 -> 1886 bytes .../icons/tango/32x32/pause.png | Bin 0 -> 1037 bytes .../icons/tango/32x32/remove-brick-disabled.png | Bin 0 -> 2206 bytes .../icons/tango/32x32/remove-brick.png | Bin 0 -> 1988 bytes .../icons/tango/32x32/remove-server.png | Bin 0 -> 2143 bytes .../icons/tango/32x32/remove-volume.png | Bin 0 -> 1712 bytes .../icons/tango/32x32/replace-brick.png | Bin 0 -> 2343 bytes .../icons/tango/32x32/reset-volume-option.png | Bin 0 -> 2303 bytes .../icons/tango/32x32/server.png | Bin 0 -> 1591 bytes .../icons/tango/32x32/servers.png | Bin 0 -> 1264 bytes .../icons/tango/32x32/settings.png | Bin 0 -> 2544 bytes .../icons/tango/32x32/start-volume-disabled.png | Bin 0 -> 1968 bytes .../icons/tango/32x32/start-volume.png | Bin 0 -> 1818 bytes .../icons/tango/32x32/start.png | Bin 0 -> 1207 bytes .../icons/tango/32x32/stop-volume-disabled.png | Bin 0 -> 1851 bytes .../icons/tango/32x32/stop-volume.png | Bin 0 -> 1754 bytes .../icons/tango/32x32/stop.png | Bin 0 -> 540 bytes .../icons/tango/32x32/view-refresh.png | Bin 0 -> 2024 bytes .../icons/tango/32x32/volume-rebalance.png | Bin 0 -> 1969 bytes .../icons/tango/32x32/volume.png | Bin 0 -> 1446 bytes .../icons/tango/48x48/add-server.png | Bin 0 -> 3606 bytes .../icons/tango/48x48/create-volume.png | Bin 0 -> 2898 bytes .../icons/tango/48x48/remove-brick-disabled.png | Bin 0 -> 3186 bytes .../icons/tango/48x48/server.png | Bin 0 -> 3295 bytes .../icons/tango/48x48/start-volume-disabled.png | Bin 0 -> 2742 bytes .../icons/tango/48x48/stop-volume-disabled.png | Bin 0 -> 2470 bytes .../icons/tango/8x8/offline.png | Bin 0 -> 381 bytes .../icons/tango/8x8/online.png | Bin 0 -> 315 bytes .../icons/tango/8x8/star.png | Bin 0 -> 244 bytes .../icons/tango/scalable/add_brick.svg | 4155 ++++++++++++++++++ .../icons/tango/scalable/add_volume.svg | 3235 ++++++++++++++ .../icons/tango/scalable/brick.svg | 652 +++ .../icons/tango/scalable/brick_migration.svg | 3620 ++++++++++++++++ .../icons/tango/scalable/bricks.svg | 684 +++ .../icons/tango/scalable/cloud.svg | 425 ++ .../tango/scalable/create-volume-disabled.svg | 3044 +++++++++++++ .../icons/tango/scalable/create-volume.svg | 3006 +++++++++++++ .../icons/tango/scalable/disk (32-32).svg | 1088 +++++ .../icons/tango/scalable/disk (48-48).svg | 2263 ++++++++++ .../icons/tango/scalable/disk.svg | 850 ++++ .../icons/tango/scalable/disk_available.svg | 1983 +++++++++ .../icons/tango/scalable/disk_error.svg | 1991 +++++++++ .../icons/tango/scalable/disk_initialisation.svg | 2302 ++++++++++ .../icons/tango/scalable/disk_inuse.svg | 1848 ++++++++ .../icons/tango/scalable/disk_uninitialised.svg | 2585 +++++++++++ .../icons/tango/scalable/download_log.svg | 1187 ++++++ .../icons/tango/scalable/high_CPU_usage.svg | 1661 ++++++++ .../icons/tango/scalable/high_memory_usage.svg | 589 +++ .../icons/tango/scalable/log.svg | 1160 +++++ .../icons/tango/scalable/low_diskspace.svg | 1790 ++++++++ .../icons/tango/scalable/offline-8x8.svg | 154 + .../icons/tango/scalable/offline.svg | 1637 +++++++ .../icons/tango/scalable/offline_brick_alert.svg | 713 ++++ .../icons/tango/scalable/offline_server.svg | 838 ++++ .../icons/tango/scalable/offline_volume.svg | 3171 ++++++++++++++ .../icons/tango/scalable/online-8x8.svg | 246 ++ .../icons/tango/scalable/online.svg | 1410 ++++++ .../icons/tango/scalable/remove-server.svg | 141 + .../icons/tango/scalable/remove_brick.svg | 4483 ++++++++++++++++++++ .../icons/tango/scalable/remove_volume.svg | 3248 ++++++++++++++ .../icons/tango/scalable/reset_volume_option.svg | 2946 +++++++++++++ .../icons/tango/scalable/running_task.svg | 1498 +++++++ .../icons/tango/scalable/star-8x8.svg | 15 + .../icons/tango/scalable/start-volume-disabled.svg | 3350 +++++++++++++++ .../icons/tango/scalable/start_volume.svg | 3312 +++++++++++++++ .../icons/tango/scalable/stop_volume.svg | 3268 ++++++++++++++ .../icons/tango/scalable/task_clear.svg | 845 ++++ .../icons/tango/scalable/task_commit.svg | 310 ++ .../icons/tango/scalable/task_pause.svg | 821 ++++ .../icons/tango/scalable/task_paused.svg | 812 ++++ .../icons/tango/scalable/task_resume.svg | 395 ++ .../icons/tango/scalable/task_running.svg | 796 ++++ .../icons/tango/scalable/task_status_completed.svg | 577 +++ .../icons/tango/scalable/task_status_error.svg | 654 +++ .../icons/tango/scalable/task_stop.svg | 748 ++++ .../icons/tango/scalable/task_stopped.svg | 784 ++++ .../icons/tango/scalable/view-refresh.svg | 393 ++ .../icons/tango/scalable/volume.svg | 2917 +++++++++++++ .../icons/tango/scalable/volume_option.svg | 2875 +++++++++++++ .../icons/tango/scalable/volume_rebalance.svg | 3713 ++++++++++++++++ .../icons/tango/scalable/volumes.svg | 2949 +++++++++++++ .../images/gauge.png | Bin 0 -> 45242 bytes .../images/gauge_small.png | Bin 0 -> 13875 bytes .../plugin.xml | 1566 +++++++ .../preferences.ini | 2 + .../splash.bmp | Bin 0 -> 398896 bytes .../splash/gluster_about.jpg | Bin 0 -> 4072 bytes .../splash/splash-dialog.bmp | Bin 0 -> 312054 bytes .../splash/splash-dialog.png | Bin 0 -> 5552 bytes .../storage/management/console/Activator.java | 83 + .../storage/management/console/AlertsManager.java | 212 + .../storage/management/console/Application.java | 135 + .../console/ApplicationActionBarAdvisor.java | 100 + .../console/ApplicationWorkbenchAdvisor.java | 98 + .../console/ApplicationWorkbenchWindowAdvisor.java | 63 + .../console/BrickTableLabelProvider.java | 85 + .../console/DeviceTableLabelProvider.java | 160 + .../console/EntityGroupContentProvider.java | 45 + .../console/GlusterDataModelManager.java | 923 ++++ .../console/GlusterServerTableLabelProvider.java | 77 + .../storage/management/console/ICommandIds.java | 33 + .../management/console/IEntityListener.java | 37 + .../storage/management/console/IImageKeys.java | 96 + .../NetworkInterfaceTableLabelProvider.java | 43 + .../storage/management/console/Perspective.java | 36 + .../console/ServerDiskTableLabelProvider.java | 133 + .../console/ServerTableLabelProvider.java | 52 + .../console/TableLabelProviderAdapter.java | 58 + .../console/TasksTableLabelProvider.java | 71 + .../console/VolumeLogTableLabelProvider.java | 40 + .../console/VolumeOptionsContentProvider.java | 47 + .../console/VolumeOptionsTableLabelProvider.java | 38 + .../console/VolumeTableLabelProvider.java | 82 + .../console/actions/AbstractActionDelegate.java | 117 + .../management/console/actions/AddBrickAction.java | 64 + .../console/actions/AddServerAction.java | 126 + .../console/actions/ChangePasswordAction.java | 23 + .../console/actions/ClearTaskAction.java | 46 + .../console/actions/CommitTaskAction.java | 72 + .../console/actions/CreateVolumeAction.java | 53 + .../console/actions/DeleteVolumeAction.java | 143 + .../console/actions/DownloadVolumeLogsAction.java | 77 + .../console/actions/EditVolumeAction.java | 33 + .../console/actions/ExportSshKeysAction.java | 77 + .../console/actions/IActionConstants.java | 36 + .../console/actions/ImportSshKeysAction.java | 44 + .../console/actions/MigrateBrickAction.java | 65 + .../console/actions/MigrateVolumeAction.java | 33 + .../console/actions/PauseTaskAction.java | 67 + .../console/actions/PreferencesAction.java | 36 + .../console/actions/RebalanceVolumeAction.java | 72 + .../console/actions/RefreshDataAction.java | 43 + .../console/actions/RemoveBrickAction.java | 91 + .../console/actions/RemoveServerAction.java | 156 + .../console/actions/ResetVolumeOptionsAction.java | 63 + .../console/actions/ResumeTaskAction.java | 45 + .../console/actions/ServerAdditionAction.java | 28 + .../console/actions/StartVolumeAction.java | 133 + .../management/console/actions/StopTaskAction.java | 46 + .../console/actions/StopVolumeAction.java | 152 + .../console/actions/TestPopupMenuAction.java | 63 + .../management/console/dialogs/AddBrickPage.java | 171 + .../management/console/dialogs/AddBrickWizard.java | 96 + .../console/dialogs/BricksSelectionPage.java | 334 ++ .../console/dialogs/ChangePasswordDialog.java | 284 ++ .../console/dialogs/ClusterSelectionDialog.java | 441 ++ .../console/dialogs/CreateVolumePage1.java | 479 +++ .../console/dialogs/CreateVolumeWizard.java | 121 + .../dialogs/InitializeDiskTypeSelection.java | 148 + .../management/console/dialogs/LoginDialog.java | 306 ++ .../console/dialogs/MigrateBrickPage1.java | 274 ++ .../console/dialogs/MigrateBrickWizard.java | 94 + .../console/dialogs/SelectDisksDialog.java | 117 + .../console/dialogs/ServerAdditionDialog.java | 197 + .../management/console/jobs/DataSyncJob.java | 68 + .../console/preferences/AlertsPreferencePage.java | 38 + .../console/preferences/ChartsPreferencePage.java | 65 + .../console/preferences/GlusterPreferencePage.java | 90 + .../console/preferences/PreferenceConstants.java | 40 + .../console/preferences/PreferenceInitializer.java | 60 + .../console/toolbar/GlusterToolbarManager.java | 105 + .../management/console/toolbar/ToolbarManager.java | 35 + .../management/console/utils/ChartUtil.java | 339 ++ .../console/utils/ChartViewerComposite.java | 465 ++ .../console/utils/EntityViewerFilter.java | 78 + .../management/console/utils/GUIHelper.java | 492 +++ .../console/utils/GlusterChartPalette.java | 479 +++ .../management/console/utils/GlusterLogger.java | 67 + .../management/console/utils/ImageUtil.java | 52 + .../validators/StringRequiredValidator.java | 61 + .../console/views/ClusterAdapterFactory.java | 101 + .../console/views/ClusterSummaryView.java | 433 ++ .../console/views/DiscoveredServerView.java | 90 + .../console/views/DiscoveredServersView.java | 83 + .../management/console/views/DisksView.java | 45 + .../console/views/GlusterServerDisksView.java | 84 + .../console/views/GlusterServerLogsView.java | 59 + .../console/views/GlusterServerSummaryView.java | 513 +++ .../console/views/GlusterServersSummaryView.java | 276 ++ .../console/views/GlusterServersView.java | 78 + .../console/views/GlusterViewsManager.java | 130 + .../views/NavigationTreeLabelDecorator.java | 87 + .../management/console/views/NavigationView.java | 160 + .../management/console/views/TasksView.java | 39 + .../management/console/views/ViewsManager.java | 38 + .../management/console/views/VolumeBricksView.java | 39 + .../management/console/views/VolumeLogsView.java | 35 + .../console/views/VolumeOptionsView.java | 36 + .../console/views/VolumeSummaryView.java | 750 ++++ .../management/console/views/VolumeView.java | 90 + .../console/views/VolumesSummaryView.java | 264 ++ .../management/console/views/VolumesView.java | 80 + .../console/views/pages/AbstractDisksPage.java | 302 ++ .../views/pages/AbstractTableTreeViewerPage.java | 191 + .../views/pages/AbstractTableViewerPage.java | 234 + .../management/console/views/pages/BricksPage.java | 116 + .../views/pages/DiskTreeContentProvider.java | 123 + .../management/console/views/pages/DisksPage.java | 70 + .../console/views/pages/GlusterServersPage.java | 131 + .../views/pages/OptionKeyEditingSupport.java | 120 + .../views/pages/OptionValueEditingSupport.java | 110 + .../console/views/pages/ServerDisksPage.java | 66 + .../console/views/pages/ServerLogsPage.java | 199 + .../console/views/pages/ServersPage.java | 131 + .../management/console/views/pages/TasksPage.java | 144 + .../console/views/pages/VolumeLogsPage.java | 426 ++ .../console/views/pages/VolumeOptionsPage.java | 360 ++ .../console/views/pages/VolumesPage.java | 122 + .../src/test.xml | 1 + 265 files changed, 108495 insertions(+) create mode 100644 src/com.gluster.storage.management.console/.classpath create mode 100644 src/com.gluster.storage.management.console/.project create mode 100644 src/com.gluster.storage.management.console/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.console/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.console/build.properties create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/arrow-down.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/arrow-up.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/bricks.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/close_task.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/cluster.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk-available.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk-error.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk-initialisation.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk-inuse.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk-uninitialized.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/disk.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/gluster_icon.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/help.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/logs.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/offline-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/online-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/pause.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/question.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/running-task.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/servers.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/settings.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/start.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/status-offline.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/status-online.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/stop.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/task-completed.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/task-error.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/view-refresh.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/volume-create.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/volume-options.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/16x16/volumes.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/disk-initialisation.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/high-memory-usage.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/low-diskspace.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/offline-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/offline-server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/replace-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/server-warning.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/system-search.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/22x22/volume-rebalance.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/add-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/add-server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/clear-task.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/commit-task.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/create-volume-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/create-volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/disk.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/download-log.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/help.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/logs.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/pause.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/remove-server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/remove-volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/replace-brick.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/reset-volume-option.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/servers.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/settings.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/start-volume-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/start-volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/start.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/stop.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/view-refresh.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/volume-rebalance.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/32x32/volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/add-server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/create-volume.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/remove-brick-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/server.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/start-volume-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/48x48/stop-volume-disabled.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/8x8/offline.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/8x8/online.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/8x8/star.png create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/add_brick.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/add_volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/brick.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/brick_migration.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/bricks.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/cloud.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/create-volume-disabled.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/create-volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk (32-32).svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk (48-48).svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk_available.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk_error.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk_initialisation.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk_inuse.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/disk_uninitialised.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/download_log.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/high_CPU_usage.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/high_memory_usage.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/log.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/low_diskspace.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/offline-8x8.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/offline.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/offline_brick_alert.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/offline_server.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/offline_volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/online-8x8.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/online.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/remove-server.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/remove_brick.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/remove_volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/reset_volume_option.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/running_task.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/star-8x8.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/start-volume-disabled.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/start_volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/stop_volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_clear.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_commit.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_pause.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_paused.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_resume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_running.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_status_completed.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_status_error.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_stop.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/task_stopped.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/view-refresh.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/volume.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/volume_option.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/volume_rebalance.svg create mode 100644 src/com.gluster.storage.management.console/icons/tango/scalable/volumes.svg create mode 100644 src/com.gluster.storage.management.console/images/gauge.png create mode 100644 src/com.gluster.storage.management.console/images/gauge_small.png create mode 100644 src/com.gluster.storage.management.console/plugin.xml create mode 100644 src/com.gluster.storage.management.console/preferences.ini create mode 100644 src/com.gluster.storage.management.console/splash.bmp create mode 100644 src/com.gluster.storage.management.console/splash/gluster_about.jpg create mode 100644 src/com.gluster.storage.management.console/splash/splash-dialog.bmp create mode 100644 src/com.gluster.storage.management.console/splash/splash-dialog.png create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Activator.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/AlertsManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Application.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationActionBarAdvisor.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchAdvisor.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchWindowAdvisor.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/BrickTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/DeviceTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/EntityGroupContentProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterDataModelManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterServerTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ICommandIds.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IEntityListener.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IImageKeys.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/NetworkInterfaceTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Perspective.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerDiskTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TableLabelProviderAdapter.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TasksTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeLogTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsContentProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AbstractActionDelegate.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddBrickAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddServerAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ChangePasswordAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ClearTaskAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CommitTaskAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CreateVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DeleteVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DownloadVolumeLogsAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/EditVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ExportSshKeysAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/IActionConstants.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ImportSshKeysAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateBrickAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PauseTaskAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PreferencesAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RebalanceVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RefreshDataAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveBrickAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveServerAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResetVolumeOptionsAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResumeTaskAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ServerAdditionAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StartVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopTaskAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopVolumeAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/TestPopupMenuAction.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickWizard.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/BricksSelectionPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ChangePasswordDialog.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ClusterSelectionDialog.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumePage1.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumeWizard.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/InitializeDiskTypeSelection.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/LoginDialog.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickPage1.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickWizard.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/SelectDisksDialog.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ServerAdditionDialog.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/jobs/DataSyncJob.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/AlertsPreferencePage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/ChartsPreferencePage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/GlusterPreferencePage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceConstants.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceInitializer.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/GlusterToolbarManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/ToolbarManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartUtil.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartViewerComposite.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/EntityViewerFilter.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GUIHelper.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterChartPalette.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterLogger.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ImageUtil.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/validators/StringRequiredValidator.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterAdapterFactory.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterSummaryView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServerView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServersView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DisksView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerDisksView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerLogsView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerSummaryView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersSummaryView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterViewsManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationTreeLabelDecorator.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/TasksView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ViewsManager.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeBricksView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeLogsView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeOptionsView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeSummaryView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesSummaryView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesView.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractDisksPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableTreeViewerPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableViewerPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/BricksPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DiskTreeContentProvider.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DisksPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/GlusterServersPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionKeyEditingSupport.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionValueEditingSupport.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerDisksPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerLogsPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServersPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/TasksPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeLogsPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeOptionsPage.java create mode 100644 src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumesPage.java create mode 100644 src/com.gluster.storage.management.console/src/test.xml (limited to 'src/com.gluster.storage.management.console') diff --git a/src/com.gluster.storage.management.console/.classpath b/src/com.gluster.storage.management.console/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/src/com.gluster.storage.management.console/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/com.gluster.storage.management.console/.project b/src/com.gluster.storage.management.console/.project new file mode 100644 index 00000000..8a79d266 --- /dev/null +++ b/src/com.gluster.storage.management.console/.project @@ -0,0 +1,28 @@ + + + com.gluster.storage.management.console + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/src/com.gluster.storage.management.console/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.console/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..abf7cf5a --- /dev/null +++ b/src/com.gluster.storage.management.console/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Thu Nov 11 15:40:30 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.console/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.console/META-INF/MANIFEST.MF new file mode 100644 index 00000000..fcb162c1 --- /dev/null +++ b/src/com.gluster.storage.management.console/META-INF/MANIFEST.MF @@ -0,0 +1,29 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: glustersp-gui +Bundle-SymbolicName: com.gluster.storage.management.console;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: com.gluster.storage.management.console.Activator +Bundle-Vendor: Gluster +Require-Bundle: org.eclipse.ui;bundle-version="3.6.1", + org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.ui.forms;bundle-version="3.5.2", + org.eclipse.rcp;bundle-version="3.6.0", + com.gluster.storage.management.core;bundle-version="1.0.0", + com.gluster.storage.management.client;bundle-version="1.0.0", + org.eclipse.core.databinding;bundle-version="1.3.100", + org.eclipse.jface.databinding;bundle-version="1.4.0", + org.eclipse.core.databinding.property;bundle-version="1.3.0", + org.eclipse.core.databinding.beans;bundle-version="1.2.100", + org.eclipse.birt.chart.engine;bundle-version="2.6.1", + org.eclipse.birt.chart.engine.extension;bundle-version="2.6.1", + org.eclipse.birt.chart.device.extension;bundle-version="2.6.1", + org.eclipse.birt.chart.device.swt;bundle-version="2.6.1", + com.ibm.icu;bundle-version="4.2.1", + com.richclientgui.rcptoolbox;bundle-version="1.0.5", + org.eclipse.core.resources, + org.apache.commons.lang;bundle-version="2.3.0", + com.gluster.storage.management.console.help;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: . diff --git a/src/com.gluster.storage.management.console/build.properties b/src/com.gluster.storage.management.console/build.properties new file mode 100644 index 00000000..47ced62b --- /dev/null +++ b/src/com.gluster.storage.management.console/build.properties @@ -0,0 +1,15 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + icons/,\ + product_lg.gif,\ + splash.bmp,\ + splash/,\ + images/,\ + plugin.xml,\ + preferences.ini +src.includes = icons/,\ + splash.bmp,\ + images/,\ + preferences.ini diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-down.png b/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-down.png new file mode 100644 index 00000000..7f23e3f4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-down.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-up.png b/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-up.png new file mode 100644 index 00000000..b8ad3050 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/arrow-up.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/bricks.png b/src/com.gluster.storage.management.console/icons/tango/16x16/bricks.png new file mode 100644 index 00000000..ed381bd5 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/bricks.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/close_task.png b/src/com.gluster.storage.management.console/icons/tango/16x16/close_task.png new file mode 100644 index 00000000..933272b4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/close_task.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/cluster.png b/src/com.gluster.storage.management.console/icons/tango/16x16/cluster.png new file mode 100644 index 00000000..c9348a21 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/cluster.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk-available.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-available.png new file mode 100644 index 00000000..c3c5f3b1 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-available.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk-error.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-error.png new file mode 100644 index 00000000..314fa2f3 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-error.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk-initialisation.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-initialisation.png new file mode 100644 index 00000000..71d0107c Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-initialisation.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk-inuse.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-inuse.png new file mode 100644 index 00000000..e4954c6a Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-inuse.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk-uninitialized.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-uninitialized.png new file mode 100644 index 00000000..ba3b48a4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk-uninitialized.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/disk.png b/src/com.gluster.storage.management.console/icons/tango/16x16/disk.png new file mode 100644 index 00000000..b74fb20e Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/disk.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/gluster_icon.png b/src/com.gluster.storage.management.console/icons/tango/16x16/gluster_icon.png new file mode 100644 index 00000000..f92e472d Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/gluster_icon.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/help.png b/src/com.gluster.storage.management.console/icons/tango/16x16/help.png new file mode 100644 index 00000000..f25fc3fb Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/help.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/logs.png b/src/com.gluster.storage.management.console/icons/tango/16x16/logs.png new file mode 100644 index 00000000..124f322f Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/logs.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/offline-brick.png b/src/com.gluster.storage.management.console/icons/tango/16x16/offline-brick.png new file mode 100644 index 00000000..48812db8 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/offline-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/online-brick.png b/src/com.gluster.storage.management.console/icons/tango/16x16/online-brick.png new file mode 100644 index 00000000..da895838 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/online-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/pause.png b/src/com.gluster.storage.management.console/icons/tango/16x16/pause.png new file mode 100644 index 00000000..04923149 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/pause.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/question.png b/src/com.gluster.storage.management.console/icons/tango/16x16/question.png new file mode 100644 index 00000000..30a47032 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/question.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/running-task.png b/src/com.gluster.storage.management.console/icons/tango/16x16/running-task.png new file mode 100644 index 00000000..ad679b8b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/running-task.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/server.png b/src/com.gluster.storage.management.console/icons/tango/16x16/server.png new file mode 100644 index 00000000..d0b397be Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/servers.png b/src/com.gluster.storage.management.console/icons/tango/16x16/servers.png new file mode 100644 index 00000000..0efee57e Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/servers.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/settings.png b/src/com.gluster.storage.management.console/icons/tango/16x16/settings.png new file mode 100644 index 00000000..d90ab661 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/settings.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/start.png b/src/com.gluster.storage.management.console/icons/tango/16x16/start.png new file mode 100644 index 00000000..d4413259 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/start.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/status-offline.png b/src/com.gluster.storage.management.console/icons/tango/16x16/status-offline.png new file mode 100644 index 00000000..dbd0204e Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/status-offline.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/status-online.png b/src/com.gluster.storage.management.console/icons/tango/16x16/status-online.png new file mode 100644 index 00000000..a31ba599 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/status-online.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/stop.png b/src/com.gluster.storage.management.console/icons/tango/16x16/stop.png new file mode 100644 index 00000000..8f591c63 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/stop.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/task-completed.png b/src/com.gluster.storage.management.console/icons/tango/16x16/task-completed.png new file mode 100644 index 00000000..5de2361a Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/task-completed.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/task-error.png b/src/com.gluster.storage.management.console/icons/tango/16x16/task-error.png new file mode 100644 index 00000000..1fc66ad2 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/task-error.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/view-refresh.png b/src/com.gluster.storage.management.console/icons/tango/16x16/view-refresh.png new file mode 100644 index 00000000..3fd71d6e Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/view-refresh.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/volume-create.png b/src/com.gluster.storage.management.console/icons/tango/16x16/volume-create.png new file mode 100644 index 00000000..628f4d50 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/volume-create.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/volume-options.png b/src/com.gluster.storage.management.console/icons/tango/16x16/volume-options.png new file mode 100644 index 00000000..d7665cb7 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/volume-options.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/volume.png b/src/com.gluster.storage.management.console/icons/tango/16x16/volume.png new file mode 100644 index 00000000..41376404 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/16x16/volumes.png b/src/com.gluster.storage.management.console/icons/tango/16x16/volumes.png new file mode 100644 index 00000000..18c2ad8b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/16x16/volumes.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/disk-initialisation.png b/src/com.gluster.storage.management.console/icons/tango/22x22/disk-initialisation.png new file mode 100644 index 00000000..73ecf4c0 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/disk-initialisation.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/high-memory-usage.png b/src/com.gluster.storage.management.console/icons/tango/22x22/high-memory-usage.png new file mode 100644 index 00000000..b7c166ab Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/high-memory-usage.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/low-diskspace.png b/src/com.gluster.storage.management.console/icons/tango/22x22/low-diskspace.png new file mode 100644 index 00000000..983012ad Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/low-diskspace.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/offline-brick.png b/src/com.gluster.storage.management.console/icons/tango/22x22/offline-brick.png new file mode 100644 index 00000000..57694d4b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/offline-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/offline-server.png b/src/com.gluster.storage.management.console/icons/tango/22x22/offline-server.png new file mode 100644 index 00000000..5900c724 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/offline-server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/replace-brick.png b/src/com.gluster.storage.management.console/icons/tango/22x22/replace-brick.png new file mode 100644 index 00000000..48a66c8c Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/replace-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/server-warning.png b/src/com.gluster.storage.management.console/icons/tango/22x22/server-warning.png new file mode 100644 index 00000000..9e2da0bc Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/server-warning.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/system-search.png b/src/com.gluster.storage.management.console/icons/tango/22x22/system-search.png new file mode 100644 index 00000000..4e522b23 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/system-search.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/22x22/volume-rebalance.png b/src/com.gluster.storage.management.console/icons/tango/22x22/volume-rebalance.png new file mode 100644 index 00000000..4539822c Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/22x22/volume-rebalance.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/add-brick.png b/src/com.gluster.storage.management.console/icons/tango/32x32/add-brick.png new file mode 100644 index 00000000..81304ab4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/add-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/add-server.png b/src/com.gluster.storage.management.console/icons/tango/32x32/add-server.png new file mode 100644 index 00000000..29a512f2 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/add-server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/clear-task.png b/src/com.gluster.storage.management.console/icons/tango/32x32/clear-task.png new file mode 100644 index 00000000..db17be6b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/clear-task.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/commit-task.png b/src/com.gluster.storage.management.console/icons/tango/32x32/commit-task.png new file mode 100644 index 00000000..ff0c9452 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/commit-task.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume-disabled.png b/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume-disabled.png new file mode 100644 index 00000000..d7b69f97 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume.png b/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume.png new file mode 100644 index 00000000..b43289b6 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/create-volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/disk.png b/src/com.gluster.storage.management.console/icons/tango/32x32/disk.png new file mode 100644 index 00000000..b34d8b77 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/disk.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/download-log.png b/src/com.gluster.storage.management.console/icons/tango/32x32/download-log.png new file mode 100644 index 00000000..62bf9d7e Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/download-log.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/help.png b/src/com.gluster.storage.management.console/icons/tango/32x32/help.png new file mode 100644 index 00000000..d60425f7 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/help.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/logs.png b/src/com.gluster.storage.management.console/icons/tango/32x32/logs.png new file mode 100644 index 00000000..b62959e4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/logs.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/pause.png b/src/com.gluster.storage.management.console/icons/tango/32x32/pause.png new file mode 100644 index 00000000..597bc014 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/pause.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick-disabled.png b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick-disabled.png new file mode 100644 index 00000000..8dbbf3c1 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick.png b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick.png new file mode 100644 index 00000000..83a657a2 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/remove-server.png b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-server.png new file mode 100644 index 00000000..fba00869 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/remove-volume.png b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-volume.png new file mode 100644 index 00000000..b7392805 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/remove-volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/replace-brick.png b/src/com.gluster.storage.management.console/icons/tango/32x32/replace-brick.png new file mode 100644 index 00000000..999332a5 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/replace-brick.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/reset-volume-option.png b/src/com.gluster.storage.management.console/icons/tango/32x32/reset-volume-option.png new file mode 100644 index 00000000..77203284 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/reset-volume-option.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/server.png b/src/com.gluster.storage.management.console/icons/tango/32x32/server.png new file mode 100644 index 00000000..e34eb4e4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/servers.png b/src/com.gluster.storage.management.console/icons/tango/32x32/servers.png new file mode 100644 index 00000000..dca03af4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/servers.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/settings.png b/src/com.gluster.storage.management.console/icons/tango/32x32/settings.png new file mode 100644 index 00000000..565f406d Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/settings.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume-disabled.png b/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume-disabled.png new file mode 100644 index 00000000..ad14408b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume.png b/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume.png new file mode 100644 index 00000000..d357d291 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/start-volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/start.png b/src/com.gluster.storage.management.console/icons/tango/32x32/start.png new file mode 100644 index 00000000..578736ec Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/start.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume-disabled.png b/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume-disabled.png new file mode 100644 index 00000000..b70b2042 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume.png b/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume.png new file mode 100644 index 00000000..5cc5e1fb Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/stop-volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/stop.png b/src/com.gluster.storage.management.console/icons/tango/32x32/stop.png new file mode 100644 index 00000000..615e465b Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/stop.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/view-refresh.png b/src/com.gluster.storage.management.console/icons/tango/32x32/view-refresh.png new file mode 100644 index 00000000..606ea9eb Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/view-refresh.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/volume-rebalance.png b/src/com.gluster.storage.management.console/icons/tango/32x32/volume-rebalance.png new file mode 100644 index 00000000..eb63ec20 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/volume-rebalance.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/32x32/volume.png b/src/com.gluster.storage.management.console/icons/tango/32x32/volume.png new file mode 100644 index 00000000..3e0d9add Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/32x32/volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/add-server.png b/src/com.gluster.storage.management.console/icons/tango/48x48/add-server.png new file mode 100644 index 00000000..3e615b62 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/add-server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/create-volume.png b/src/com.gluster.storage.management.console/icons/tango/48x48/create-volume.png new file mode 100644 index 00000000..88a494cc Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/create-volume.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/remove-brick-disabled.png b/src/com.gluster.storage.management.console/icons/tango/48x48/remove-brick-disabled.png new file mode 100644 index 00000000..368b6696 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/remove-brick-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/server.png b/src/com.gluster.storage.management.console/icons/tango/48x48/server.png new file mode 100644 index 00000000..a568c0b8 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/server.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/start-volume-disabled.png b/src/com.gluster.storage.management.console/icons/tango/48x48/start-volume-disabled.png new file mode 100644 index 00000000..fcf25df4 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/start-volume-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/48x48/stop-volume-disabled.png b/src/com.gluster.storage.management.console/icons/tango/48x48/stop-volume-disabled.png new file mode 100644 index 00000000..f418875a Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/48x48/stop-volume-disabled.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/8x8/offline.png b/src/com.gluster.storage.management.console/icons/tango/8x8/offline.png new file mode 100644 index 00000000..6b33d298 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/8x8/offline.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/8x8/online.png b/src/com.gluster.storage.management.console/icons/tango/8x8/online.png new file mode 100644 index 00000000..58a61f1a Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/8x8/online.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/8x8/star.png b/src/com.gluster.storage.management.console/icons/tango/8x8/star.png new file mode 100644 index 00000000..5f8fc748 Binary files /dev/null and b/src/com.gluster.storage.management.console/icons/tango/8x8/star.png differ diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/add_brick.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/add_brick.svg new file mode 100644 index 00000000..b1fb427c --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/add_brick.svg @@ -0,0 +1,4155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/add_volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/add_volume.svg new file mode 100644 index 00000000..66307f36 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/add_volume.svg @@ -0,0 +1,3235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/brick.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/brick.svg new file mode 100644 index 00000000..365110f2 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/brick.svg @@ -0,0 +1,652 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + go + lower + down + arrow + pointer + > + + + + + Andreas Nilsson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/brick_migration.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/brick_migration.svg new file mode 100644 index 00000000..280b4c4f --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/brick_migration.svg @@ -0,0 +1,3620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/bricks.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/bricks.svg new file mode 100644 index 00000000..39af40f2 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/bricks.svg @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + go + lower + down + arrow + pointer + > + + + + + Andreas Nilsson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/cloud.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/cloud.svg new file mode 100644 index 00000000..d51128ac --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/cloud.svg @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume-disabled.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume-disabled.svg new file mode 100644 index 00000000..2cc8da4e --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume-disabled.svg @@ -0,0 +1,3044 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume.svg new file mode 100644 index 00000000..14a5823f --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/create-volume.svg @@ -0,0 +1,3006 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk (32-32).svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk (32-32).svg new file mode 100644 index 00000000..bfe35cce --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk (32-32).svg @@ -0,0 +1,1088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk (48-48).svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk (48-48).svg new file mode 100644 index 00000000..79f172df --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk (48-48).svg @@ -0,0 +1,2263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk.svg new file mode 100644 index 00000000..730e9b27 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk.svg @@ -0,0 +1,850 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk_available.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_available.svg new file mode 100644 index 00000000..667535c1 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_available.svg @@ -0,0 +1,1983 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk_error.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_error.svg new file mode 100644 index 00000000..1dda3bbf --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_error.svg @@ -0,0 +1,1991 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk_initialisation.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_initialisation.svg new file mode 100644 index 00000000..5bffaa8f --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_initialisation.svg @@ -0,0 +1,2302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk_inuse.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_inuse.svg new file mode 100644 index 00000000..5d5388b2 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_inuse.svg @@ -0,0 +1,1848 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/disk_uninitialised.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_uninitialised.svg new file mode 100644 index 00000000..f3cdd2ee --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/disk_uninitialised.svg @@ -0,0 +1,2585 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/download_log.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/download_log.svg new file mode 100644 index 00000000..2ac27d12 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/download_log.svg @@ -0,0 +1,1187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + document + settings + preferences + properties + tweak + + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/high_CPU_usage.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/high_CPU_usage.svg new file mode 100644 index 00000000..1ed67ab8 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/high_CPU_usage.svg @@ -0,0 +1,1661 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/high_memory_usage.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/high_memory_usage.svg new file mode 100644 index 00000000..0ee3b389 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/high_memory_usage.svg @@ -0,0 +1,589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/log.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/log.svg new file mode 100644 index 00000000..42559766 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/log.svg @@ -0,0 +1,1160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + document + settings + preferences + properties + tweak + + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/low_diskspace.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/low_diskspace.svg new file mode 100644 index 00000000..dc5faa1b --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/low_diskspace.svg @@ -0,0 +1,1790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + cdrom + media + removable + cd + audio + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/offline-8x8.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/offline-8x8.svg new file mode 100644 index 00000000..fb587339 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/offline-8x8.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/offline.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/offline.svg new file mode 100644 index 00000000..9ee10367 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/offline.svg @@ -0,0 +1,1637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + document + settings + preferences + properties + tweak + + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/offline_brick_alert.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_brick_alert.svg new file mode 100644 index 00000000..5bc030db --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_brick_alert.svg @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + go + lower + down + arrow + pointer + > + + + + + Andreas Nilsson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/offline_server.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_server.svg new file mode 100644 index 00000000..f1f50c40 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_server.svg @@ -0,0 +1,838 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/offline_volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_volume.svg new file mode 100644 index 00000000..8146a910 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/offline_volume.svg @@ -0,0 +1,3171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/online-8x8.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/online-8x8.svg new file mode 100644 index 00000000..8cef7653 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/online-8x8.svg @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/online.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/online.svg new file mode 100644 index 00000000..c25a4232 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/online.svg @@ -0,0 +1,1410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + document + settings + preferences + properties + tweak + + + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/remove-server.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/remove-server.svg new file mode 100644 index 00000000..4280df60 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/remove-server.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-03-08 + + + Jakub Steiner + + + + + workstation + computer + node + client + + + + http://jimmac.musichall.cz/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/remove_brick.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/remove_brick.svg new file mode 100644 index 00000000..450b24c8 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/remove_brick.svg @@ -0,0 +1,4483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/remove_volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/remove_volume.svg new file mode 100644 index 00000000..83055628 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/remove_volume.svg @@ -0,0 +1,3248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/reset_volume_option.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/reset_volume_option.svg new file mode 100644 index 00000000..cd048c2b --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/reset_volume_option.svg @@ -0,0 +1,2946 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/running_task.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/running_task.svg new file mode 100644 index 00000000..d9cf0582 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/running_task.svg @@ -0,0 +1,1498 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/star-8x8.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/star-8x8.svg new file mode 100644 index 00000000..f3027569 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/star-8x8.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/start-volume-disabled.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/start-volume-disabled.svg new file mode 100644 index 00000000..3ef559c7 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/start-volume-disabled.svg @@ -0,0 +1,3350 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/start_volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/start_volume.svg new file mode 100644 index 00000000..5e738c33 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/start_volume.svg @@ -0,0 +1,3312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/stop_volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/stop_volume.svg new file mode 100644 index 00000000..315bb09b --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/stop_volume.svg @@ -0,0 +1,3268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_clear.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_clear.svg new file mode 100644 index 00000000..02b0b919 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_clear.svg @@ -0,0 +1,845 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Lapo Calamandrei + + + + + + media + pause + playback + video + music + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_commit.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_commit.svg new file mode 100644 index 00000000..29817471 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_commit.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + go + higher + up + arrow + pointer + > + + + + + Andreas Nilsson + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_pause.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_pause.svg new file mode 100644 index 00000000..ff9b5f3e --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_pause.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Lapo Calamandrei + + + + + + media + pause + playback + video + music + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_paused.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_paused.svg new file mode 100644 index 00000000..9d6930e1 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_paused.svg @@ -0,0 +1,812 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_resume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_resume.svg new file mode 100644 index 00000000..2bd8732c --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_resume.svg @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Lapo Calamandrei + + + + + + play + media + music + video + player + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_running.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_running.svg new file mode 100644 index 00000000..fa15b7b8 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_running.svg @@ -0,0 +1,796 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_completed.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_completed.svg new file mode 100644 index 00000000..ce0bf238 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_completed.svg @@ -0,0 +1,577 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_error.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_error.svg new file mode 100644 index 00000000..5fb8b116 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_status_error.svg @@ -0,0 +1,654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_stop.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_stop.svg new file mode 100644 index 00000000..07227fd4 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_stop.svg @@ -0,0 +1,748 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Lapo Calamandrei + + + + + + media + stop + playback + video + music + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/task_stopped.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/task_stopped.svg new file mode 100644 index 00000000..d900f03f --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/task_stopped.svg @@ -0,0 +1,784 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-10 + + + Andreas Nilsson + + + + + edit + paste + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/view-refresh.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/view-refresh.svg new file mode 100644 index 00000000..565f6dad --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/view-refresh.svg @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + View Refresh + + + reload + refresh + view + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/volume.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/volume.svg new file mode 100644 index 00000000..b5e50a46 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/volume.svg @@ -0,0 +1,2917 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/volume_option.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/volume_option.svg new file mode 100644 index 00000000..3fb4a928 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/volume_option.svg @@ -0,0 +1,2875 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/volume_rebalance.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/volume_rebalance.svg new file mode 100644 index 00000000..78fdc384 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/volume_rebalance.svg @@ -0,0 +1,3713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/icons/tango/scalable/volumes.svg b/src/com.gluster.storage.management.console/icons/tango/scalable/volumes.svg new file mode 100644 index 00000000..3c99b006 --- /dev/null +++ b/src/com.gluster.storage.management.console/icons/tango/scalable/volumes.svg @@ -0,0 +1,2949 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/images/gauge.png b/src/com.gluster.storage.management.console/images/gauge.png new file mode 100644 index 00000000..6f5764ea Binary files /dev/null and b/src/com.gluster.storage.management.console/images/gauge.png differ diff --git a/src/com.gluster.storage.management.console/images/gauge_small.png b/src/com.gluster.storage.management.console/images/gauge_small.png new file mode 100644 index 00000000..71e424fe Binary files /dev/null and b/src/com.gluster.storage.management.console/images/gauge_small.png differ diff --git a/src/com.gluster.storage.management.console/plugin.xml b/src/com.gluster.storage.management.console/plugin.xml new file mode 100644 index 00000000..362bb221 --- /dev/null +++ b/src/com.gluster.storage.management.console/plugin.xml @@ -0,0 +1,1566 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.console/preferences.ini b/src/com.gluster.storage.management.console/preferences.ini new file mode 100644 index 00000000..04afab80 --- /dev/null +++ b/src/com.gluster.storage.management.console/preferences.ini @@ -0,0 +1,2 @@ +org.eclipse.ui/KEY_CONFIGURATION_ID = com.gluster.storage.management.console.KeyConfig +org.eclipse.help.base/help_home=/com.gluster.storage.management.console.help/html/help_home.html \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/splash.bmp b/src/com.gluster.storage.management.console/splash.bmp new file mode 100644 index 00000000..c70f24c6 Binary files /dev/null and b/src/com.gluster.storage.management.console/splash.bmp differ diff --git a/src/com.gluster.storage.management.console/splash/gluster_about.jpg b/src/com.gluster.storage.management.console/splash/gluster_about.jpg new file mode 100644 index 00000000..242fa560 Binary files /dev/null and b/src/com.gluster.storage.management.console/splash/gluster_about.jpg differ diff --git a/src/com.gluster.storage.management.console/splash/splash-dialog.bmp b/src/com.gluster.storage.management.console/splash/splash-dialog.bmp new file mode 100644 index 00000000..2de2897f Binary files /dev/null and b/src/com.gluster.storage.management.console/splash/splash-dialog.bmp differ diff --git a/src/com.gluster.storage.management.console/splash/splash-dialog.png b/src/com.gluster.storage.management.console/splash/splash-dialog.png new file mode 100644 index 00000000..789eafb0 Binary files /dev/null and b/src/com.gluster.storage.management.console/splash/splash-dialog.png differ diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Activator.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Activator.java new file mode 100644 index 00000000..8edae7f4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Activator.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "com.gluster.storage.management.console"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + public void editorOpened() { + System.err.println("Editor opened!"); + } + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/AlertsManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/AlertsManager.java new file mode 100644 index 00000000..26419446 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/AlertsManager.java @@ -0,0 +1,212 @@ +/** + * AlertsManager.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; + +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Alert.ALERT_TYPES; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Partition; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +public class AlertsManager { + private List alerts = new ArrayList(); + private Cluster cluster; + + private Double CPU_USAGE_THRESHOLD; + private Double MEMORY_USAGE_THRESHOLD; + private Double DISK_SPACE_USAGE_THRESHOLD; + + public AlertsManager(Cluster cluster) { + this.cluster = cluster; + + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + CPU_USAGE_THRESHOLD = preferenceStore.getDouble(PreferenceConstants.P_SERVER_CPU_CRITICAL_THRESHOLD); + MEMORY_USAGE_THRESHOLD = preferenceStore.getDouble(PreferenceConstants.P_SERVER_MEMORY_USAGE_THRESHOLD); + DISK_SPACE_USAGE_THRESHOLD = preferenceStore.getDouble(PreferenceConstants.P_DISK_SPACE_USAGE_THRESHOLD); + } + + public List getAlerts() { + return alerts; + } + + public Alert getAlert(String id) { + for (Alert alert : getAlerts()) { + if (alert.getId().equals(id)) { + return alert; + } + } + return null; + } + + public void addAlert(Alert alert) { + alerts.add(alert); + } + + public void addAlerts(List alerts) { + this.alerts.addAll(alerts); + } + + public void setAlerts(List alerts) { + this.alerts = alerts; + } + + public Boolean removeAlert(String id) { + for (int i = 0; i < alerts.size(); i++) { + if (alerts.get(i).getId().equals(id)) { + return (alerts.remove(i) != null); + } + } + return false; + } + + public void clearAll() { + this.alerts.clear(); + } + + public void buildAlerts() { + clearAll(); + addAlerts(getServerAlerts()); + addAlerts(getVolumeAlerts()); + } + + private List getServerAlerts() { + List serverAlerts = new ArrayList(); + Alert offlineServerAlert = getOfflineServerAlerts(); + if (offlineServerAlert != null) { + serverAlerts.add(offlineServerAlert); // Single alert for offline servers + } + + for (GlusterServer server : cluster.getServers()) { + // To check off line servers + // if (server.getStatus() == SERVER_STATUS.OFFLINE) { + // serverAlerts.add(new Alert(ALERT_TYPES.OFFLINE_SERVERS_ALERT, server.getName(), "Server [" + // + server.getName() + "] is Offline")); + // continue; // If the server is Offline skip other Alert builds + // } + + // To check High CPU usage + if (server.getCpuUsage() >= CPU_USAGE_THRESHOLD) { + serverAlerts.add(new Alert(ALERT_TYPES.CPU_USAGE_ALERT, server.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.CPU_USAGE_ALERT.ordinal()] + " [" + server.getCpuUsage() + + "] in server [" + server.getName() + "]")); + } + + // To check High Memory usage + Double memoryUtilized = server.getMemoryInUse() / server.getTotalMemory() * 100d; + if (memoryUtilized >= MEMORY_USAGE_THRESHOLD) { + serverAlerts.add(new Alert(ALERT_TYPES.MEMORY_USAGE_ALERT, server.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.MEMORY_USAGE_ALERT.ordinal()] + " [" + + StringUtil.formatNumber(memoryUtilized, 2) + "%] in server [" + server.getName() + + "]")); + } + + // To Check low disk space + serverAlerts.addAll(getLowDiskAlerts(server)); + } + return serverAlerts; + } + + private Alert getOfflineServerAlerts() { + List offlineServers = new ArrayList(); + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == SERVER_STATUS.OFFLINE) { + offlineServers.add(server.getName()); + } + } + if (offlineServers.size() > 0) { + return new Alert(ALERT_TYPES.OFFLINE_SERVERS_ALERT, "Server", + Alert.ALERT_TYPE_STR[ALERT_TYPES.OFFLINE_SERVERS_ALERT.ordinal()] + "(s) " + + offlineServers.toString()); + } + return null; + } + + private List getLowDiskAlerts(GlusterServer server) { + List diskAlerts = new ArrayList(); + boolean hasPartition; + Double deviceSpaceUsed; + for (Disk disk : server.getDisks()) { + hasPartition = false; + for (Partition partition : disk.getPartitions()) { + hasPartition = true; + deviceSpaceUsed = partition.getSpaceInUse() / partition.getSpace() * 100d; + if (deviceSpaceUsed >= DISK_SPACE_USAGE_THRESHOLD) { + diskAlerts.add(new Alert(ALERT_TYPES.DISK_USAGE_ALERT, partition.getQualifiedName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.DISK_USAGE_ALERT.ordinal()] + " [" + + StringUtil.formatNumber(deviceSpaceUsed, 2) + "% used] in disk [" + + partition.getQualifiedName() + "]")); + } + } + if (hasPartition) { + continue; // Do not check disk usage + } + + // If it is disk + deviceSpaceUsed = disk.getSpaceInUse() / disk.getSpace() * 100d; + if (deviceSpaceUsed >= DISK_SPACE_USAGE_THRESHOLD) { + diskAlerts.add(new Alert(ALERT_TYPES.DISK_USAGE_ALERT, disk.getQualifiedName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.DISK_USAGE_ALERT.ordinal()] + " [" + + StringUtil.formatNumber(deviceSpaceUsed, 2) + "% used] in [" + + disk.getQualifiedName() + "]")); + } + } + return diskAlerts; + } + + private List getVolumeAlerts() { + List volumeAlerts = new ArrayList(); + List offlineBricks = new ArrayList(); + + for (Volume volume : cluster.getVolumes()) { + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + continue; + } + + // To check off line bricks + offlineBricks = new ArrayList(); + for (Brick brick : volume.getBricks()) { + if (brick.getStatus() == BRICK_STATUS.OFFLINE) { + offlineBricks.add(brick.getQualifiedName()); + } + } + // One offline brick alert per volume + if (offlineBricks.size() > 0) { + volumeAlerts.add(new Alert(ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT, volume.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT.ordinal()] + " " + + offlineBricks.toString() + " in volume " + volume.getName())); + } + } + return volumeAlerts; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Application.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Application.java new file mode 100644 index 00000000..e84dac47 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Application.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +import com.gluster.storage.management.console.dialogs.LoginDialog; +import com.gluster.storage.management.core.model.Entity; + +/** + * This class controls all aspects of the application's execution + */ +public class Application implements IApplication { + + public static final String PLUGIN_ID = "com.gluster.storage.management.console"; + private static Application instance; + private List entityListeners = Collections.synchronizedList(new ArrayList()); + private IStatusLineManager statusLineManager; + + public Application() { + instance = this; + } + + public static Application getApplication() { + return instance; + } + + public IStatusLineManager getStatusLineManager() { + return statusLineManager; + } + + public void setStatusLineManager(IStatusLineManager statusLineManager) { + this.statusLineManager = statusLineManager; + } + + private boolean login() { + LoginDialog loginDialog = new LoginDialog(new Shell(Display.getDefault())); + return (loginDialog.open() == Window.OK); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext) + */ + public Object start(IApplicationContext context) { + setSystemProperties(); + + Display display = PlatformUI.createDisplay(); + + final boolean[] loginSuccess = new boolean[1]; + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + loginSuccess[0] = login(); + } + }); + + if (!loginSuccess[0]) { + return IApplication.EXIT_OK; + } + try { + int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()); + if (returnCode == PlatformUI.RETURN_RESTART) { + return IApplication.EXIT_RESTART; + } + + return IApplication.EXIT_OK; + } finally { + display.dispose(); + } + } + + private void setSystemProperties() { + // TODO: Trying this to avoid the webstart authentication dialog + // to be tested, and removed if this doesn't work. + System.setProperty("javaws.cfg.jauthenticator", "none"); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.equinox.app.IApplication#stop() + */ + public void stop() { + if (!PlatformUI.isWorkbenchRunning()) + return; + final IWorkbench workbench = PlatformUI.getWorkbench(); + final Display display = workbench.getDisplay(); + display.syncExec(new Runnable() { + public void run() { + if (!display.isDisposed()) + workbench.close(); + } + }); + } + + public void addEntityListener(IEntityListener listener) { + entityListeners.add(listener); + } + + public void entityChanged(Entity entity, String[] paremeters) { + for (IEntityListener listener : entityListeners) { + listener.entityChanged(entity, paremeters); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationActionBarAdvisor.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationActionBarAdvisor.java new file mode 100644 index 00000000..e49e1275 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationActionBarAdvisor.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.ICoolBarManager; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.console.utils.GUIHelper; + +/** + * An action bar advisor is responsible for creating, adding, and disposing of the actions added to a workbench window. + * Each window will be populated with new actions. + */ +public class ApplicationActionBarAdvisor extends ActionBarAdvisor { + private IWorkbenchWindow window; + /* + * Actions - important to allocate these only in makeActions, and then use them in the fill methods. This ensures + * that the actions aren't recreated when fillActionBars is called with FILL_PROXY. + */ + private IWorkbenchAction exitAction; + private IWorkbenchAction aboutAction; + private IWorkbenchAction helpContentsAction; + + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { + super(configurer); + } + + protected void makeActions(final IWorkbenchWindow window) { + this.window = window; + /* + * Creates the actions and registers them. Registering is needed to ensure that key bindings work. The + * corresponding commands keybindings are defined in the plugin.xml file. Registering also provides automatic + * disposal of the actions when the window is closed. + */ + exitAction = ActionFactory.QUIT.create(window); + register(exitAction); + + aboutAction = ActionFactory.ABOUT.create(window); + aboutAction.setText("&About"); + aboutAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.HELP_16x16)); + register(aboutAction); + + helpContentsAction = ActionFactory.HELP_CONTENTS.create(window); + helpContentsAction.setText("&Contents"); + //helpContentsAction.setImageDescriptor(newImage) + register(helpContentsAction); + } + + protected void fillMenuBar(IMenuManager menuBar) { + // File + MenuManager fileMenu = new MenuManager("&File", IWorkbenchActionConstants.M_FILE); + fileMenu.add(new Separator()); + fileMenu.add(exitAction); + + // Help + MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP); + helpMenu.add(helpContentsAction); + helpMenu.add(aboutAction); + + menuBar.add(fileMenu); + // Add a group marker indicating where action set menus will appear. + // All action sets from plugin.xml will get added here + menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + menuBar.add(helpMenu); + } + + protected void fillCoolBar(ICoolBarManager coolBar) { + // All our actions are added to toolbar through the extension point org.eclipse.ui.actionSets + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchAdvisor.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchAdvisor.java new file mode 100644 index 00000000..e76503d5 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchAdvisor.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +import com.gluster.storage.management.console.jobs.DataSyncJob; +import com.gluster.storage.management.console.preferences.PreferenceConstants; + +/** + * This workbench advisor creates the window advisor, and specifies + * the perspective id for the initial window. + */ +public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { + private Job syncJob; + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + private long JOB_INTERVAL = preferenceStore.getLong(PreferenceConstants.P_DATA_SYNC_INTERVAL) * 1000; + private IPropertyChangeListener propertyChangeListener; + + public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + return new ApplicationWorkbenchWindowAdvisor(configurer); + } + + public String getInitialWindowPerspectiveId() { + return Perspective.ID; + } + + @Override + public void initialize(IWorkbenchConfigurer configurer) { + super.initialize(configurer); + configurer.setSaveAndRestore(false); // we don't need save/restore as of now + + createPropertyChangeListener(); + preferenceStore.addPropertyChangeListener(propertyChangeListener); + } + + private void createPropertyChangeListener() { + propertyChangeListener = new IPropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getProperty().equals(PreferenceConstants.P_DATA_SYNC_INTERVAL)) { + JOB_INTERVAL = (Integer)event.getNewValue() * 1000l; + } + } + }; + } + + @Override + public void postStartup() { + super.postStartup(); + setupBackgroundJobs(); + } + + private void setupBackgroundJobs() { + syncJob = new DataSyncJob("Cluster Data Sync"); + syncJob.schedule(JOB_INTERVAL); + syncJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + super.done(event); + + // job done. schedule again after the pre-defined interval + syncJob.schedule(JOB_INTERVAL); + } + }); + } + + @Override + public boolean preShutdown() { + return syncJob.cancel(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchWindowAdvisor.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchWindowAdvisor.java new file mode 100644 index 00000000..2411dcb5 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ApplicationWorkbenchWindowAdvisor.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +import com.gluster.storage.management.console.utils.GUIHelper; + +public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { + private final static int DEFAULT_WIDTH = 1024; + private final static int DEFAULT_HEIGHT = 768; + private final GUIHelper guiHelper = GUIHelper.getInstance(); + + public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + super(configurer); + } + + @Override + public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) { + return new ApplicationActionBarAdvisor(configurer); + } + + @Override + public void preWindowOpen() { + super.preWindowOpen(); + + IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); + configurer.setInitialSize(new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT)); + configurer.setShowCoolBar(true); + configurer.setShowStatusLine(true); + configurer.setShowMenuBar(true); + configurer.setShowProgressIndicator(true); // shows progress indicator in status bar + } + + @Override + public void postWindowCreate() { + super.postWindowCreate(); + guiHelper.centerShellInScreen(getWindowConfigurer().getWindow().getShell()); + getWindowConfigurer().getWindow().getShell().setMaximized(true); + Application.getApplication().setStatusLineManager( + getWindowConfigurer().getActionBarConfigurer().getStatusLineManager()); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/BrickTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/BrickTableLabelProvider.java new file mode 100644 index 00000000..4796578e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/BrickTableLabelProvider.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.BricksPage.BRICK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.console.views.pages.DisksPage.DISK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class BrickTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + + if (!(element instanceof Brick)) { + return null; + } + + Brick brick = (Brick) element; + if (columnIndex == DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + BRICK_STATUS status = brick.getStatus(); + + switch(status) { + case ONLINE: + return guiHelper.getImage(IImageKeys.BRICK_ONLINE_16x16); + case OFFLINE: + return guiHelper.getImage(IImageKeys.BRICK_OFFLINE_16x16); + } + } + return null; + } + + private String getDeviceFreeSpace(Device device) { + if (device != null && device.isReady() && device.getFreeSpace() != null) { + return NumberUtil.formatNumber((device.getFreeSpace() / 1024)); + } else { + return "NA"; + } + } + + private String getDeviceCapacity(Device device) { + if (device != null && device.isReady() && device.getSpace() != null && device.getSpace() != 0.0) { + return NumberUtil.formatNumber((device.getSpace() / 1024)); + } else { + return "NA"; + } + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Brick)) { + return null; + } + + Brick brick = (Brick) element; + Device device = GlusterDataModelManager.getInstance().getDeviceForBrickDir(brick); + return (columnIndex == BRICK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? brick.getServerName() + : columnIndex == BRICK_TABLE_COLUMN_INDICES.BRICK.ordinal() ? brick.getBrickDirectory() + : columnIndex == BRICK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? getDeviceFreeSpace(device) + : columnIndex == BRICK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? getDeviceCapacity(device) + : columnIndex == BRICK_TABLE_COLUMN_INDICES.STATUS.ordinal() ? brick.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/DeviceTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/DeviceTableLabelProvider.java new file mode 100644 index 00000000..3d8fa432 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/DeviceTableLabelProvider.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.resource.FontRegistry; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Device.DEVICE_STATUS; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Partition; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class DeviceTableLabelProvider extends LabelProvider implements ITableLabelProvider { + + private GUIHelper guiHelper = GUIHelper.getInstance(); + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + public enum DEVICE_COLUMN_INDICES { + DISK, PARTITION, FREE_SPACE, SPACE_IN_USE, STATUS + }; + + FontRegistry registry = new FontRegistry(); + + public DeviceTableLabelProvider() { + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Device)) { + return null; + } + + Device device = (Device) element; + if (columnIndex == DEVICE_COLUMN_INDICES.STATUS.ordinal()) { + DEVICE_STATUS status = device.getStatus(); + + if (status == null) { + if (element instanceof Partition) { + if (columnIndex == DEVICE_COLUMN_INDICES.STATUS.ordinal()) { + status = device.getStatus(); + } + } + } + + if (status == null) { + return null; + } + + if(element instanceof Disk && ((Disk)element).hasPartitions()) { + // disk has partitions. so don't show status image at disk level. + return null; + } + + switch (status) { + case INITIALIZED: + if(modelManager.isDeviceUsed(device)) { + return guiHelper.getImage(IImageKeys.DISK_IN_USE_16x16); + } else { + return guiHelper.getImage(IImageKeys.DISK_AVAILABLE_16x16); + } + case IO_ERROR: + return guiHelper.getImage(IImageKeys.IO_ERROR_16x16); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED_16x16); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.DISK_INITIALIZING_16x16); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + @Override + public String getText(Object element) { + return super.getText(element); + } + + private String getDeviceFreeSpace(Device device) { + if (device.hasErrors() || device.isUninitialized()) { + return "NA"; + } else { + return NumberUtil.formatNumber((device.getFreeSpace() / 1024)); + } + } + + private String getTotalDeviceSpace(Device device) { + if (device.hasErrors() || device.isUninitialized()) { + return "NA"; + } else { + return NumberUtil.formatNumber((device.getSpace() / 1024)); + } + } + + public String getColumnText(Object element, int columnIndex) { + + if (element == null) { + return ""; + } + + Device device = (Device) element; + if (columnIndex == DEVICE_COLUMN_INDICES.DISK.ordinal()) { + // show value in "disk" column only if it's a disk + if (device instanceof Disk) { + return device.getQualifiedName(); + } else { + return ""; + } + } + + if(element instanceof Disk && ((Disk)element).hasPartitions()) { + // disk has partitions. so don't show any other details + return ""; + } + + if (columnIndex == DEVICE_COLUMN_INDICES.FREE_SPACE.ordinal()) { + return "" + getDeviceFreeSpace(device); + } else if (columnIndex == DEVICE_COLUMN_INDICES.SPACE_IN_USE.ordinal()) { + return "" + getTotalDeviceSpace(device); + } else if (columnIndex == DEVICE_COLUMN_INDICES.PARTITION.ordinal()) { + if (device instanceof Partition) { + return device.getQualifiedName(); + } else { + return ""; + } + } else if (columnIndex == DEVICE_COLUMN_INDICES.STATUS.ordinal()) { + if(device.isUninitialized()) { + return ""; + } + if(modelManager.isDeviceUsed(device)) { + return "In Use"; + } else { + return device.getStatusStr(); + } + } else { + return ""; + } + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/EntityGroupContentProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/EntityGroupContentProvider.java new file mode 100644 index 00000000..9035e4e2 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/EntityGroupContentProvider.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.gluster.storage.management.core.model.EntityGroup; + +public class EntityGroupContentProvider implements + IStructuredContentProvider { + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + @SuppressWarnings("rawtypes") + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof EntityGroup) { + return ((EntityGroup) inputElement).getChildren().toArray(); + } + return null; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterDataModelManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterDataModelManager.java new file mode 100644 index 00000000..f9474ab4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterDataModelManager.java @@ -0,0 +1,923 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.gluster.storage.management.client.DiscoveredServersClient; +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.console.utils.GlusterLogger; +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Alert.ALERT_TYPES; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Device.DEVICE_STATUS; +import com.gluster.storage.management.core.model.Device.DEVICE_TYPE; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Partition; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.model.VolumeOptionInfo; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; + +public class GlusterDataModelManager { + private static GlusterDataModelManager instance = new GlusterDataModelManager(); + private GlusterDataModel model; + private String securityToken; + private List listeners = new ArrayList(); + private List volumeOptionsDefaults; + private String clusterName; + private static Boolean syncInProgress = false; + private static final GlusterLogger logger = GlusterLogger.getInstance();; + + private GlusterDataModelManager() { + } + + public String getSecurityToken() { + return securityToken; + } + + public void setSecurityToken(String securityToken) { + this.securityToken = securityToken; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getClusterName() { + return clusterName; + } + + public GlusterDataModel getModel() { + return model; + } + + public static GlusterDataModelManager getInstance() { + return instance; + } + + public void initializeModel(String clusterName, IProgressMonitor monitor) { + setClusterName(clusterName); + + model = fetchData(clusterName, monitor); + } + + private GlusterDataModel fetchData(String clusterName, IProgressMonitor monitor) { + GlusterDataModel model = fetchModel(monitor); + + initializeAlerts(model.getCluster()); + initializeVolumeOptionsDefaults(); + + return model; + } + + public void refreshVolumeData(Volume oldVolume) { + VolumesClient volumeClient = new VolumesClient(); + Volume newVolume = volumeClient.getVolume(oldVolume.getName()); + if(!oldVolume.equals(newVolume)) { + volumeChanged(oldVolume, newVolume); + } + } + + private boolean isCancelled(IProgressMonitor monitor) { + if(monitor.isCanceled()) { + monitor.setTaskName("Data sync cancelled!"); + monitor.done(); + return true; + } else { + return false; + } + } + + public GlusterDataModel fetchModel(IProgressMonitor monitor) { + synchronized (syncInProgress) { + if(syncInProgress) { + logger.info("Previous data sync is still running. Skipping this one."); + return null; + } + syncInProgress = true; + } + + try { + logger.info("Starting data sync"); + GlusterDataModel model = new GlusterDataModel("Gluster Data Model"); + Cluster cluster = new Cluster(clusterName, model); + model.addCluster(cluster); + + monitor.beginTask("Data Sync", 6); + + monitor.setTaskName("Syncing servers..."); + initializeGlusterServers(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing volumes..."); + initializeVolumes(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing discovered servers..."); + initializeAutoDiscoveredServers(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing tasks..."); + initializeTasks(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing aggregated CPU stats..."); + initializeAggregatedCpuStats(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing aggregated Network stats..."); + initializeAggregatedNetworkStats(cluster); + monitor.worked(1); + + monitor.done(); + return model; + } finally { + syncInProgress = false; + } + } + + public void updateModel(GlusterDataModel model) { + updateVolumes(model); + updateGlusterServers(model); + updateDiscoveredServers(model); + updateTasks(model); + updateAlerts(model); + updateServerStatistics(model); + } + + private void updateServerStatistics(GlusterDataModel newModel) { + model.getCluster().setAggregatedCpuStats(newModel.getCluster().getAggregatedCpuStats()); + model.getCluster().setAggregatedNetworkStats(newModel.getCluster().getAggregatedNetworkStats()); + for(ClusterListener listener : listeners) { + listener.aggregatedStatsChanged(); + } + } + + private void updateAlerts(GlusterDataModel newModel) { + model.getCluster().getAlerts().clear(); + + // generate alerts for "newModel" + initializeAlerts(newModel.getCluster()); + + // set the new alerts on "model" + model.getCluster().setAlerts(newModel.getCluster().getAlerts()); + + // fire event "alertsGenerated" + alertsGenerated(); + } + + private void updateTasks(GlusterDataModel newModel) { + List oldTasks = model.getCluster().getTaskInfoList(); + List newTasks = newModel.getCluster().getTaskInfoList(); + + Set addedTasks = GlusterCoreUtil.getAddedEntities(oldTasks, newTasks, true); + for(TaskInfo task : addedTasks) { + addTask(task); + } + + Set removedTasks = GlusterCoreUtil.getAddedEntities(newTasks, oldTasks, true); + for(TaskInfo task : removedTasks) { + removeTask(task); + } + + Map modifiedTasks = GlusterCoreUtil.getModifiedEntities(oldTasks, newTasks); + for(Entry entry : modifiedTasks.entrySet()) { + TaskInfo modifiedTask = entry.getKey(); + modifiedTask.copyFrom(entry.getValue()); + updateTask(modifiedTask); + } + } + + private void updateDiscoveredServers(GlusterDataModel newModel) { + List oldServers = model.getCluster().getAutoDiscoveredServers(); + List newServers = newModel.getCluster().getAutoDiscoveredServers(); + + Set addedServers = GlusterCoreUtil.getAddedEntities(oldServers, newServers, true); + for (Server addedServer : addedServers) { + addDiscoveredServer(addedServer); + } + + Set removedServers = GlusterCoreUtil.getAddedEntities(newServers, oldServers, true); + for (Server removedServer : removedServers) { + removeDiscoveredServer(removedServer); + } + + Map modifiedServers = GlusterCoreUtil.getModifiedEntities(oldServers, newServers); + for(Entry entry : modifiedServers.entrySet()) { + discoveredServerChanged(entry.getKey(), entry.getValue()); + } + } + + private void updateGlusterServers(GlusterDataModel newModel) { + List oldServers = model.getCluster().getServers(); + List newServers = newModel.getCluster().getServers(); + + Set addedServers = GlusterCoreUtil.getAddedEntities(oldServers, newServers, true); + for (GlusterServer addedServer : addedServers) { + addGlusterServer(addedServer); + } + + Set removedServers = GlusterCoreUtil.getAddedEntities(newServers, oldServers, true); + for (GlusterServer removedServer : removedServers) { + removeGlusterServer(removedServer); + } + + Map modifiedServers = GlusterCoreUtil.getModifiedEntities(oldServers, newServers); + for(Entry entry : modifiedServers.entrySet()) { + glusterServerChanged(entry.getKey(), entry.getValue()); + } + } + + public void glusterServerChanged(GlusterServer oldServer, GlusterServer newServer) { + oldServer.copyFrom(newServer); + for (ClusterListener listener : listeners) { + listener.serverChanged(oldServer, new Event(EVENT_TYPE.GLUSTER_SERVER_CHANGED, newServer)); + } + + updateDisks(oldServer, oldServer.getDisks(), newServer.getDisks()); + } + + private void updateDisks(Server server, List oldDisks, List newDisks) { + Set addedDisks = GlusterCoreUtil.getAddedEntities(oldDisks, newDisks, false); + addDisks(server, addedDisks); + + Set removedDisks = GlusterCoreUtil.getAddedEntities(newDisks, oldDisks, false); + removeDisks(server, removedDisks); + + Map modifiedDisks = GlusterCoreUtil.getModifiedEntities(oldDisks, newDisks); + disksChanged(server, modifiedDisks); + } + + private void disksChanged(Server server, Map modifiedDisks) { + if(modifiedDisks.size() == 0) { + return; + } + + for (Entry entry : modifiedDisks.entrySet()) { + entry.getKey().copyFrom(entry.getValue()); + } + for (ClusterListener listener : listeners) { + if (server instanceof GlusterServer) { + listener.serverChanged((GlusterServer) server, new Event(EVENT_TYPE.DEVICES_CHANGED, modifiedDisks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DEVICES_CHANGED, modifiedDisks)); + } + } + } + + public void updateDeviceStatus(String serverName, String deviceName, DEVICE_STATUS status) { + GlusterServer server = model.getCluster().getServer(serverName); + Device device = getDeviceDetails(server, deviceName); + if (device != null) { + device.setStatus(status); + device.setType(DEVICE_TYPE.DATA); + for (ClusterListener listener : listeners) { + listener.serverChanged((GlusterServer) server, new Event(EVENT_TYPE.DEVICES_CHANGED, device)); + } + } + } + + private Device getDeviceDetails(GlusterServer server, String deviceName) { + for (Disk disk : server.getDisks()) { + if (disk.hasPartitions()) { + for (Partition partition : disk.getPartitions()) { + if (partition.getName().equals(deviceName)) { + return partition; + } + } + } else { + if (disk.getName().equals(deviceName)) { + return (Device) disk; + } + } + } + return null; + } + + public void addDisks(Server server, Set disks) { + if(disks.size() == 0) { + return; + } + + server.addDisks(disks); + for (ClusterListener listener : listeners) { + if(server instanceof GlusterServer) { + listener.serverChanged((GlusterServer)server, new Event(EVENT_TYPE.DEVICES_ADDED, disks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DEVICES_ADDED, disks)); + } + } + } + + public void removeDisks(Server server, Set disks) { + if(disks.size() == 0) { + return; + } + + for(Disk disk : disks) { + server.removeDisk(disk); + } + + for (ClusterListener listener : listeners) { + if(server instanceof GlusterServer) { + listener.serverChanged((GlusterServer)server, new Event(EVENT_TYPE.DEVICES_REMOVED, disks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DEVICES_REMOVED, disks)); + } + } + } + + private void updateVolumes(GlusterDataModel newModel) { + List oldVolumes = model.getCluster().getVolumes(); + List newVolumes = newModel.getCluster().getVolumes(); + + Set addedVolumes = GlusterCoreUtil.getAddedEntities(oldVolumes, newVolumes, false); + for (Volume addedVolume : addedVolumes) { + addVolume(addedVolume); + } + + Set removedVolumes = GlusterCoreUtil.getAddedEntities(newVolumes, oldVolumes, false); + for (Volume removedVolume : removedVolumes) { + deleteVolume(removedVolume); + } + + Map modifiedVolumes = GlusterCoreUtil.getModifiedEntities(oldVolumes, newVolumes); + for(Entry entry : modifiedVolumes.entrySet()) { + volumeChanged(entry.getKey(), entry.getValue()); + } + } + + public void volumeChanged(Volume oldVolume, Volume newVolume) { + oldVolume.copyFrom(newVolume); + for (ClusterListener listener : listeners) { + listener.volumeChanged(oldVolume, new Event(EVENT_TYPE.VOLUME_CHANGED, newVolume)); + } + updateBricks(oldVolume, oldVolume.getBricks(), newVolume.getBricks()); + } + + private void updateBricks(Volume volume, List oldBricks, List newBricks) { + Set addedBricks = GlusterCoreUtil.getAddedEntities(oldBricks, newBricks, false); + addBricks(volume, addedBricks); + + Set removedBricks = GlusterCoreUtil.getAddedEntities(newBricks, oldBricks, false); + removeBricks(volume, removedBricks); + + Map modifiedBricks = GlusterCoreUtil.getModifiedEntities(oldBricks, newBricks); + bricksChanged(volume, modifiedBricks); + } + + public void bricksChanged(Volume volume, Map modifiedBricks) { + if(modifiedBricks.size() == 0) { + return; + } + + for(Entry entry : modifiedBricks.entrySet()) { + entry.getKey().copyFrom(entry.getValue()); + } + + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_CHANGED, modifiedBricks)); + } + } + + private void initializeGlusterServers(Cluster cluster) { + cluster.setServers(new GlusterServersClient(cluster.getName()).getServers()); + } + + private void initializeAutoDiscoveredServers(Cluster cluster) { + cluster.setAutoDiscoveredServers(new DiscoveredServersClient(securityToken).getDiscoveredServerDetails()); + } + + private void initializeVolumes(Cluster cluster) { + VolumesClient volumeClient = new VolumesClient(cluster.getName()); + cluster.setVolumes(volumeClient.getAllVolumes()); + } + + private void initializeVolumeOptionsDefaults() { + this.volumeOptionsDefaults = new VolumesClient(clusterName).getVolumeOptionsDefaults(); + } + + private void initializeTasks(Cluster cluster) { + List taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); + //List taskInfoList = getDummyTasks(); + cluster.setTaskInfoList(taskInfoList); + } + + public void initializeAggregatedCpuStats(Cluster cluster) { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD); + + cluster.setAggregatedCpuStats(new GlusterServersClient().getAggregatedCpuStats(cpuStatsPeriod)); + } + + public void initializeAggregatedNetworkStats(Cluster cluster) { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD); + + cluster.setAggregatedNetworkStats(new GlusterServersClient().getAggregatedNetworkStats(networkStatsPeriod)); + } + + private List getDummyTasks() { + List taskInfoList = new ArrayList(); + + // Task #1 + TaskInfo taskInfo = new TaskInfo(); + taskInfo.setType(TASK_TYPE.BRICK_MIGRATE); + taskInfo.setName("Migrate Brick-music"); + taskInfo.setPauseSupported(true); + taskInfo.setStopSupported(true); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, ""))); + + taskInfo.getStatus().setMessage("Paused"); + taskInfo.setDescription("Migrate Brick on volume [Movies] from /export/adb/music to /export/sdc/music."); + taskInfoList.add(taskInfo); + + // Task #2 + taskInfo = new TaskInfo(); + taskInfo.setType(TASK_TYPE.DISK_FORMAT); + taskInfo.setName("Initialize disk [KVM-GVSA1:sdc]"); + taskInfo.setPauseSupported(false); + taskInfo.setStopSupported(false); + taskInfo.setStatus( new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, ""))); + taskInfo.getStatus().setMessage("Format completed 80% ..."); + taskInfo.setDescription("Formatting disk [KVM-GVSA1:sdc]"); + taskInfoList.add(taskInfo); + + // Task #2 + taskInfo = new TaskInfo(); + taskInfo.setType(TASK_TYPE.VOLUME_REBALANCE); + taskInfo.setName("Rebalance volume [songs]"); + taskInfo.setPauseSupported(false); + taskInfo.setStopSupported(false); + taskInfo.setStatus( new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, ""))); + taskInfo.getStatus().setMessage("Rebalance step1: layout fix in progress"); + taskInfo.setDescription("Rebalance volume [songs]"); + taskInfoList.add(taskInfo); + + return taskInfoList; + } + + private List getDummyAlerts(Cluster cluster) { + List alerts = new ArrayList(); + for (Server server : cluster.getServers()) { + if (alerts.size() == 0) { + alerts.add(new Alert(ALERT_TYPES.CPU_USAGE_ALERT, server.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.CPU_USAGE_ALERT.ordinal()] + " [93.42 %] in " + + server.getName())); + continue; + } + + if (alerts.size() == 1) { + alerts.add(new Alert(ALERT_TYPES.MEMORY_USAGE_ALERT, server.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.MEMORY_USAGE_ALERT.ordinal()] + " [91.83 %] in " + + server.getName())); + continue; + } + + if (alerts.size() == 2) { + alerts.add(new Alert(ALERT_TYPES.OFFLINE_SERVERS_ALERT, server.getName(), + Alert.ALERT_TYPE_STR[ALERT_TYPES.OFFLINE_SERVERS_ALERT.ordinal()] + " " + server.getName())); + continue; + } + + if (alerts.size() == 3) { + alerts.add(new Alert(ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT, "songs", + Alert.ALERT_TYPE_STR[ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT.ordinal()] + + " [KVM-GVSA4:/export/hdb4/songs] in volume [songs]")); + continue; + } + } + return alerts; + } + + public void initializeAlerts(Cluster cluster) { + AlertsManager alertsManager = new AlertsManager(cluster); + alertsManager.buildAlerts(); + cluster.setAlerts( alertsManager.getAlerts() ); + //cluster.setAlerts( getDummyAlerts(cluster) ); + } + + public Volume addVolume(List volumes, String name, Cluster cluster, VOLUME_TYPE volumeType, + TRANSPORT_TYPE transportType, VOLUME_STATUS status) { + Volume volume = new Volume(name, cluster, volumeType, transportType, status); + volumes.add(volume); + + return volume; + } + +// private Device getDevice(String serverName, String deviceName) { +// List allDevices = getReadyDevicesOfAllServers(); +// for (Device device : allDevices) { +// if (device.getServerName().equals(serverName) && device.getName().equals(deviceName)) { +// return device; +// } +// } +// return null; +// } + + /* + * @param diskName (sda) + * + * @return The device object for given device name + */ + public Device getDeviceDetails(String deviceName) { + List allDevices = getReadyDevicesOfAllServers(); + for (Device device : allDevices) { + if (device.getName().equals(deviceName)) { + return device; + } + } + return null; + } + + + public Device getDeviceForBrickDir(Brick brick) { + Device brickDevice = null; + for (Device device : getReadyDevicesOfServer(brick.getServerName(), new ArrayList())) { + if (brick.getBrickDirectory().startsWith( device.getMountPoint() )) { + if (brickDevice == null || device.getMountPoint().length() > brickDevice.getMountPoint().length()) { + brickDevice = device; + } + } + } + return brickDevice; + } + + public List getReadyDevicesOfVolume(Volume volume) { + Device device = null; + List volumeDevices = new ArrayList(); + for (Brick brick : volume.getBricks()) { + // device = getDevice(brick.getServerName(), brick.getDeviceName()); + device = getDeviceForBrickDir(brick); + if (device != null && device.isReady()) { + volumeDevices.add(device); + } + } + return volumeDevices; + } + + public List getReadyDevicesOfAllServers() { + return getReadyDevicesOfAllServersExcluding(new ArrayList()); + } + + public List getReadyDevicesOfAllServersExcluding(List excludeDevices) { + List devices = new ArrayList(); + + for (Server server : model.getCluster().getServers()) { + devices.addAll( getReadyDevicesOfServer(server.getName(), excludeDevices) ); + } + return devices; + } + + public List getReadyDevicesOfServer(String serverName, List excludeDevices) { + List devices = new ArrayList(); + GlusterServer server = model.getCluster().getServer(serverName); + if (!server.isOnline()) { + return devices; + } + for (Disk disk : server.getDisks()) { + if (disk.hasPartitions()) { + for (Partition partition : disk.getPartitions()) { + if (partition.isReady() && !excludeDevices.contains(partition)) { + devices.add(partition); + } + } + } else if (disk.isReady() && !excludeDevices.contains(disk)) { + devices.add(disk); + } + } + return devices; + } + + public void addClusterListener(ClusterListener listener) { + listeners.add(listener); + } + + public void removeClusterListener(ClusterListener listener) { + listeners.remove(listener); + } + + public void addGlusterServer(GlusterServer server) { + Cluster cluster = model.getCluster(); + cluster.addServer(server); + + for (ClusterListener listener : listeners) { + listener.serverAdded(server); + } + + removeDiscoveredServer(server.getName()); + } + + public void addDiscoveredServer(Server server) { + Cluster cluster = model.getCluster(); + cluster.addDiscoveredServer(server); + + for (ClusterListener listener : listeners) { + listener.discoveredServerAdded(server);; + } + } + + public void discoveredServerChanged(Server oldServer, Server newServer) { + oldServer.copyFrom(newServer); + for (ClusterListener listener : listeners) { + listener.discoveredServerChanged(oldServer, new Event(EVENT_TYPE.DISCOVERED_SERVER_CHANGED, newServer)); + } + updateDisks(oldServer, oldServer.getDisks(), newServer.getDisks()); + } + + public void removeDiscoveredServer(String serverName) { + Cluster cluster = model.getCluster(); + // TODO: Move auto-discovered servers outside the cluster + for(Server server : cluster.getAutoDiscoveredServers()) { + if(server.getName().toUpperCase().equals(serverName.toUpperCase())) { + removeDiscoveredServer(server); + return; + } + } + } + + public void removeDiscoveredServer(Server server) { + Cluster cluster = model.getCluster(); + cluster.removeDiscoveredServer(server); + + for (ClusterListener listener : listeners) { + listener.discoveredServerRemoved(server); + } + } + + public void removeGlusterServer(GlusterServer server) { + Cluster cluster = model.getCluster(); + cluster.removeServer(server); + + // can't use an iterator here. The method AbstractList.Itr#next checks for concurrent modification. + // Since listeners can end up creating new views, which add themselves as listeners, the listeners + // list can be concurrently modified which can result in an exception while using iterator. + // Hence we use List#get instead of the iterator + for(int i = 0; i < listeners.size(); i++) { + ClusterListener listener = listeners.get(i); + listener.serverRemoved(server); + } + + // add it to discovered servers list if it is online server + if (server.isOnline()) { + Server removedServer = new Server(); + removedServer.copyFrom(server); + removedServer.addDisks(server.getDisks()); + addDiscoveredServer(removedServer); + } + } + + public void deleteVolume(Volume volume) { + Cluster cluster = model.getCluster(); + cluster.deleteVolume(volume); + + // can't use an iterator here. The method AbstractList.Itr#next checks for concurrent modification. + // Since listeners can end up creating new views, which add themselves as listeners, the listeners + // list can be concurrently modified which can result in an exception while using iterator. + // Hence we use List#get instead of the iterator + for(int i = 0; i < listeners.size(); i++) { + ClusterListener listener = listeners.get(i); + listener.volumeDeleted(volume); + } + } + + public void updateVolumeStatus(Volume volume, VOLUME_STATUS newStatus) { + volume.setStatus(newStatus); + + if(newStatus == VOLUME_STATUS.OFFLINE) { + // mark as bricks also as offline + for(Brick brick : volume.getBricks()) { + brick.setStatus(BRICK_STATUS.OFFLINE); + } + } else { + Volume newVolume = new VolumesClient().getVolume(volume.getName()); //Getting latest brick info + updateBricks(volume, volume.getBricks(), newVolume.getBricks()); + } + + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_STATUS_CHANGED, newStatus)); + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_CHANGED, volume.getBricks())); + } + } + + public void resetVolumeOptions(Volume volume) { + volume.getOptions().clear(); + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_OPTIONS_RESET, null)); + } + } + + public void addBricks(Volume volume, Set bricks) { + if(bricks.size() == 0) { + return; + } + + volume.addBricks(bricks); + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_ADDED, bricks)); + } + } + + public void removeBricks(Volume volume, Set bricks) { + if(bricks.size() == 0) { + return; + } + + // Remove the bricks from the volume object + for (Brick brick : bricks) { + volume.removeBrick(brick); + } + + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_REMOVED, bricks)); + } + } + + public void setVolumeOption(Volume volume, String optionKey, String optionValue) { + volume.setOption(optionKey, optionValue); + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_OPTION_SET, optionKey)); + } + } + + public void addVolume(Volume volume) { + Cluster cluster = model.getCluster(); + cluster.addVolume(volume); + + for (ClusterListener listener : listeners) { + listener.volumeCreated(volume); + } + } + + public void addTask(TaskInfo taskInfo) { + Cluster cluster = model.getCluster(); + cluster.addTaskInfo(taskInfo); + for (ClusterListener listener : listeners) { + listener.taskAdded(taskInfo); + } + } + + // Updating the Task + public void updateTask(TaskInfo taskInfo) { + for (ClusterListener listener : listeners) { + listener.taskUpdated(taskInfo); + } + } + + public void removeTask(TaskInfo taskInfo) { + model.getCluster().removeTaskInfo(taskInfo); + for (ClusterListener listener : listeners) { + listener.taskRemoved(taskInfo); + } + } + + public void alertsGenerated() { + for (ClusterListener listener : listeners) { + listener.alertsGenerated(); + } + } + + public List getVolumeOptionsDefaults() { + return volumeOptionsDefaults; + } + + public VolumeOptionInfo getVolumeOptionInfo(String optionKey) { + for (VolumeOptionInfo info : volumeOptionsDefaults) { + if (info.getName().equals(optionKey)) { + return info; + } + } + throw new GlusterRuntimeException("Invalid option key [" + optionKey + + "] passed to GlusterDataModelManager#getVolumeOptionInfo"); + } + + public String getVolumeOptionDefaultValue(String optionKey) { + return getVolumeOptionInfo(optionKey).getDefaultValue(); + } + + public String getVolumeOptionDesc(String optionKey) { + return getVolumeOptionInfo(optionKey).getDescription(); + } + + public void setAccessControlList(Volume volume, String accessControlList) { + setVolumeOption(volume, Volume.OPTION_AUTH_ALLOW, accessControlList); + } + + public void setNfsEnabled(Volume volume, boolean enabled) { + setVolumeOption(volume, Volume.OPTION_NFS_DISABLE, (enabled) ? GlusterConstants.OFF : GlusterConstants.ON); + } + + public void setCifsConfig(Volume volume, boolean enabled, List cifsUsers) { + if (enabled) { + volume.enableCifs(); + volume.setCifsUsers(cifsUsers); + } else { + volume.disableCifs(); + } + } + + public Server getGlusterServer(String serverName) { + for (Server server : model.getCluster().getServers()) { + if (server.getName().equalsIgnoreCase(serverName)) { + return server; + } + } + return null; + } + + private Boolean isDeviceUsed(Volume volume, Device device) { + Device brickDevice = null; + for (Brick brick : volume.getBricks()) { + brickDevice = getDeviceForBrickDir(brick); + if (brickDevice != null && device.getName().equals(brickDevice.getName()) + && device.getServerName().equalsIgnoreCase(brick.getServerName())) { + return true; + } + } + return false; + } + + public boolean isDeviceUsed(Device device) { + if (device.getStatus() == DEVICE_STATUS.INITIALIZED) { + for (Volume volume : model.getCluster().getVolumes()) { + if (isDeviceUsed(volume, device)) { + return true; + } + } + } + return false; + } + + public List getVolumesOfServer(String serverName) { + List volumeNames = new ArrayList(); + Cluster cluster = model.getCluster(); + for (Volume volume : cluster.getVolumes()) { + for (Brick brick : volume.getBricks()) { + if (serverName.equalsIgnoreCase(brick.getServerName())) { + volumeNames.add(volume.getName()); + break; + } + } + } + return volumeNames; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterServerTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterServerTableLabelProvider.java new file mode 100644 index 00000000..71d252ef --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/GlusterServerTableLabelProvider.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.GlusterServersPage.GLUSTER_SERVER_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class GlusterServerTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof GlusterServer)) { + return null; + } + + GlusterServer server = (GlusterServer) element; + if(columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + SERVER_STATUS status = server.getStatus(); + if(status == SERVER_STATUS.ONLINE) { + return guiHelper.getImage(IImageKeys.STATUS_ONLINE_16x16); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE_16x16); + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof GlusterServer)) { + return null; + } + + GlusterServer server = (GlusterServer) element; + + if (server.getStatus() == SERVER_STATUS.OFFLINE + && columnIndex != GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() + && columnIndex != GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + return "NA"; + } + + return (columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() ? server.getName() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal() ? server.getStatusStr() + // : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.PREFERRED_NETWORK.ordinal() ? server.getPreferredNetworkInterface().getName() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS.ordinal() ? "" + server.getNumOfCPUs() + //: columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE.ordinal() ? "" + server.getCpuUsage() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY.ordinal() ? "" + NumberUtil.formatNumber((server.getTotalMemory() / 1024)) + //: columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE.ordinal() ? "" + server.getMemoryInUse() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_FREE_SPACE.ordinal() ? NumberUtil.formatNumber((server.getFreeDiskSpace() / 1024)) + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES.ordinal() ? server.getIpAddressesAsString() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE.ordinal() ? NumberUtil.formatNumber((server.getTotalDiskSpace() / 1024)) + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ICommandIds.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ICommandIds.java new file mode 100644 index 00000000..36cfd9dc --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ICommandIds.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +/** + * Interface defining the application's command IDs. + * Key bindings can be defined for specific commands. + * To associate an action with a command, use IAction.setActionDefinitionId(commandId). + * + * @see org.eclipse.jface.action.IAction#setActionDefinitionId(String) + */ +public interface ICommandIds { + + public static final String CMD_OPEN = "com.gluster.storage.management.console.open"; + public static final String CMD_OPEN_MESSAGE = "com.gluster.storage.management.console.openMessage"; + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IEntityListener.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IEntityListener.java new file mode 100644 index 00000000..91d90afe --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IEntityListener.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Any class that is interested in changes to entities in application scope should implement this interface and register + * with the application using {@link Application#addEntityListener(IEntityListener)} + * + * @author root + * + */ +public interface IEntityListener { + /** + * This method is called whenever any attribute of an entity in application scope changes + * @param entity Entity that has changed + * @param paremeters List of attribute names that have changed. This can be null. + */ + public void entityChanged(Entity entity, String[] paremeters); +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IImageKeys.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IImageKeys.java new file mode 100644 index 00000000..67590b27 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/IImageKeys.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +public interface IImageKeys { + + + public static final String CLUSTER_16x16 = "icons/tango/16x16/cluster.png"; + + public static final String VOLUMES_16x16 = "icons/tango/16x16/volumes.png"; + public static final String VOLUME_16x16 = "icons/tango/16x16/volume.png"; + public static final String CREATE_VOLUME_32x32 = "icons/tango/32x32/create-volume.png"; + public static final String START_VOLUME_32x32 = "icons/tango/32x32/start-volume.png"; + public static final String STOP_VOLUME_32x32 = "icons/tango/32x32/stop-volume.png"; + public static final String RESET_VOLUME_OPTIONS_32x32 = "icons/tango/32x32/reset-volume-option.png"; + public static final String VOLUME_OPTIONS_16x16 = "icons/tango/16x16/volume-options.png"; + public static final String CREATE_VOLUME_48x48 = "icons/tango/48x48/create-volume.png"; + public static final String REMOVE_VOLUME_32x32 = "icons/tango/32x32/remove-volume.png"; + public static final String VOLUME_REBALANCE_32x32 = "icons/tango/32x32/volume-rebalance.png"; + public static final String VOLUME_REBALANCE_22x22 = "icons/tango/22x22/volume-rebalance.png"; + public static final String BRICK_MIGRATE_32x32 = "icons/tango/32x32/replace-brick.png"; + public static final String BRICK_MIGRATE_22x22 = "icons/tango/22x22/replace-brick.png"; + public static final String ADD_BRICK_32x32 = "icons/tango/32x32/add-brick.png"; + public static final String REMOVE_BRICK_32x32 = "icons/tango/32x32/remove-brick.png"; + public static final String BRICK_OFFLINE_22x22 = "icons/tango/22x22/offline-brick.png"; + public static final String BRICKS_16x16 = "icons/tango/16x16/bricks.png"; + public static final String BRICK_ONLINE_16x16 = "icons/tango/16x16/online-brick.png"; + public static final String BRICK_OFFLINE_16x16 = "icons/tango/16x16/offline-brick.png"; + + public static final String SERVERS_16x16 = "icons/tango/16x16/servers.png"; + public static final String SERVER_16x16 = "icons/tango/16x16/server.png"; + public static final String SERVER_WARNING_22x22 = "icons/tango/22x22/server-warning.png"; + public static final String MEMORY_USAGE_ALERT_22x22 = "icons/tango/22x22/high-memory-usage.png"; + public static final String SERVER_OFFLINE_22x22 = "icons/tango/22x22/offline-server.png"; + public static final String ADD_SERVER_32x32 = "icons/tango/32x32/add-server.png"; + public static final String ADD_SERVER_48x48 = "icons/tango/48x48/add-server.png"; + public static final String REMOVE_SERVER_32x32 = "icons/tango/32x32/remove-server.png"; + + public static final String DISK_16x16 = "icons/tango/16x16/disk.png"; + public static final String DISKS_16x16 = "icons/tango/16x16/disk.png"; + public static final String DISK_UNINITIALIZED_16x16 = "icons/tango/16x16/disk-uninitialized.png"; + public static final String IO_ERROR_16x16 = "icons/tango/16x16/disk-error.png"; + public static final String DISK_AVAILABLE_16x16 = "icons/tango/16x16/disk-available.png"; + public static final String DISK_INITIALIZING_16x16 = "icons/tango/16x16/disk-initialisation.png"; + public static final String DISK_INITIALIZING_22x22 = "icons/tango/22x22/disk-initialisation.png"; + public static final String DISK_IN_USE_16x16 = "icons/tango/16x16/disk-inuse.png"; + public static final String LOW_DISK_SPACE_22x22 = "icons/tango/22x22/low-diskspace.png"; + + public static final String STATUS_OFFLINE_16x16 = "icons/tango/16x16/status-offline.png"; + public static final String STATUS_ONLINE_16x16 = "icons/tango/16x16/status-online.png"; + + public static final String HELP_16x16 = "icons/tango/16x16/question.png"; + public static final String SEARCH_22x22 = "icons/tango/22x22/system-search.png"; + public static final String ARROW_UP_16x16 = "icons/tango/16x16/arrow-up.png"; + public static final String ARROW_DOWN_16x16 = "icons/tango/16x16/arrow-down.png"; + + public static final String DOWNLOAD_LOG_32x32 = "icons/tango/32x32/download-log.png"; + + + public static final String PAUSE_TASK_32x32 = "icons/tango/32x32/pause.png"; + public static final String RESUME_TASK_32x32 = "icons/tango/32x32/start.png"; + public static final String STOP_TASK_32x32 = "icons/tango/32x32/stop.png"; + public static final String CLEAR_TASK_32x32 = "icons/tango/32x32/clear-task.png"; + public static final String COMMIT_TASK_32x32 = "icons/tango/32x32/commit-task.png"; + public static final String PAUSE_TASK_16x16 = "icons/tango/16x16/pause.png"; + public static final String RESUME_TASK_16x16 = "icons/tango/16x16/start.png"; + public static final String STOP_TASK_16x16 = "icons/tango/16x16/stop.png"; + public static final String CLEAR_TASK_16x16 = "icons/tango/16x16/close_task.png"; + public static final String COMPLETED_TASK_16x16 = "icons/tango/16x16/task-completed.png"; + + public static final String OVERLAY_OFFLINE_8x8 = "icons/tango/8x8/offline.png"; + public static final String OVERLAY_ONLINE_8x8 = "icons/tango/8x8/online.png"; + public static final String OVERLAY_STAR_8x8 = "icons/tango/8x8/star.png"; + + public static final String SPLASH_IMAGE = "splash.bmp"; + public static final String DIALOG_SPLASH_IMAGE = "splash/splash-dialog.bmp"; + + public static final String GAUGE_SMALL = "images/gauge_small.png"; + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/NetworkInterfaceTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/NetworkInterfaceTableLabelProvider.java new file mode 100644 index 00000000..54ed5349 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/NetworkInterfaceTableLabelProvider.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + + +import com.gluster.storage.management.console.views.GlusterServerSummaryView.NETWORK_INTERFACE_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.NetworkInterface; + +public class NetworkInterfaceTableLabelProvider extends TableLabelProviderAdapter { + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof NetworkInterface)) { + return null; + } + + NetworkInterface networkInterface = (NetworkInterface) element; + String columnText = (columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE.ordinal() ? networkInterface.getName() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.MODEL.ordinal() ? networkInterface.getModel() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.SPEED.ordinal() ? networkInterface.getSpeed() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.IP_ADDRESS.ordinal() ? networkInterface.getIpAddress() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.NETMASK.ordinal() ? networkInterface.getNetMask() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.GATEWAY.ordinal() ? networkInterface.getDefaultGateway() + : "Invalid"); + return ((columnText == null || columnText.trim().equals("")) ? CoreConstants.NA : columnText); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Perspective.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Perspective.java new file mode 100644 index 00000000..9593bb88 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/Perspective.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +public class Perspective implements IPerspectiveFactory { + + /** + * The ID of the perspective as specified in the extension. + */ + public static final String ID = Perspective.class.getName(); + + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(false); + //layout.addStandaloneView(ClusterView.ID, false, IPageLayout.LEFT, 0.30f, layout.getEditorArea()); + //layout.addStandaloneView(DetailsView.ID, false, IPageLayout.RIGHT, 0.70f, layout.getEditorArea()); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerDiskTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerDiskTableLabelProvider.java new file mode 100644 index 00000000..2f49d2b3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerDiskTableLabelProvider.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.DeviceTableLabelProvider.DEVICE_COLUMN_INDICES; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.ServerDisksPage.SERVER_DISK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Device.DEVICE_STATUS; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Partition; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class ServerDiskTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + private GlusterDataModelManager glusterDataModelManager = GlusterDataModelManager.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Device)) { + return null; + } + + Device device = (Device) element; + if (columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + DEVICE_STATUS status = device.getStatus(); + + if (status == null) { + return null; + } + + if(element instanceof Disk && ((Disk)element).hasPartitions()) { + // disk has partitions. so don't show status image at disk level. + return null; + } + + switch (status) { + case INITIALIZED: + if(glusterDataModelManager.isDeviceUsed(device)) { + return guiHelper.getImage(IImageKeys.DISK_IN_USE_16x16); + } else { + return guiHelper.getImage(IImageKeys.DISK_AVAILABLE_16x16); + } + case IO_ERROR: + return guiHelper.getImage(IImageKeys.IO_ERROR_16x16); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED_16x16); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.DISK_INITIALIZING_16x16); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + private String getDeviceFreeSpace(Device device) { + if (device.hasErrors() || device.isUninitialized()) { + return "NA"; + } else { + return NumberUtil.formatNumber((device.getFreeSpace() / 1024)); + } + } + + private String getTotalDeviceSpace(Device device) { + if (device.hasErrors() || device.isUninitialized()) { + return "NA"; + } else { + return NumberUtil.formatNumber((device.getSpace() / 1024)); + } + } + + public String getColumnText(Object element, int columnIndex) { + Device device = (Device) element; + if (columnIndex == DEVICE_COLUMN_INDICES.DISK.ordinal()) { + // show value in "disk" column only if it's a disk + if (device instanceof Disk) { + return device.getName(); + } else { + return ""; + } + } + + if(element instanceof Disk && ((Disk)element).hasPartitions()) { + // disk has partitions. so don't show any other details + return ""; + } + + if (columnIndex == DEVICE_COLUMN_INDICES.FREE_SPACE.ordinal()) { + return "" + getDeviceFreeSpace(device); + } else if (columnIndex == DEVICE_COLUMN_INDICES.SPACE_IN_USE.ordinal()) { + return "" + getTotalDeviceSpace(device); + } else if (columnIndex == DEVICE_COLUMN_INDICES.PARTITION.ordinal()) { + if (device instanceof Partition) { + return device.getName(); + } else { + return ""; + } + } else if (columnIndex == DEVICE_COLUMN_INDICES.STATUS.ordinal()) { + if(device.isUninitialized()) { + return ""; + } + if(glusterDataModelManager.isDeviceUsed(device)) { + return "In Use"; + } else { + return device.getStatusStr(); + } + } else { + return ""; + } + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerTableLabelProvider.java new file mode 100644 index 00000000..eccf67ec --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/ServerTableLabelProvider.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.ServersPage.SERVER_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class ServerTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Server)) { + return null; + } + + Server server = (Server) element; + return (columnIndex == SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() ? server.getName() + : columnIndex == SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES.ordinal() ? server.getIpAddressesAsString() + : columnIndex == SERVER_TABLE_COLUMN_INDICES.NUM_OF_DISKS.ordinal() ? "" + + server.getNumOfDisks() : columnIndex == SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE + .ordinal() ? NumberUtil.formatNumber((server.getTotalDiskSpace() / 1024)) + // : columnIndex == SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS.ordinal() ? "" + + // server.getNumOfCPUs() + // : columnIndex == SERVER_TABLE_COLUMN_INDICES.CPU_USAGE.ordinal() ? "" + server.getCpuUsage() + // : columnIndex == SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY.ordinal() ? "" + + // server.getTotalMemory() + // : columnIndex == SERVER_TABLE_COLUMN_INDICES.MEMORY_IN_USE.ordinal() ? "" + + // server.getMemoryInUse() + // : columnIndex == SERVER_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE.ordinal() ? "" + + // server.getDiskSpaceInUse() + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TableLabelProviderAdapter.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TableLabelProviderAdapter.java new file mode 100644 index 00000000..5c527082 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TableLabelProviderAdapter.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Image; + +public class TableLabelProviderAdapter implements ITableLabelProvider { + + @Override + public void addListener(ILabelProviderListener listener) { + // do nothing + + } + + @Override + public void dispose() { + // do nothing + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return true; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + // do nothing + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + return null; + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TasksTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TasksTableLabelProvider.java new file mode 100644 index 00000000..66fbefd3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/TasksTableLabelProvider.java @@ -0,0 +1,71 @@ +/** + * TasksTableLabelProvider.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.TasksPage.TASK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + + +public class TasksTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + + if (!(element instanceof TaskInfo)) { + return null; + } + + TaskInfo taskInfo = (TaskInfo) element; + if (columnIndex == TASK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + int statusCode = taskInfo.getStatus().getCode(); + + switch (statusCode) { + case Status.STATUS_CODE_SUCCESS: + return guiHelper.getImage(IImageKeys.COMPLETED_TASK_16x16); + case Status.STATUS_CODE_PAUSE: + return guiHelper.getImage(IImageKeys.PAUSE_TASK_16x16); + case Status.STATUS_CODE_RUNNING: + return guiHelper.getImage(IImageKeys.RESUME_TASK_16x16); + case Status.STATUS_CODE_FAILURE: + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE_16x16); + default: + break; + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof TaskInfo)) { + return null; + } + + TaskInfo taskInfo = (TaskInfo) element; + return (columnIndex == TASK_TABLE_COLUMN_INDICES.TASK.ordinal()) ? taskInfo.getDescription().trim() : taskInfo.getStatus().getMessage().trim(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeLogTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeLogTableLabelProvider.java new file mode 100644 index 00000000..7b81ab87 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeLogTableLabelProvider.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + + +import com.gluster.storage.management.console.views.pages.VolumeLogsPage.LOG_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.VolumeLogMessage; +import com.gluster.storage.management.core.utils.DateUtil; + +public class VolumeLogTableLabelProvider extends TableLabelProviderAdapter { + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof VolumeLogMessage)) { + return null; + } + + VolumeLogMessage logMessage = (VolumeLogMessage) element; + return (columnIndex == LOG_TABLE_COLUMN_INDICES.DATE.ordinal() ? DateUtil.formatDate(logMessage.getTimestamp()) + : columnIndex == LOG_TABLE_COLUMN_INDICES.TIME.ordinal() ? DateUtil.formatTime(logMessage.getTimestamp()) + : columnIndex == LOG_TABLE_COLUMN_INDICES.BRICK.ordinal() ? logMessage.getBrickDirectory() + : columnIndex == LOG_TABLE_COLUMN_INDICES.SEVERITY.ordinal() ? "" + logMessage.getSeverity() + : columnIndex == LOG_TABLE_COLUMN_INDICES.MESSAGE.ordinal() ? logMessage.getMessage() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsContentProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsContentProvider.java new file mode 100644 index 00000000..1289f0f4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsContentProvider.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.gluster.storage.management.core.model.VolumeOptions; + +/** + * @author root + * + */ +public class VolumeOptionsContentProvider implements IStructuredContentProvider { + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof VolumeOptions) { + return ((VolumeOptions) inputElement).getOptions().toArray(); + } + return null; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsTableLabelProvider.java new file mode 100644 index 00000000..5a1089de --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeOptionsTableLabelProvider.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import java.util.Map.Entry; + +import com.gluster.storage.management.console.views.pages.VolumeOptionsPage.OPTIONS_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.VolumeOption; + +public class VolumeOptionsTableLabelProvider extends TableLabelProviderAdapter { + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Entry)) { + return null; + } + + VolumeOption option = (VolumeOption)element; + return (columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal() ? option.getKey() + : columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE.ordinal() ? option.getValue() + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeTableLabelProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeTableLabelProvider.java new file mode 100644 index 00000000..908c23d5 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/VolumeTableLabelProvider.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console; + +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.VolumesPage.VOLUME_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class VolumeTableLabelProvider implements ITableLabelProvider { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void addListener(ILabelProviderListener listener) { + } + + @Override + public void dispose() { + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Volume)) { + return null; + } + + Volume volume = (Volume) element; + if(columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS.ordinal()) { + VOLUME_STATUS status = volume.getStatus(); + if(status == VOLUME_STATUS.ONLINE) { + return guiHelper.getImage(IImageKeys.STATUS_ONLINE_16x16); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE_16x16); + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Volume)) { + return null; + } + + Volume volume = (Volume) element; + return (columnIndex == VOLUME_TABLE_COLUMN_INDICES.NAME.ordinal() ? volume.getName() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_TYPE.ordinal() ? volume.getVolumeTypeStr() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.TRANSPORT_TYPE.ordinal() ? volume.getTransportTypeStr() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.NUM_OF_BRICKS.ordinal() ? "" + volume.getNumOfBricks() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS.ordinal() ? volume.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AbstractActionDelegate.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AbstractActionDelegate.java new file mode 100644 index 00000000..9a5a3437 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AbstractActionDelegate.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.internal.UIPlugin; + +import com.gluster.storage.management.console.utils.GlusterLogger; +import com.gluster.storage.management.core.model.Entity; + +/** + * All action delegates in the application should extend from this class. It provides common functionality of grabbing + * the Window object on initialization and extracting the selected entity in case of selection change on the navigation + * tree. + */ +@SuppressWarnings("restriction") +public abstract class AbstractActionDelegate implements IWorkbenchWindowActionDelegate { + protected IWorkbenchWindow window; + protected static final GlusterLogger logger = GlusterLogger.getInstance(); + + // the latest selected entity + protected Entity selectedEntity; + + @Override + public void run(final IAction action) { + // Real action code must be executed using Display#asyncExec. + // Otherwise the system can hang when opening new dialog boxes on linux platform + try { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + performAction(action); + } + }); + } catch (final Exception e) { + final String actionDesc = action.getDescription(); + logger.error("Exception while running action [" + actionDesc + "]", e); + + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + showErrorDialog(actionDesc, e.getMessage()); + } + }); + } + } + + abstract protected void performAction(final IAction action); + + @Override + public void selectionChanged(IAction action, ISelection selection) { + if (selection instanceof StructuredSelection) { + Entity selectedEntity = (Entity) ((StructuredSelection) selection).getFirstElement(); + + if (this.selectedEntity == selectedEntity) { + // entity selection has not changed. do nothing. + return; + } + + if (selectedEntity != null) { + this.selectedEntity = selectedEntity; + } + } + } + + @Override + public void init(IWorkbenchWindow window) { + this.window = window; + } + + protected Shell getShell() { + return getWindow().getShell(); + } + + protected IWorkbenchWindow getWindow() { + return window == null ? UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow() : window; + } + + protected void showInfoDialog(final String title, final String message) { + MessageDialog.openInformation(getShell(), title, message); + } + + protected void showWarningDialog(final String title, final String message) { + MessageDialog.openWarning(getShell(), title, message); + } + + protected void showErrorDialog(final String title, final String message) { + MessageDialog.openError(getShell(), title, message); + } + + protected boolean showConfirmDialog(final String title, final String message) { + return MessageDialog.openQuestion(getShell(), title, message); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddBrickAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddBrickAction.java new file mode 100644 index 00000000..479353ff --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddBrickAction.java @@ -0,0 +1,64 @@ +/** + * AddBrickAction.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ + +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.dialogs.AddBrickWizard; +import com.gluster.storage.management.core.model.Volume; + +public class AddBrickAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void dispose() { + window = null; + } + + @Override + protected void performAction(IAction action) { + // TODO: open a dialog box + // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + + // volume.getName()); + AddBrickWizard wizard = new AddBrickWizard(volume); // Also add single page + + WizardDialog dialog = new WizardDialog(getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(1024, 600); + dialog.open(); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + this.volume = (Volume) selectedEntity; + // action.setEnabled(volume.getStatus() == VOLUME_STATUS.ONLINE); + } + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddServerAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddServerAction.java new file mode 100644 index 00000000..6b47c6c2 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/AddServerAction.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.dialogs.ServerAdditionDialog; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Server; + +public class AddServerAction extends AbstractActionDelegate { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + protected void performAction(final IAction action) { + final Runnable addServerThread = new Runnable() { + @Override + public void run() { + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + GlusterServersClient glusterServersClient = new GlusterServersClient(); + + Set selectedServers = GUIHelper.getInstance().getSelectedEntities(getWindow(), Server.class); + Set successServers = new HashSet(); + Set partSuccessServers = new HashSet(); + String errMsg = ""; + String partErrMsg = ""; + + if (selectedServers.isEmpty()) { + addServerManually(); + } else { + for (Server server : selectedServers) { + guiHelper.setStatusMessage("Adding server [" + server.getName() + "]..."); + + try { + glusterServersClient.addServer(server.getName()); + modelManager.addGlusterServer(glusterServersClient.getGlusterServer(server.getName())); + successServers.add(server); + } catch (Exception e) { + if (!errMsg.isEmpty()) { + errMsg += CoreConstants.NEWLINE; + } + errMsg += "Server " + server.getName() + ". Error: [" + e.getMessage() + "]"; + } + } + + guiHelper.clearStatusMessage(); + showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, + errMsg, partErrMsg); + } + } + + private void addServerManually() { + try { + // To open a dialog for server addition + ServerAdditionDialog dialog = new ServerAdditionDialog(getShell()); + dialog.open(); + } catch (Exception e) { + logger.error("Error in Manual server addition", e); + showErrorDialog("Add server", "Add server failed! [" + e.getMessage() + "]"); + } + } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + Display.getDefault().asyncExec(addServerThread); + } + }); + } + + private void showStatusMessage(String dialogTitle, Set selectedServers, Set successServers, + Set partSuccessServers, String errMsg, String partErrMsg) { + if (successServers.size() == selectedServers.size()) { + if (selectedServers.size() == 1) { + showInfoDialog(dialogTitle, "Server [" + selectedServers.iterator().next() + "] added successfully!"); + } else { + showInfoDialog(dialogTitle, "Following servers added successfully!" + CoreConstants.NEWLINE + + selectedServers); + } + return; + } + + String finalMsg = ""; + if (successServers.size() == 0 && partSuccessServers.size() == 0) { + finalMsg = "Server Addition Failed! Error(s):" + CoreConstants.NEWLINE + errMsg; + } else { + finalMsg = (successServers.isEmpty() ? "" : "Following servers added successfully : " + + CoreConstants.NEWLINE + successServers + CoreConstants.NEWLINE) + + (partSuccessServers.isEmpty() ? "" : "Following servers were added to cluster, but with some errors: " + + CoreConstants.NEWLINE + partErrMsg + CoreConstants.NEWLINE) + + (errMsg.isEmpty() ? "" : CoreConstants.NEWLINE + + "Following errors occurred on other selected servers: " + CoreConstants.NEWLINE + errMsg); + } + showErrorDialog(dialogTitle, finalMsg); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ChangePasswordAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ChangePasswordAction.java new file mode 100644 index 00000000..a06f13b4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ChangePasswordAction.java @@ -0,0 +1,23 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; + +import com.gluster.storage.management.console.dialogs.ChangePasswordDialog; + +public class ChangePasswordAction extends AbstractActionDelegate { + + @Override + protected void performAction(IAction action) { + try { + // To open a dialog for change password + ChangePasswordDialog dialog = new ChangePasswordDialog(getShell()); + dialog.open(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void dispose() { + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ClearTaskAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ClearTaskAction.java new file mode 100644 index 00000000..7cb9a873 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ClearTaskAction.java @@ -0,0 +1,46 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public class ClearTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + + try { + new TasksClient().deleteTask(taskInfo.getName()); // taskId + modelManager.removeTask(taskInfo); + action.setEnabled(false); // TODO disable other task buttons + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be cleared! Error: [" + e.getMessage() + "]"); + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + action.setEnabled(false); + if (selectedEntity instanceof TaskInfo) { + taskInfo = (TaskInfo) selectedEntity; + action.setEnabled(taskInfo.getStatus().getCode() == Status.STATUS_CODE_SUCCESS + || taskInfo.getStatus().getCode() == Status.STATUS_CODE_FAILURE); + } else { + action.setEnabled(false); + } + } + + @Override + public void dispose() { + + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CommitTaskAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CommitTaskAction.java new file mode 100644 index 00000000..ff47ff41 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CommitTaskAction.java @@ -0,0 +1,72 @@ +package com.gluster.storage.management.console.actions; + + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; + +public class CommitTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + try { + new TasksClient().commitTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, "Committed"))); + modelManager.removeTask(taskInfo); + showInfoDialog(actionDesc, "Commit successful"); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be Committed! Error: [" + e.getMessage() + "]"); + return; // Prevent to update model + } + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + try { + String volumeName = taskInfo.getReference(); + Volume oldVolume = modelManager.getModel().getCluster().getVolume(volumeName); + Volume newVolume = (new VolumesClient()).getVolume(volumeName); + + modelManager.volumeChanged(oldVolume, newVolume); + } catch (Exception e) { + String errMsg = "Volume brick update failed! [" + e.getMessage() + "]"; + logger.error(errMsg, e); + showInfoDialog(actionDesc, errMsg); + } + } + }); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + action.setEnabled(false); + if (selectedEntity instanceof TaskInfo) { + taskInfo = (TaskInfo) selectedEntity; + action.setEnabled(taskInfo.getCommitSupported() + && taskInfo.getStatus().getCode() == Status.STATUS_CODE_COMMIT_PENDING); + } + } + + public void updateVolume(String volumeName) { + + } + + @Override + public void dispose() { + + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CreateVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CreateVolumeAction.java new file mode 100644 index 00000000..38be70bd --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/CreateVolumeAction.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +import com.gluster.storage.management.console.dialogs.CreateVolumeWizard; + +public class CreateVolumeAction extends AbstractActionDelegate { + @Override + protected void performAction(IAction action) { + CreateVolumeWizard wizard = new CreateVolumeWizard(); + + WizardDialog dialog = new WizardDialog(getShell(), wizard) { + @Override + protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { + Button button = super.createButton(parent, id, label, defaultButton); + if (id == IDialogConstants.FINISH_ID) { + button.setText("&Create"); + } + return button; + } + }; + dialog.create(); + dialog.getShell().setSize(500, 610); + dialog.open(); + } + + @Override + public void dispose() { + window = null; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DeleteVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DeleteVolumeAction.java new file mode 100644 index 00000000..4e460603 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DeleteVolumeAction.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +public class DeleteVolumeAction extends AbstractActionDelegate { + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private List volumes = new ArrayList(); + private List selectedVolumeNames = new ArrayList(); + private List onlineVolumeNames = new ArrayList(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + VolumesClient vc = new VolumesClient(); + + collectVolumeNames(); + String warningMessage; + if (onlineVolumeNames.size() > 0) { // There are some online volumes, get confirmation to stop and delete all + // the volumes + warningMessage = "Following volume(s) [" + StringUtil.collectionToString(onlineVolumeNames, ", ") + + "] are online, " + CoreConstants.NEWLINE + "Are you sure to continue?"; + } else { + warningMessage = "Are you sure to delete the following volume(s) [" + + StringUtil.collectionToString(selectedVolumeNames, ", ") + "] ?"; + } + + Integer deleteOption = new MessageDialog(getShell(), "Delete Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME_16x16), warningMessage, MessageDialog.QUESTION, new String[] { "Cancel", + "Delete volume and data", "Delete volume, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } + + boolean confirmDelete = (deleteOption == 1) ? true : false; + List deletedVolumes = new ArrayList(); + List failedVolumes = new ArrayList(); + String errorMessage = ""; + + for (Volume volume : volumes) { + try { + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { // stop if online volume + vc.stopVolume(volume.getName()); + } + vc.deleteVolume(volume, confirmDelete); + modelManager.deleteVolume(volume); + deletedVolumes.add(volume.getName()); + } catch (Exception e) { + // there is a possibility that the error was in post-delete operation, which means + // volume was deleted, but some other error happened. check if this is the case. + if (vc.volumeExists(volume.getName())) { + errorMessage += CoreConstants.NEWLINE + "Volume [" + volume.getName() + + "] could not be deleted! Error: [" + e.getMessage() + "]"; + failedVolumes.add(volume.getName()); + } else { + errorMessage += CoreConstants.NEWLINE + "Volume deleted, but following error(s) occured: [" + + e.getMessage() + "]"; + modelManager.deleteVolume(volume); + deletedVolumes.add(volume.getName()); + } + } + } + + // Display the success or failure info + if (deletedVolumes.size() == 0) { // No volume(s) deleted successfully + showErrorDialog(actionDesc, "Following volume(s) [" + StringUtil.collectionToString(failedVolumes, ", ") + + "] could not be delete! " + CoreConstants.NEWLINE + "Error: [" + errorMessage + "]"); + } else { + String info = "Following volumes [" + StringUtil.collectionToString(deletedVolumes, ", ") + + "] are deleted successfully!"; + if (errorMessage != "") { + info += CoreConstants.NEWLINE + CoreConstants.NEWLINE + "Following volumes [" + + StringUtil.collectionToString(failedVolumes, ", ") + "] are failed to delete! [" + + errorMessage + "]"; + } + showInfoDialog(actionDesc, info); + } + } + + private void collectVolumeNames() { + selectedVolumeNames.clear(); + onlineVolumeNames.clear(); + for (Volume volume : volumes) { + selectedVolumeNames.add(volume.getName()); + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + onlineVolumeNames.add(volume.getName()); + } + } + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + Set selectedVolumes = GUIHelper.getInstance().getSelectedEntities(getWindow(), Volume.class); + volumes.clear(); + if (selectedVolumes == null || selectedVolumes.isEmpty()) { + super.selectionChanged(action, selection); + if (selectedEntity instanceof Volume) { + volumes.add((Volume) selectedEntity); + } + } else { + volumes.addAll(selectedVolumes); //TODO reverse the collection to maintain the selected order + } + + action.setEnabled( (volumes.size() > 0) ); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DownloadVolumeLogsAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DownloadVolumeLogsAction.java new file mode 100644 index 00000000..df24f15b --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/DownloadVolumeLogsAction.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Volume; + +/** + * + */ +public class DownloadVolumeLogsAction extends AbstractActionDelegate { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void dispose() { + } + + @Override + protected void performAction(IAction action) { + final VolumesClient client = new VolumesClient(); + final Runnable downloadLogsThread = new Runnable() { + + @Override + public void run() { + Volume volume = guiHelper.getSelectedEntity(getWindow(), Volume.class); + + FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); + dialog.setFilterNames(new String[] {"GZipped Tar (*.tar.gz)"}); + dialog.setFilterExtensions(new String[] {"*.tar.gz"}); + String filePath = dialog.open(); + + if(filePath == null) { + return; + } + + String title = "Download Volume Logs [" + volume.getName() + "]"; + try { + client.downloadLogs(volume.getName(), filePath); + showInfoDialog(title, "Volume logs downloaded successfully to [" + filePath + "]"); + } catch(Exception e) { + showErrorDialog(title, e.getMessage()); + } + } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + + @Override + public void run() { + Display.getDefault().asyncExec(downloadLogsThread); + } + }); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/EditVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/EditVolumeAction.java new file mode 100644 index 00000000..610cbdf6 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/EditVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; + +public class EditVolumeAction extends AbstractActionDelegate { + @Override + protected void performAction(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ExportSshKeysAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ExportSshKeysAction.java new file mode 100644 index 00000000..2f0d03dc --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ExportSshKeysAction.java @@ -0,0 +1,77 @@ +/** + * ExportSshKeysAction.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; + +import com.gluster.storage.management.client.KeysClient; + +/** + * @author root + * + */ +public class ExportSshKeysAction extends AbstractActionDelegate { + + @Override + protected void performAction(IAction action) { + final KeysClient client = new KeysClient(); + final Runnable exportKeysThread = new Runnable() { + + @Override + public void run() { + FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); + dialog.setFilterNames(new String[] {"Tar (*.tar)"}); + dialog.setFilterExtensions(new String[] {"*.tar"}); + String filePath = dialog.open(); + + if(filePath == null) { + return; + } + + String title = "Export SSH Keys"; + try { + client.exportSshKeys(filePath); + showInfoDialog(title, "SSH keys exported successfully to [" + filePath + "]"); + } catch(Exception e) { + showErrorDialog(title, e.getMessage()); + } + } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + + @Override + public void run() { + Display.getDefault().asyncExec(exportKeysThread); + } + }); + } + + + @Override + public void dispose() { + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/IActionConstants.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/IActionConstants.java new file mode 100644 index 00000000..862d4144 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/IActionConstants.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +public interface IActionConstants { + public static final String ACTION_SET_CLUSTER = "com.gluster.storage.management.console.actionsets.gluster"; + public static final String ACTION_SET_VOLUMES = "com.gluster.storage.management.console.actionsets.volumes"; + public static final String ACTION_SET_VOLUME = "com.gluster.storage.management.console.actionsets.volume"; + public static final String ACTION_SET_DISKS = "com.gluster.storage.management.console.actionsets.disks"; + public static final String ACTION_SET_DISK = "com.gluster.storage.management.console.actionsets.disk"; + public static final String ACTION_SET_GLUSTER_SERVERS = "com.gluster.storage.management.console.actionsets.glusterservers"; + public static final String ACTION_SET_GLUSTER_SERVER = "com.gluster.storage.management.console.actionsets.glusterserver"; + public static final String ACTION_SET_DISCOVERED_SERVERS = "com.gluster.storage.management.console.actionsets.serversdiscovered"; + public static final String ACTION_SET_DISCOVERED_SERVER = "com.gluster.storage.management.console.actionsets.serverdiscovered"; + public static final String ACTION_SET_TASK = "com.gluster.storage.management.console.actionsets.task"; + public static final String ACTION_SET_EDIT = "com.gluster.storage.management.console.actionsets.edit"; + + public static final String COMMAND_CREATE_VOLUME = "com.gluster.storage.management.console.commands.CreateVolume"; + public static final String COMMAND_ADD_SERVER = "com.gluster.storage.management.console.commands.AddServer"; +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ImportSshKeysAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ImportSshKeysAction.java new file mode 100644 index 00000000..4bdb3835 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ImportSshKeysAction.java @@ -0,0 +1,44 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; + +import com.gluster.storage.management.client.KeysClient; + +public class ImportSshKeysAction extends AbstractActionDelegate { + + @Override + protected void performAction(IAction action) { + final KeysClient client = new KeysClient(); + + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + FileDialog dialog = new FileDialog(getShell(), SWT.OPEN); + dialog.setText("Open"); + dialog.setFilterNames(new String[] { "ssh-keys (*.tar)" }); + dialog.setFilterExtensions(new String[] { "*.tar" }); + + String selectedFile = dialog.open(); + if (selectedFile == null) { + return; + } + + String title = "Import SSH Keys"; + try { + client.importSshKeys(selectedFile); + showInfoDialog(title, "SSH keys imported successfully!"); + } catch (Exception e) { + showErrorDialog(title, e.getMessage()); + } + } + }); + } + + @Override + public void dispose() { + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateBrickAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateBrickAction.java new file mode 100644 index 00000000..4816871e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateBrickAction.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.console.dialogs.MigrateBrickWizard; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Volume; + +public class MigrateBrickAction extends AbstractActionDelegate { + private Volume volume; + private Brick brick; + + @Override + protected void performAction(IAction action) { + MigrateBrickWizard wizard = new MigrateBrickWizard(volume, brick); + + WizardDialog dialog = new WizardDialog(window.getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(1024, 600); + dialog.open(); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + Set bricks; + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + } + + action.setEnabled(false); + if (selectedEntity instanceof Brick) { + bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); + brick = (Brick) bricks.iterator().next(); + action.setEnabled(brick != null); + } + } + + @Override + public void dispose() { + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateVolumeAction.java new file mode 100644 index 00000000..66013222 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/MigrateVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; + +public class MigrateVolumeAction extends AbstractActionDelegate { + @Override + protected void performAction(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PauseTaskAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PauseTaskAction.java new file mode 100644 index 00000000..92a79c73 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PauseTaskAction.java @@ -0,0 +1,67 @@ +/** + * PauseTaskAction.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskStatus; + + +public class PauseTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + + try { + new TasksClient().pauseTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, "Paused"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Paused! Error: [" + e.getMessage() + "]"); + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + action.setEnabled(false); + if (selectedEntity instanceof TaskInfo) { + taskInfo = (TaskInfo) selectedEntity; + action.setEnabled(taskInfo.getPauseSupported() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING); + } + } + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PreferencesAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PreferencesAction.java new file mode 100644 index 00000000..b81a2a51 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/PreferencesAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.actions.ActionFactory; + +public class PreferencesAction extends AbstractActionDelegate { + + @Override + public void dispose() { + + } + + @Override + protected void performAction(IAction action) { + ActionFactory.PREFERENCES.create(window).run(); + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RebalanceVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RebalanceVolumeAction.java new file mode 100644 index 00000000..d154439e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RebalanceVolumeAction.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.net.URI; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.Volume; + +public class RebalanceVolumeAction extends AbstractActionDelegate { + private Volume volume; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + try { + URI uri = new VolumesClient().rebalanceStart(volume.getName(), false, false, false); + // Add the task to model + TasksClient taskClient = new TasksClient(); + TaskInfo taskInfo = taskClient.getTaskInfo(uri); + if (taskInfo != null && taskInfo instanceof TaskInfo) { + GlusterDataModelManager.getInstance().getModel().getCluster().addTaskInfo(taskInfo); + } + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] rebalance started successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume rebalance could not be started on [" + volume.getName() + "]! Error: [" + + e.getMessage() + "]"); + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + Volume selectedVolume = guiHelper.getSelectedEntity(getWindow(), Volume.class); + if (selectedVolume != null) { + volume = (Volume) selectedVolume; + action.setEnabled(true); + } else { + action.setEnabled(false); + } + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RefreshDataAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RefreshDataAction.java new file mode 100644 index 00000000..fe9bb80a --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RefreshDataAction.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; + +import com.gluster.storage.management.console.jobs.DataSyncJob; + +/** + * + */ +public class RefreshDataAction extends AbstractActionDelegate { + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() + */ + @Override + public void dispose() { + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) + */ + @Override + protected void performAction(IAction action) { + new DataSyncJob("Cluster Data Sync").schedule(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveBrickAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveBrickAction.java new file mode 100644 index 00000000..01d70b21 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveBrickAction.java @@ -0,0 +1,91 @@ +package com.gluster.storage.management.console.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPart; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.VolumeBricksView; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.StringUtil; + +public class RemoveBrickAction extends AbstractActionDelegate { + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private GUIHelper guiHelper = GUIHelper.getInstance(); + private Set bricks; + private Volume volume; + boolean confirmDelete = false; + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + List brickList = getBrickList(bricks); + Integer deleteOption = new MessageDialog(getShell(), "Remove Bricks(s)", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME_16x16), "Are you sure you want to remove following bricks from volume [" + volume.getName() + + "] ? " + CoreConstants.NEWLINE + StringUtil.collectionToString(brickList, ", "), MessageDialog.QUESTION, new String[] { + "Cancel", "Remove bricks, delete data", "Remove bricks, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } + + if (deleteOption == 1) { + confirmDelete = true; + } + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + public void run() { + VolumesClient client = new VolumesClient(); + try { + client.removeBricks(volume.getName(), bricks, confirmDelete); + // Update model with removed bricks in the volume + modelManager.removeBricks(volume, bricks); + + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] bricks(s) removed successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume [" + volume.getName() + + "] bricks(s) could not be removed! Error: [" + e.getMessage() + "]"); + } + } + }); + } + + @Override + public void dispose() { + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + action.setEnabled(false); + volume = (Volume) guiHelper.getSelectedEntity(window, Volume.class); + if (volume != null) { + // a volume is selected on navigation tree. Let's check if the currently open view is volume disks view + IWorkbenchPart view = guiHelper.getActiveView(); + if (view instanceof VolumeBricksView) { + // volume disks view is open. check if any brick is selected + bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); + action.setEnabled(bricks.size() > 0); + } + } + } + + private List getBrickList(Set bricks) { + List brickList = new ArrayList(); + for (Brick brick : bricks) { + brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); + } + return brickList; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveServerAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveServerAction.java new file mode 100644 index 00000000..7f286191 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/RemoveServerAction.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.GlusterServer; + +public class RemoveServerAction extends AbstractActionDelegate { + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + protected void performAction(final IAction action) { + final Runnable removeServerThread = new Runnable() { + @Override + public void run() { + final String actionDesc = action.getDescription(); + + Set selectedServers = guiHelper.getSelectedEntities(getWindow(), + GlusterServer.class); + + if (!validate(action, selectedServers)) { + return; + } + + boolean confirmed = showConfirmDialog(actionDesc, "Are you sure you want to remove the server(s) " + + selectedServers + " ?"); + if (!confirmed) { + return; + } + + Set successServers = new HashSet(); + String errMsg = ""; + for (GlusterServer server : selectedServers) { + guiHelper.setStatusMessage("Removing server [" + server.getName() + "]..."); + + GlusterServersClient client = new GlusterServersClient(); + try { + client.removeServer(server.getName()); + GlusterServer glusterServer = (GlusterServer) server; + modelManager.removeGlusterServer(glusterServer); + successServers.add(server); + } catch(Exception e) { + errMsg += "[" + server.getName() + "] : " + e.getMessage(); + } + } + + guiHelper.clearStatusMessage(); + showStatusMessage(action.getDescription(), selectedServers, successServers, errMsg); + } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + Display.getDefault().asyncExec(removeServerThread); + } + }); + } + + private void showStatusMessage(String dialogTitle, Set selectedServers, Set successServers, + String errMsg) { + if (successServers.size() == selectedServers.size()) { + if(selectedServers.size() == 1) { + showInfoDialog(dialogTitle, "Server [" + selectedServers.iterator().next() + "] removed successfully!"); + } else { + showInfoDialog(dialogTitle, "Following servers removed successfully: " + CoreConstants.NEWLINE + + selectedServers); + } + return; + } + + if (successServers.size() == 0) { + errMsg = "Server Removal Failed! Error(s):" + CoreConstants.NEWLINE + errMsg; + } else { + errMsg = "Following servers removed successfully : " + CoreConstants.NEWLINE + successServers + + CoreConstants.NEWLINE + "Following errors occurred on other selected servers: " + + CoreConstants.NEWLINE + errMsg; + } + showErrorDialog(dialogTitle, errMsg); + } + + private boolean validate(IAction action, Set selectedServers) { + Map> usedServers = new HashMap>(); + for (GlusterServer server : selectedServers) { + List configuredVolumes = modelManager.getVolumesOfServer(server.getName()); + + if (configuredVolumes.size() > 0) { + usedServers.put(server, configuredVolumes); + } + } + + if (usedServers.size() > 0) { + if (usedServers.size() == 1) { + showErrorDialog(action.getDescription(), "Server [" + usedServers.keySet().iterator().next() + + "] cannot be removed as it is being used by volume(s): " + CoreConstants.NEWLINE + + usedServers.values().iterator().next() ); + } else { + String serverList = ""; + for (Entry> entry : usedServers.entrySet()) { + serverList += entry.getKey() + " -> " + entry.getValue() + CoreConstants.NEWLINE; + } + showErrorDialog(action.getDescription(), + "Following servers cannot be removed as they are being used by volume(s): " + + CoreConstants.NEWLINE + serverList ); + } + return false; + } + return true; + } + + public void dispose() { + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + Set selectedServers = GUIHelper.getInstance().getSelectedEntities(getWindow(), + GlusterServer.class); + if(selectedServers == null || selectedServers.isEmpty()) { + action.setEnabled(false); + } else { + action.setEnabled(true); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResetVolumeOptionsAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResetVolumeOptionsAction.java new file mode 100644 index 00000000..183b1668 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResetVolumeOptionsAction.java @@ -0,0 +1,63 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Volume; + +public class ResetVolumeOptionsAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void dispose() { + } + + @Override + protected void performAction(final IAction action) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + final String actionDesc = action.getDescription(); + + boolean confirmed = showConfirmDialog(actionDesc, + "Are you sure you want to reset all options of the volume [" + volume.getName() + "] ?"); + if (!confirmed) { + return; + } + + try { + new VolumesClient().resetVolumeOptions(volume.getName()); + showInfoDialog(actionDesc, "Volume options for [" + volume.getName() + "] reset successfully!"); + modelManager.resetVolumeOptions(volume); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume options for [" + volume.getName() + + "] could not be reset! Error: [" + e.getMessage() + "]"); + } + } + }); + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.console.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction + * , org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + volume = GUIHelper.getInstance().getSelectedEntity(getWindow(), Volume.class); + + if (volume instanceof Volume) { + action.setEnabled(volume.getOptions().size() > 0); + } else { + action.setEnabled(false); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResumeTaskAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResumeTaskAction.java new file mode 100644 index 00000000..d672a760 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ResumeTaskAction.java @@ -0,0 +1,45 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskStatus; + +public class ResumeTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, "Resumed"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Resumed! Error: [" + e.getMessage() + "]"); + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + action.setEnabled(false); + if (selectedEntity instanceof TaskInfo) { + taskInfo = (TaskInfo) selectedEntity; + action.setEnabled(taskInfo.getStatus().getCode() == Status.STATUS_CODE_PAUSE); + } + } + + @Override + public void dispose() { + + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ServerAdditionAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ServerAdditionAction.java new file mode 100644 index 00000000..f47f6347 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/ServerAdditionAction.java @@ -0,0 +1,28 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; + +import com.gluster.storage.management.console.dialogs.ServerAdditionDialog; +import com.gluster.storage.management.console.utils.GlusterLogger; + +public class ServerAdditionAction extends AbstractActionDelegate { + private static final GlusterLogger logger = GlusterLogger.getInstance(); + @Override + public void dispose() { + // TODO Auto-generated method stub + + } + + @Override + protected void performAction(IAction action) { + try { + // To open a dialog for server addition + ServerAdditionDialog dialog = new ServerAdditionDialog(getShell()); + dialog.open(); + } catch (Exception e) { + logger.error("Error in Manual server addition", e); + e.printStackTrace(); + } + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StartVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StartVolumeAction.java new file mode 100644 index 00000000..588dfdd6 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StartVolumeAction.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +public class StartVolumeAction extends AbstractActionDelegate { + //private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private List volumes = new ArrayList(); + private List selectedVolumeNames = new ArrayList(); + private List offlineVolumeNames = new ArrayList(); + + @Override + protected void performAction(IAction action) { + final String actionDesc = action.getDescription(); + VolumesClient vc = new VolumesClient(); + + collectVolumeNames(); + + if (offlineVolumeNames.size() == 0) { + String errorMessage; + if (selectedVolumeNames.size() == 1) { + errorMessage = "Volume [" + StringUtil.collectionToString(selectedVolumeNames, ", ") + "] is already online!"; + } else { + errorMessage = "Volumes [" + StringUtil.collectionToString(selectedVolumeNames, ", ") + "] are already online!"; + } + showWarningDialog(actionDesc, errorMessage); + return; // Volume already online. Don't do anything. + } + + List startedVolumes = new ArrayList(); + List failedVolumes = new ArrayList(); + String errorMessage = ""; + + for (Volume volume : volumes) { + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + continue; // skip if online volume + } + try { + vc.startVolume(volume.getName()); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.ONLINE); + startedVolumes.add(volume.getName()); + }catch (Exception e) { + failedVolumes.add(volume.getName()); + errorMessage += e.getMessage(); + } + } + + // Display the success or failure info + if (startedVolumes.size() == 0) { // No volume(s) started successfully + showErrorDialog(actionDesc, "Following volume(s) [" + StringUtil.collectionToString(failedVolumes, ", ") + + "] could not be start! " + CoreConstants.NEWLINE + "Error: [" + errorMessage + "]"); + } else { + String info = "Following volume(s) [" + StringUtil.collectionToString(startedVolumes, ", ") + + "] are started successfully!"; + if (errorMessage != "") { + info += CoreConstants.NEWLINE + CoreConstants.NEWLINE + "Following volume(s) [" + + StringUtil.collectionToString(failedVolumes, ", ") + "] are failed to start! [" + + errorMessage + "]"; + } + showInfoDialog(actionDesc, info); + } + } + + private void collectVolumeNames() { + selectedVolumeNames.clear(); + offlineVolumeNames.clear(); + for (Volume volume : volumes) { + selectedVolumeNames.add(volume.getName()); + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + offlineVolumeNames.add(volume.getName()); + } + } + } + + @Override + public void dispose() { + + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + Set selectedVolumes = GUIHelper.getInstance().getSelectedEntities(getWindow(), Volume.class); + volumes.clear(); + if (selectedVolumes == null || selectedVolumes.isEmpty()) { + super.selectionChanged(action, selection); + if (selectedEntity instanceof Volume) { + volumes.add((Volume) selectedEntity); + } + } else { + volumes.addAll(selectedVolumes); //TODO reverse the collection to maintain the selected order + } + + action.setEnabled(false); + // To enable the action + for (Volume volume : volumes) { + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + action.setEnabled(true); + break;// If find an online volume, enable the action + } + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopTaskAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopTaskAction.java new file mode 100644 index 00000000..25afa320 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopTaskAction.java @@ -0,0 +1,46 @@ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public class StopTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + + try { + new TasksClient().stopTask(taskInfo.getName()); + // On successful stop clear from the task list + modelManager.removeTask(taskInfo); + action.setEnabled(false); // TODO disable other task buttons + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + action.setEnabled(false); + if (selectedEntity instanceof TaskInfo) { + taskInfo = (TaskInfo) selectedEntity; + action.setEnabled(taskInfo.getStopSupported() + && (taskInfo.getStatus().getCode() == Status.STATUS_CODE_PAUSE + || taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING)); + } + } + + @Override + public void dispose() { + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopVolumeAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopVolumeAction.java new file mode 100644 index 00000000..bcfadcc5 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/StopVolumeAction.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +public class StopVolumeAction extends AbstractActionDelegate { + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private List volumes = new ArrayList(); + private List selectedVolumeNames = new ArrayList(); + private List onlineVolumeNames = new ArrayList(); + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + VolumesClient vc = new VolumesClient(); + + collectVolumeNames(); + + if (onlineVolumeNames.size() == 0) { + String errorMessage; + if (selectedVolumeNames.size() == 1) { + errorMessage = "Volume [" + StringUtil.collectionToString(selectedVolumeNames, ", ") + + "] is already offline!"; + } else { + errorMessage = "Volumes [" + StringUtil.collectionToString(selectedVolumeNames, ", ") + + "] are already offline!"; + } + showWarningDialog(actionDesc, errorMessage); + return; // Volume already offline. Don't do anything. + } + + Integer userAction = new MessageDialog(getShell(), "Stop Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME_16x16), "Are you sure you want to stop the following volume(s)?" + + CoreConstants.NEWLINE + "[" + StringUtil.collectionToString(onlineVolumeNames, ", ") + "]", + MessageDialog.QUESTION, new String[] { "No", "Yes" }, -1).open(); + + if (userAction <= 0) { // user select cancel or pressed escape key + return; + } + + List stoppedVolumes = new ArrayList(); + List failedVolumes = new ArrayList(); + String errorMessage = ""; + + for (Volume volume : volumes) { + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + continue; // skip if offline volume + } + try { + vc.stopVolume(volume.getName()); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + stoppedVolumes.add(volume.getName()); + } catch (Exception e) { + failedVolumes.add(volume.getName()); + errorMessage += e.getMessage(); + } + } + + // Display the success or failure info + if (stoppedVolumes.size() == 0) { // No volume(s) stopped successfully + showErrorDialog(actionDesc, "Following volume(s) [" + StringUtil.collectionToString(failedVolumes, ", ") + + "] could not be stopped! " + CoreConstants.NEWLINE + "Error: [" + errorMessage + "]"); + } else { + String info = "Following volume(s) [" + StringUtil.collectionToString(stoppedVolumes, ", ") + + "] are stopped successfully!"; + if (errorMessage != "") { + info += CoreConstants.NEWLINE + CoreConstants.NEWLINE + "Following volume(s) [" + + StringUtil.collectionToString(failedVolumes, ", ") + "] are failed to stop! [" + errorMessage + + "]"; + } + showInfoDialog(actionDesc, info); + } + } + + private void collectVolumeNames() { + selectedVolumeNames.clear(); + onlineVolumeNames.clear(); + for (Volume volume : volumes) { + selectedVolumeNames.add(volume.getName()); + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + onlineVolumeNames.add(volume.getName()); + } + } + } + + @Override + public void dispose() { + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.console.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction + * , org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + + Set selectedVolumes = GUIHelper.getInstance().getSelectedEntities(getWindow(), Volume.class); + volumes.clear(); + if (selectedVolumes == null || selectedVolumes.isEmpty()) { + super.selectionChanged(action, selection); + if (selectedEntity instanceof Volume) { + volumes.add((Volume) selectedEntity); + } + } else { + volumes.addAll(selectedVolumes); //TODO reverse the collection to maintain the selected order + } + + action.setEnabled(false); + // To enable the action + for (Volume volume : volumes) { + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + action.setEnabled(true); + break;// If find an online volume, enable the action + } + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/TestPopupMenuAction.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/TestPopupMenuAction.java new file mode 100644 index 00000000..0cf32adf --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/actions/TestPopupMenuAction.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IActionDelegate; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +public class TestPopupMenuAction implements IObjectActionDelegate { + + private Shell shell; + + /** + * Constructor for Action1. + */ + public TestPopupMenuAction() { + super(); + } + + /** + * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + shell = targetPart.getSite().getShell(); + } + + /** + * @see IActionDelegate#run(IAction) + */ + public void run(IAction action) { + MessageDialog.openInformation( + shell, + "glustersp-gui", + "New Action was executed."); + } + + /** + * @see IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickPage.java new file mode 100644 index 00000000..aa0a0b9c --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickPage.java @@ -0,0 +1,171 @@ +/** + * AddDiskPage.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.dialogs; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; +import com.richclientgui.toolbox.duallists.IRemovableContentProvider; + +/** + * @author root + * + */ +public class AddBrickPage extends WizardPage { + private List availableDevices = new ArrayList(); + private List selectedDevices = new ArrayList(); + private Volume volume = null; + private BricksSelectionPage page = null; + + + public static final String PAGE_NAME = "add.disk.volume.page"; + + /** + * @param pageName + */ + protected AddBrickPage(Volume volume) { + super(PAGE_NAME); + this.volume = volume; + setTitle("Add Brick"); + + String description = "Add bricks to [" + volume.getName() + "] "; + if ( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + description += "(in multiples of " + volume.getReplicaCount() + ")"; + } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + description += "(in multiples of " + volume.getStripeCount() + ")"; + } + setDescription(description); + + availableDevices = getAvailableDevices(volume); + + setPageComplete(false); + setErrorMessage("Please select bricks to be added to the volume [" + volume.getName() +"]"); + } + + + private boolean isDeviceUsed(Volume volume, Device device){ + for (Brick volumeBrick : volume.getBricks()) { + if ( device.getQualifiedBrickName(volume.getName()).equals(volumeBrick.getQualifiedName())) { + return true; + } + } + return false; + } + + protected List getAvailableDevices(Volume volume) { + List availableDevices = new ArrayList(); + for (Device device : GlusterDataModelManager.getInstance().getReadyDevicesOfAllServers()) { + if ( ! isDeviceUsed(volume, device) ) { + availableDevices.add(device); + } + } + return availableDevices; + } + + public Set getChosenDevices() { + return new HashSet(page.getChosenDevices()); + } + + public Set getChosenBricks( String volumeName ) { + return page.getChosenBricks(volumeName); + } + + private boolean isValidDiskSelection(int diskCount) { + if ( diskCount == 0) { + return false; + } + switch (volume.getVolumeType()) { + case DISTRIBUTED_MIRROR: + return (diskCount % volume.getReplicaCount() == 0); + case DISTRIBUTED_STRIPE: + return (diskCount % volume.getStripeCount() == 0); + } + return true; + } + + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createControl(Composite parent) { + getShell().setText("Add Brick"); + List chosenDevices = new ArrayList(); // or volume.getDisks(); + + page = new BricksSelectionPage(parent, SWT.NONE, availableDevices, chosenDevices, volume.getName()); + page.addDiskSelectionListener(new ListContentChangedListener() { + @Override + public void listContentChanged(IRemovableContentProvider contentProvider) { + List newChosenDevices = page.getChosenDevices(); + + // validate chosen disks + if(isValidDiskSelection(newChosenDevices.size())) { + clearError(); + } else { + setError(); + } + } + }); + setControl(page); + } + + private void setError() { + String errorMessage = null; + if ( volume.getVolumeType() == VOLUME_TYPE.PLAIN_DISTRIBUTE) { + errorMessage = "Please select at least one brick!"; + } else if( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + errorMessage = "Please select bricks in multiples of " + volume.getReplicaCount(); + } else { + errorMessage = "Please select bricks in multiples of " + volume.getStripeCount(); + } + + setPageComplete(false); + setErrorMessage(errorMessage); + } + + private void clearError() { + setErrorMessage(null); + setPageComplete(true); + } + + public BricksSelectionPage getDialogPage() { + return this.page; + } + + public void setPageComplete() { + + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickWizard.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickWizard.java new file mode 100644 index 00000000..734dd5e4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/AddBrickWizard.java @@ -0,0 +1,96 @@ +/** + * AddDiskWizard.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.dialogs; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.StringUtil; + +/** + * + */ +public class AddBrickWizard extends Wizard { + private AddBrickPage page; + private Volume volume; + + public AddBrickWizard(Volume volume) { + setWindowTitle("Gluster Management Console - Add Brick"); + setHelpAvailable(false); // TODO: Introduce wizard help + this.volume = volume; + } + + public void addPages() { + page = new AddBrickPage(volume); + addPage(page); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + Set bricks = page.getChosenBricks(volume.getName()); + VolumesClient volumeClient = new VolumesClient(); + try { + Set brickList = getBrickList(bricks); + + volumeClient.addBricks(volume.getName(), brickList); + + // Update model with new bricks in the volume + GlusterDataModelManager.getInstance().addBricks(volume, bricks); + + MessageDialog.openInformation(getShell(), "Add brick(s) to Volume", "Volume [" + volume.getName() + + "] is expanded with bricks [" + StringUtil.collectionToString(brickList, ", ") + "]"); + return true; + } catch (Exception e) { + MessageDialog.openError(getShell(), "Add brick(s) to Volume", e.getMessage()); + return false; + } + } + + private Set getBrickList(Set bricks) { + Set brickList = new HashSet(); + for(Brick brick : bricks) { + brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); + } + return brickList; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#canFinish() + */ + @Override + public boolean canFinish() { + return super.canFinish() && page.isPageComplete(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/BricksSelectionPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/BricksSelectionPage.java new file mode 100644 index 00000000..5ec12a74 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/BricksSelectionPage.java @@ -0,0 +1,334 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.TableLabelProviderAdapter; +import com.gluster.storage.management.console.utils.EntityViewerFilter; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.richclientgui.toolbox.duallists.CustomTableDualListComposite; +import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; +import com.richclientgui.toolbox.duallists.IRemovableContentProvider; +import com.richclientgui.toolbox.duallists.RemovableContentProvider; +import com.richclientgui.toolbox.duallists.TableColumnData; + +public class BricksSelectionPage extends Composite { + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, BRICK_DIRECTORY, FREE_SPACE, TOTAL_SPACE + } + + private static final String[] DISK_TABLE_COLUMNS_NAMES = { "Server", "Brick Directory", "Free Space (GB)", + "Total Space (GB)" }; + + private GUIHelper guiHelper = GUIHelper.getInstance(); + private CustomTableDualListComposite dualTableViewer; + private Text filterText; + // This list keeps track of the order of the disks as user changes the same by clicking on up/down arrow buttons + private List chosenDevices = new ArrayList(); + + private IRemovableContentProvider chosenBricksContentProvider; + + private Button btnUp; + + private Button btnDown; + + public BricksSelectionPage(final Composite parent, int style, List allDevices, List selectedDevices, + String volumeName) { + super(parent, style); + + createPage(allDevices, selectedDevices, volumeName); + + parent.layout(); + } + + public void addDiskSelectionListener(ListContentChangedListener listener) { + dualTableViewer.addChosenListChangedSelectionListener(listener); + } + + private TableLabelProviderAdapter getDiskLabelProvider(final String volumeName) { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Device)) { + return null; + } + + Device device = (Device) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? device.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.BRICK_DIRECTORY.ordinal() ? device.getMountPoint() + + "/" + volumeName + : columnIndex == DISK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? NumberUtil + .formatNumber((device.getFreeSpace() / 1024)) + : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil + .formatNumber((device.getSpace() / 1024)) : "Invalid"); + } + }; + } + + private int indexOf(List disks, Disk searchDisk) { + for (Disk disk : disks) { + if (disk.getQualifiedName().equals(searchDisk.getQualifiedName())) { + return disks.indexOf(disk); + } + } + return -1; + } + + private void createPage(List allDevice, List selectedDevice, String volumeName) { + setupPageLayout(); + + filterText = guiHelper.createFilterText(this); + new Label(this, SWT.NONE); + + createDualTableViewer(allDevice, selectedDevice, volumeName); + createFilter(filterText, false); // attach filter text to the dual table viewer for auto-filtering + + Composite buttonContainer = new Composite(this, SWT.NONE); + buttonContainer.setLayout(new GridLayout(1, false)); + GridData buttonContainerData = new GridData(SWT.FILL, SWT.CENTER, true, true); + buttonContainerData.minimumWidth = 40; + buttonContainer.setLayoutData(buttonContainerData); + + btnUp = new Button(buttonContainer, SWT.TOGGLE); + GridData btnUpData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); + btnUpData.minimumWidth = 30; + btnUp.setLayoutData(btnUpData); + btnUp.setImage(guiHelper.getImage(IImageKeys.ARROW_UP_16x16)); + btnUp.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + chosenDevices = getChosenDevices(); + List selectedDevices = getSelectedChosenDevices(); + + chosenBricksContentProvider.removeElements(chosenDevices); + for (Device device : selectedDevices) { + int index = chosenDevices.indexOf(device); + Device deviceAbove = chosenDevices.get(index - 1); + chosenDevices.set(index - 1, device); + chosenDevices.set(index, deviceAbove); + } + chosenBricksContentProvider.addElements(chosenDevices); + dualTableViewer.refreshChosenViewer(); + updateButtons(); + } + }); + + btnDown = new Button(buttonContainer, SWT.TOGGLE); + btnDown.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false)); + btnDown.setImage(guiHelper.getImage(IImageKeys.ARROW_DOWN_16x16)); + btnDown.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + + chosenDevices = getChosenDevices(); + List selectedDevices = getSelectedChosenDevices(); + + chosenBricksContentProvider.removeElements(chosenDevices); + for (Device disk : selectedDevices) { + int index = chosenDevices.indexOf(disk); + Device deviceBelow = chosenDevices.get(index + 1); + chosenDevices.set(index + 1, disk); + chosenDevices.set(index, deviceBelow); + } + chosenBricksContentProvider.addElements(chosenDevices); + dualTableViewer.refreshChosenViewer(); + updateButtons(); + + } + }); + } + + private List getSelectedChosenDevices() { + TableItem[] selectedItems = dualTableViewer.getChosenTable().getSelection(); + List selectedDevices = new ArrayList(); + for (TableItem item : selectedItems) { + selectedDevices.add((Device) item.getData()); + } + return selectedDevices; + } + + private void createFilter(final Text filterText, boolean caseSensitive) { + final String initialFilterString = filterText.getText(); + + final EntityViewerFilter filter = new EntityViewerFilter(initialFilterString, caseSensitive); + // On every keystroke inside the text field, update the filter string + filterText.addKeyListener(new KeyAdapter() { + private String filterString = initialFilterString; + + @Override + public void keyReleased(KeyEvent e) { + String enteredString = filterText.getText(); + if (enteredString.equals(filterString)) { + // Filter string has not changed. don't do anything + return; + } + + // Update filter string + filterString = enteredString; + filter.setFilterString(filterString); + + // Refresh viewer with newly filtered content + dualTableViewer.refreshAvailableViewer(); + dualTableViewer.refreshChosenViewer(); + } + }); + + dualTableViewer.setAvailableViewerFilter(filter); + dualTableViewer.setChosenViewerFilter(filter); + } + + private void createDualTableViewer(List allDevices, List selectedDevices, String volumeName) { + TableColumnData[] columnData = createColumnData(); + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(volumeName); + + dualTableViewer = new CustomTableDualListComposite(this, SWT.NONE, columnData, columnData); + + dualTableViewer.setViewerLabels("Available:", "Selected:"); + + dualTableViewer.setAvailableTableLinesVisible(false); + dualTableViewer.setAvailableTableHeaderVisible(true); + dualTableViewer.setAvailableContentProvider(new RemovableContentProvider(getAvailableDevice(allDevices, + selectedDevices))); + dualTableViewer.setAvailableLabelProvider(diskLabelProvider); + + dualTableViewer.setChosenTableLinesVisible(true); + dualTableViewer.setChosenTableHeaderVisible(true); + + chosenBricksContentProvider = new RemovableContentProvider(selectedDevices); + dualTableViewer.setChosenContentProvider(chosenBricksContentProvider); + dualTableViewer.setChosenLabelProvider(diskLabelProvider); + + dualTableViewer.getChosenTable().addSelectionListener(new SelectionAdapter() { + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(SelectionEvent e) { + updateButtons(); + } + }); + } + + private void updateButtons() { + btnUp.setEnabled(true); + btnDown.setEnabled(true); + List selectedChosenDevices = getSelectedChosenDevices(); + List chosenDevices = getChosenDevices(); + for (Device device : selectedChosenDevices) { + int index = chosenDevices.indexOf(device); + if (index == 0) { + btnUp.setEnabled(false); + } + if (index == chosenDevices.size() - 1) { + btnDown.setEnabled(false); + } + } + } + + /** + * @param allDevices + * @param selectedDevices + * @return + */ + private List getAvailableDevice(List allDevices, List selectedDevices) { + List availableDevices = new ArrayList(); + for (Device device : allDevices) { + if (!selectedDevices.contains(device)) { + availableDevices.add(device); + } + } + return availableDevices; + } + + private TableColumnData[] createColumnData() { + DISK_TABLE_COLUMN_INDICES[] columns = DISK_TABLE_COLUMN_INDICES.values(); + TableColumnData[] columnData = new TableColumnData[columns.length]; + int columnNum; + for (DISK_TABLE_COLUMN_INDICES column : columns) { + columnNum = column.ordinal(); + columnData[columnNum] = new TableColumnData(columnNum, DISK_TABLE_COLUMNS_NAMES[columnNum], 100); + } + return columnData; + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + + setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + public List getChosenDevices() { + Object[] devicesArr = (Object[]) chosenBricksContentProvider.getElements(dualTableViewer); + if (devicesArr != null) { + List devices = new ArrayList(); + for (Object device : devicesArr) { + devices.add((Device) device); + } + return devices; + } + return null; + } + + public Set getChosenBricks(String volumeName) { + Object[] bricksArr = (Object[]) chosenBricksContentProvider.getElements(dualTableViewer); + + if (bricksArr != null) { + Set bricks = new HashSet(); + for (Object device : bricksArr) { + bricks.add(new Brick(((Device) device).getServerName(), BRICK_STATUS.ONLINE, ((Device) device) + .getMountPoint() + "/" + volumeName)); // Assumption mount point is not having trailing "/" + } + return bricks; + } + return null; + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ChangePasswordDialog.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ChangePasswordDialog.java new file mode 100644 index 00000000..1576ffe3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ChangePasswordDialog.java @@ -0,0 +1,284 @@ +/** + * ChangePasswordDialog.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.dialogs; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.PojoProperties; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.client.UsersClient; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.validators.StringRequiredValidator; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.ConnectionDetails; + +public class ChangePasswordDialog extends Dialog { + public static final int RETURN_CODE_ERROR = 2; + private Text oldPassword; + private Text newPassword; + private Text confirmPassword; + private Button okButton; + + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Composite composite; + + private final ConnectionDetails connectionDetails = new ConnectionDetails("gluster", ""); + + public ChangePasswordDialog(Shell shell) { + super(shell); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 2; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + // ------------------------------------------ + + private void createLabel(Composite composite, String label) { + Label passwordLabel = new Label(composite, SWT.NONE); + passwordLabel.setText(label); + passwordLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private Text createPasswordText(Composite composite) { + Text field = new Text(composite, SWT.BORDER | SWT.PASSWORD); + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + layoutData.widthHint = convertWidthInCharsToPixels(32); + field.setLayoutData(layoutData); + return field; + } + + @Override + protected Control createDialogArea(Composite parent) { + // parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE)); + parent.setBackgroundMode(SWT.INHERIT_FORCE); + + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + + createLabel(composite, "Old Password:"); + oldPassword = createPasswordText(composite); + + createLabel(composite, "New Password:"); + newPassword = createPasswordText(composite); + + createLabel(composite, "Confirm Password:"); + confirmPassword = createPasswordText(composite); + + createListeners(); + + return composite; + } + + /** + * + */ + private void createListeners() { + ModifyListener listener = new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + updateButtonStatus(); + } + }; + + oldPassword.addModifyListener(listener); + newPassword.addModifyListener(listener); + confirmPassword.addModifyListener(listener); + } + + private void updateButtonStatus() { + String oldPwd = oldPassword.getText(); + String newPwd = newPassword.getText(); + String confirmPwd = confirmPassword.getText(); + if(oldPwd.isEmpty() || newPwd.isEmpty() || confirmPwd.isEmpty()) { + okButton.setEnabled(false); + return; + } + + if(!newPwd.equals(confirmPwd)) { + okButton.setEnabled(false); + return; + } + + if (confirmPwd.equals(CoreConstants.DEFAULT_PASSWORD) || isContainsWhiteSpace(confirmPwd)) { + okButton.setEnabled(false); + return; + } + + if (newPwd.length() < 4 ) { // Minimum password length is 4 + okButton.setEnabled(false); + return; + } + + okButton.setEnabled(true); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + okButton = createButton(parent, IDialogConstants.OK_ID, "&Change", true); + okButton.setEnabled(false); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + + setupDataBinding(); + } + + public boolean isContainsWhiteSpace(String text) { + return text.matches(".*[\\s\\\\].*"); // White space or backslash + } + + public class ConfirmPasswordValidator extends StringRequiredValidator { + public ConfirmPasswordValidator(String errorText, ControlDecoration controlDecoration, Control linkedControl) { + super(errorText, controlDecoration, linkedControl); + } + + @Override + public IStatus validate(Object value) { + + IStatus status = super.validate(value); + if (status.isOK()) { + String errMsg = null; + if (errMsg == null && isContainsWhiteSpace( newPassword.getText())) { + errMsg = "Password should not contain space or back slash characters"; + } + + if (!value.equals(newPassword.getText())) { + errMsg = "Passwords mismatched"; + } + + if (errMsg == null && value.equals(CoreConstants.DEFAULT_PASSWORD)) { + errMsg = "New password should not be a default password"; + } + + if(errMsg != null) { + controlDecoration.setDescriptionText(errMsg); + controlDecoration.show(); + linkedControl.setEnabled(false); + return ValidationStatus.error(errMsg); + } + } + return status; + } + }; + + private void setupDataBinding() { + DataBindingContext dataBindingContext = new DataBindingContext(SWTObservables.getRealm(Display.getCurrent())); + UpdateValueStrategy passwordBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + UpdateValueStrategy newPwdBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + UpdateValueStrategy confirmPwdBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + + // The Validator shows error decoration and disables OK button on + // validation failure + passwordBindingStrategy.setBeforeSetValidator(new StringRequiredValidator("Please enter old password!", + guiHelper.createErrorDecoration(oldPassword), null)); + + dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(oldPassword), + PojoProperties.value("password").observe(connectionDetails), passwordBindingStrategy, + passwordBindingStrategy); + + newPwdBindingStrategy.setBeforeSetValidator(new StringRequiredValidator("Please enter new password!", guiHelper + .createErrorDecoration(newPassword), null)); + + dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(newPassword), + PojoProperties.value("newPassword").observe(connectionDetails), newPwdBindingStrategy, + newPwdBindingStrategy); + + confirmPwdBindingStrategy.setBeforeSetValidator(new ConfirmPasswordValidator("Please enter confirm password!", + guiHelper.createErrorDecoration(confirmPassword), null)); + + dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(confirmPassword), + PojoProperties.value("confirmNewPassword").observe(connectionDetails), confirmPwdBindingStrategy, + confirmPwdBindingStrategy); + } + + protected void okPressed() { + String user = connectionDetails.getUserId(); + String oldPassword = connectionDetails.getPassword(); + String newPassword = connectionDetails.getNewPassword(); + + UsersClient usersClient = new UsersClient(); + try { + usersClient.changePassword(user, oldPassword, newPassword); + MessageDialog.openInformation(getShell(), "Change password", "Password changed successfully!"); + this.close(); + } catch (Exception e) { + MessageDialog.openError(getShell(), "Change password Failed", e.getMessage()); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ClusterSelectionDialog.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ClusterSelectionDialog.java new file mode 100644 index 00000000..ac510f5e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ClusterSelectionDialog.java @@ -0,0 +1,441 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.console.Activator; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.console.utils.GUIHelper; + +/** + * Cluster selection dialog, which prompts for the cluster name to be managed + */ +public class ClusterSelectionDialog extends Dialog { + protected enum CLUSTER_MODE { SELECT, CREATE, REGISTER }; + + private Combo clusterNameCombo = null; + private Text newClusterNameText = null; + private Text existingClusterNameText = null; + private Text serverNameText = null; + private Button okButton; + + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Composite composite; + private ControlDecoration newClusterNameErrorDecoration; + private ControlDecoration existingClusterNameErrorDecoration; + private ControlDecoration serverNameErrorDecoration; + private List clusters; + private Button selectButton; + private Button createButton; + private Button registerButton; + private Composite clusterSelectionComposite; + private Composite clusterCreationComposite; + private Composite clusterRegisterComposite; + private StackLayout stackLayout; + + private String clusterName; + private CLUSTER_MODE clusterMode; + private String serverName; + private Button dontAskAgainButton; + IPreferenceStore preferenceStore; + + public ClusterSelectionDialog(Shell parentShell, List clusters) { + super(parentShell); + this.clusters = clusters; + preferenceStore = Activator.getDefault().getPreferenceStore(); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console - Select Cluster"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + private void createClusterNameLabel(Composite composite) { + Label clusterNameLabel = new Label(composite, SWT.NONE); + clusterNameLabel.setText("Cluster &Name:"); + clusterNameLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createClusterNameCombo(Composite composite) { + clusterNameCombo = new Combo(composite, SWT.READ_ONLY); + clusterNameCombo.setItems(clusters.toArray(new String[0])); + clusterNameCombo.select(0); + + String clusterName = preferenceStore.getString(PreferenceConstants.P_DEFAULT_CLUSTER_NAME); + if(clusterName != null && !clusterName.isEmpty()) { + selectCluster(clusterName); + } + } + + public void selectCluster(String clusterName) { + for(int i = 0; i < clusters.size(); i++) { + if(clusterNameCombo.getItem(i).equals(clusterName)) { + clusterNameCombo.select(i); + break; + } + } + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 3; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + @Override + protected Control createDialogArea(Composite parent) { + //parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE)); + // Makes sure that child composites inherit the same background + parent.setBackgroundMode(SWT.INHERIT_FORCE); + + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + + createRadioButtons(); + createSubComposites(); + + return composite; + } + + private void createSubComposites() { + Composite subComposite = new Composite(composite, SWT.NONE); + GridData data = new GridData(); + data.horizontalSpan = 3; + subComposite.setLayoutData(data); + stackLayout = new StackLayout(); + subComposite.setLayout(stackLayout); + + createClusterSelectionComposite(subComposite, stackLayout); + createClusterCreationComposite(subComposite); + createClusterRegisterComposite(subComposite); + + createRadioButtonListeners(subComposite); + if(clusters.size() > 0) { + selectButton.setSelection(true); + stackLayout.topControl = clusterSelectionComposite; + clusterNameCombo.setFocus(); + } else { + createButton.setSelection(true); + stackLayout.topControl = clusterCreationComposite; + newClusterNameText.setFocus(); + } + subComposite.layout(); + } + + private void createClusterRegisterComposite(Composite composite) { + clusterRegisterComposite = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.horizontalSpacing = 15; + clusterRegisterComposite.setLayout(layout); + + createClusterNameLabel(clusterRegisterComposite); + existingClusterNameText = createText(clusterRegisterComposite); + existingClusterNameText.setToolTipText("Enter a name for the cluster being registered."); + existingClusterNameErrorDecoration = createErrorDecoration(existingClusterNameText, "Please enter a cluster name!"); + existingClusterNameErrorDecoration.show(); + + createClusterServerLabel(clusterRegisterComposite); + serverNameText = createText(clusterRegisterComposite); + serverNameText.setToolTipText("Enter host name / IP address of one of the servers of the cluster."); + serverNameErrorDecoration = createErrorDecoration(serverNameText, "Please enter a server name!"); + serverNameErrorDecoration.show(); + } + + private void createClusterServerLabel(Composite composite) { + Label serverNameLabel = new Label(composite, SWT.NONE); + serverNameLabel.setText("Server Na&me:"); + serverNameLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createClusterCreationComposite(Composite subComposite) { + clusterCreationComposite = new Composite(subComposite, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.horizontalSpacing = 15; + clusterCreationComposite.setLayout(layout); + + createClusterNameLabel(clusterCreationComposite); + newClusterNameText = createText(clusterCreationComposite); + newClusterNameText.setToolTipText("Enter name of the cluster to be created"); + newClusterNameErrorDecoration = createErrorDecoration(newClusterNameText, "Please enter cluster name!"); + newClusterNameErrorDecoration.show(); + } + + private Text createText(Composite parent) { + Text text = new Text(parent, SWT.NONE); + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + int width = convertWidthInCharsToPixels(32); + layoutData.widthHint = width; + layoutData.minimumWidth = width; + text.setLayoutData(layoutData); + + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validate(); + } + }); + + return text; + } + + private void createClusterSelectionComposite(Composite subComposite, StackLayout stackLayout) { + clusterSelectionComposite = new Composite(subComposite, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + clusterSelectionComposite.setLayout(layout); + createClusterNameLabel(clusterSelectionComposite); + createClusterNameCombo(clusterSelectionComposite); + + createPreferenceCheckboxes(clusterSelectionComposite); + + stackLayout.topControl = clusterSelectionComposite; + } + + private void createPreferenceCheckboxes(Composite composite) { + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, false); + layoutData.verticalIndent = 5; + layoutData.horizontalSpan = 2; + + dontAskAgainButton = new Button(composite, SWT.CHECK); + dontAskAgainButton.setLayoutData(layoutData); + dontAskAgainButton.setText("&Don't ask again"); + dontAskAgainButton.setEnabled(true); + dontAskAgainButton.setSelection(false); + dontAskAgainButton.setToolTipText("Always manage the selected cluster without showing this dialog box." + + "This preference can later be changed from the \"Settings\" menu."); + } + + private void createRadioButtons() { + { + if (clusters.size() > 0) { + selectButton = new Button(composite, SWT.RADIO); + selectButton.setText("&Select"); + } + } + { + createButton = new Button(composite, SWT.RADIO); + createButton.setText("&Create"); + } + { + registerButton = new Button(composite, SWT.RADIO); + registerButton.setText("&Register"); + } + } + + private void validate() { + okButton.setEnabled(false); + + if(selectButton != null && selectButton.getSelection()) { + okButton.setEnabled(true); + return; + } + + if(createButton.getSelection()) { + String newClusterName = newClusterNameText.getText().trim(); + if(newClusterName.isEmpty()) { + newClusterNameErrorDecoration.setDescriptionText("Please enter a cluster name!"); + newClusterNameErrorDecoration.show(); + } else if(clusters.contains(newClusterName)) { + newClusterNameErrorDecoration.setDescriptionText("Cluster [" + newClusterName + "] already exists!"); + newClusterNameErrorDecoration.show(); + } else { + okButton.setEnabled(true); + newClusterNameErrorDecoration.hide(); + } + } + + if(registerButton.getSelection()) { + okButton.setEnabled(true); + String clusterName = existingClusterNameText.getText().trim(); + if(existingClusterNameText.getText().trim().isEmpty()) { + existingClusterNameErrorDecoration.setDescriptionText("Please enter a cluster name!"); + existingClusterNameErrorDecoration.show(); + okButton.setEnabled(false); + } else if(clusters.contains(clusterName)) { + existingClusterNameErrorDecoration.setDescriptionText("Cluster [" + clusterName + "] already exists!"); + existingClusterNameErrorDecoration.show(); + okButton.setEnabled(false); + } else { + existingClusterNameErrorDecoration.hide(); + } + + if(serverNameText.getText().trim().isEmpty()) { + serverNameErrorDecoration.show(); + okButton.setEnabled(false); + } else { + serverNameErrorDecoration.hide(); + } + } + } + + private void createRadioButtonListeners(final Composite parent) { + if (clusters.size() > 0) { + selectButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + stackLayout.topControl = clusterSelectionComposite; + clusterNameCombo.select(0); + validate(); + parent.layout(); + clusterNameCombo.setFocus(); + } + }); + } + createButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + stackLayout.topControl = clusterCreationComposite; + validate(); + parent.layout(); + newClusterNameText.setFocus(); + } + }); + registerButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + stackLayout.topControl = clusterRegisterComposite; + validate(); + parent.layout(); + existingClusterNameText.setFocus(); + } + }); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + + setupDataBinding(); + } + + private ControlDecoration createErrorDecoration(Text text, String message) { + ControlDecoration errorDecoration = guiHelper.createErrorDecoration(text); + errorDecoration.setDescriptionText(message); + errorDecoration.hide(); + return errorDecoration; + } + + /** + * Sets up data binding between the text fields and the connection details object. Also attaches a "string required" + * validator to the "password" text field. This validator is configured to do the following on validation failure
+ *
  • show an ERROR decorator
  • disable the "Login" button + */ + private void setupDataBinding() { + clusterNameCombo.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + if(clusterNameCombo.getText().trim().isEmpty()) { + okButton.setEnabled(false); + newClusterNameErrorDecoration.show(); + } else { + okButton.setEnabled(true); + newClusterNameErrorDecoration.hide(); + } + } + }); + } + + @Override + protected void okPressed() { + if(selectButton != null && selectButton.getSelection()) { + clusterMode = CLUSTER_MODE.SELECT; + clusterName = clusterNameCombo.getText(); + + if(dontAskAgainButton.getSelection()) { + preferenceStore.setValue(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, false); + preferenceStore.setValue(PreferenceConstants.P_DEFAULT_CLUSTER_NAME, clusterName); + } else { + preferenceStore.setValue(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, true); + } + } else if(createButton.getSelection()) { + clusterMode = CLUSTER_MODE.CREATE; + clusterName = newClusterNameText.getText().trim(); + } else if(registerButton.getSelection()) { + clusterMode = CLUSTER_MODE.REGISTER; + clusterName = existingClusterNameText.getText().trim(); + serverName = serverNameText.getText().trim(); + } + super.okPressed(); + } + + public String getClusterName() { + return clusterName; + } + + public CLUSTER_MODE getClusterMode() { + return clusterMode; + } + + public String getServerName() { + return serverName; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumePage1.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumePage1.java new file mode 100644 index 00000000..fa240a11 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumePage1.java @@ -0,0 +1,479 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.ValidationUtil; + +public class CreateVolumePage1 extends WizardPage { + public static final String PAGE_NAME = "create.volume.page.1"; + private Text txtName; + private ComboViewer typeComboViewer; + private Text txtAccessControl; + private Text txtCifsUsers; + private Volume volume = new Volume(); + private Button btnNfs; + private Button btnCIFS; + private Button btnStartVolume; + private Link linkCustomize; + private List allDevices; + private List selectedDevices; + + /** + * Create the wizard. + */ + public CreateVolumePage1() { + super(PAGE_NAME); + setTitle("Create Volume"); + setDescription("Create a new Volume by choosing bricks from the cluster servers and configuring the volume properties."); + + // by default, we create volume with all available disks + allDevices = GlusterDataModelManager.getInstance().getReadyDevicesOfAllServers(); + selectedDevices = allDevices; // volume.setDisks(allDisks); + } + + private List getBricks(List allDisks) { + List disks = new ArrayList(); + for(Disk disk: allDisks) { + disks.add(disk.getServerName() + ":" + disk.getName()); + } + return disks; + } + + /** + * Create contents of the wizard. + * @param parent + */ + public void createControl(Composite parent) { + setPageComplete(false); + Composite container = createContainer(parent); + + createEmptyRow(container); + + createNameLabel(container); + createNameText(container); + + createTypeLabel(container); + createTypeCombo(container); + +// createTransportTypeLabel(container); +// createTransportTypeValueLabel(container); + + createDisksLabel(container); + createDisksCustomizeLink(container); + + createNasProtocolLabel(container); + createNasProtocolCheckboxes(container); + + createCifsUserLabel(container); + createCifsUserText(container); + + createEmptyLabel(container); + createCifsUserInfoLabel(container); + + createAccessControlLabel(container); + createAccessControlText(container); + + createEmptyLabel(container); + createAccessControlInfoLabel(container); + + createStartVolumeLabel(container); + createStartVolumeCheckbox(container); + } + + private void createStartVolumeCheckbox(Composite container) { + btnStartVolume = new Button(container, SWT.CHECK); + btnStartVolume.setSelection(true); + } + + private void createStartVolumeLabel(Composite container) { + Label lblStartVolume = new Label(container, SWT.NONE); + lblStartVolume.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblStartVolume.setText("Start Volume: "); + } + + private void createCifsUserInfoLabel(Composite container) { + Label lblCifsUserInfo = new Label(container, SWT.TOP); + lblCifsUserInfo.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); + lblCifsUserInfo.setText("(Comma separated list user names)"); + } + + private void createAccessControlInfoLabel(Composite container) { + Label lblAccessControlInfo = new Label(container, SWT.TOP); + lblAccessControlInfo.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); + lblAccessControlInfo.setText("(Comma separated list of IP addresses/hostnames)"); + } + + private void createEmptyLabel(Composite container) { + new Label(container, SWT.NONE); + } + + private void createAccessControlText(Composite container) { + txtAccessControl = new Text(container, SWT.BORDER); + txtAccessControl.setText("*"); + GridData accessControlData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + accessControlData.widthHint = 300; + txtAccessControl.setLayoutData(accessControlData); + txtAccessControl.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateForm(); + } + }); + } + + private void createAccessControlLabel(Composite container) { + Label lblAccessControl = new Label(container, SWT.NONE); + lblAccessControl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblAccessControl.setText("Access Control: "); + } + + private void createCifsUserLabel(Composite container) { + Label lblAccessControl = new Label(container, SWT.NONE); + lblAccessControl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblAccessControl.setText("CIFS Users: "); + } + + private void createCifsUserText(Composite container) { + txtCifsUsers = new Text(container, SWT.BORDER); +// txtCifsUsers.setText("testuser1,testuser2,testuser3"); + GridData cifsControlData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + cifsControlData.widthHint = 300; + txtCifsUsers.setLayoutData(cifsControlData); + txtCifsUsers.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + validateForm(); + } + }); + } + + private void createNasProtocolCheckboxes(Composite container) { + Button btnGluster = new Button(container, SWT.CHECK); + btnGluster.setEnabled(false); + btnGluster.setSelection(true); + btnGluster.setText("Gluster"); + createEmptyLabel(container); + + btnNfs = new Button(container, SWT.CHECK); + btnNfs.setEnabled(true); + btnNfs.setSelection(true); + btnNfs.setText("NFS"); + createEmptyLabel(container); + + btnCIFS = new Button(container, SWT.CHECK); + btnCIFS.setEnabled(true); + btnCIFS.setSelection(false); + btnCIFS.setText("CIFS"); + btnCIFS.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + validateForm(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + validateForm(); + } + }); + } + + private void createNasProtocolLabel(Composite container) { + Label lblNasProtocol = new Label(container, SWT.RIGHT); + lblNasProtocol.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblNasProtocol.setText("Access Protocol: "); + } + + private void createDisksCustomizeLink(Composite container) { + linkCustomize = new Link(container, SWT.UNDERLINE_LINK); + linkCustomize.setText("All Brick(s) (customize)" ); + linkCustomize.setEnabled(false); + linkCustomize.addListener (SWT.Selection, new Listener () { + public void handleEvent(Event event) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + SelectDisksDialog dialog = new SelectDisksDialog(getShell(), allDevices, selectedDevices, txtName.getText().trim()); + + dialog.create(); + if(dialog.open() == Window.OK) { + // user has customized disks. get them from the dialog box. + selectedDevices = dialog.getSelectedDevices(); + linkCustomize.setText("" + selectedDevices.size() + " Brick(s) (customize)"); + validateForm(); + } + } + }); + } + }); + } + + private void createDisksLabel(Composite container) { + Label lblDisks = new Label(container, SWT.RIGHT); + lblDisks.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblDisks.setText("Bricks: "); + } + + private void createTransportTypeValueLabel(Composite container) { + Label lblEthernet = new Label(container, SWT.NONE); + lblEthernet.setText("Ethernet"); + } + + private void createTransportTypeLabel(Composite container) { + Label lblTransportType = new Label(container, SWT.NONE); + lblTransportType.setText("Transport Type: "); + } + + private void createTypeCombo(Composite container) { + typeComboViewer = new ComboViewer(container, SWT.READ_ONLY); + Combo typeCombo = typeComboViewer.getCombo(); + GridData typeComboData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + typeCombo.setLayoutData(typeComboData); + typeComboViewer.setContentProvider(new ArrayContentProvider()); + typeComboViewer.setInput(Volume.VOLUME_TYPE.values()); + typeCombo.select(VOLUME_TYPE.PLAIN_DISTRIBUTE.ordinal()); // default type = Plain Distribute + typeComboViewer.setLabelProvider(new LabelProvider() { + @Override + public String getText(Object element) { + VOLUME_TYPE volumeType = (VOLUME_TYPE)element; + return Volume.getVolumeTypeStr(volumeType); + } + }); + typeComboViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + validateForm(); + } + }); + } + + private void createTypeLabel(Composite container) { + Label lblType = new Label(container, SWT.NONE); + lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblType.setText("Type: "); + } + + private void createNameText(Composite container) { + txtName = new Text(container, SWT.BORDER); + GridData txtNameData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + txtNameData.widthHint = 300; + txtName.setTextLimit(32); + txtName.setLayoutData(txtNameData); + txtName.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validateForm(); + } + }); + } + + private void createNameLabel(Composite container) { + Label lblName = new Label(container, SWT.NONE); + lblName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblName.setText("Name: "); + } + + private void createEmptyRow(Composite container) { + createEmptyLabel(container); + createEmptyLabel(container); + } + + private Composite createContainer(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + setControl(container); + + GridLayout gl_container = new GridLayout(2, false); + gl_container.verticalSpacing = 10; + gl_container.marginHeight = 10; + gl_container.marginLeft = 20; + gl_container.horizontalSpacing = 10; + container.setLayout(gl_container); + return container; + } + + public Volume getVolume() { + volume.setName(txtName.getText()); + + IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); + volume.setVolumeType((VOLUME_TYPE)selection.getFirstElement()); + + volume.setTransportType(TRANSPORT_TYPE.ETHERNET); // Support only for Ethernet + Set nasProtocols = new HashSet(); + nasProtocols.add(NAS_PROTOCOL.GLUSTERFS); + nasProtocols.add(NAS_PROTOCOL.NFS); + + volume.setAccessControlList(txtAccessControl.getText()); + + if (btnNfs.getSelection()) { + volume.enableNFS(); + } else { + volume.disableNFS(); + } + + if (btnCIFS.getSelection()) { + volume.enableCifs(); + volume.setCifsUsers(Arrays.asList(txtCifsUsers.getText().split(","))); + } else { + volume.disableCifs(); + } + + for (Device device : selectedDevices) { + Brick brick = new Brick(device.getServerName(), BRICK_STATUS.ONLINE, device.getMountPoint() + "/" + + volume.getName()); + volume.addBrick(brick); + } + + return volume; + } + + public Boolean startVolumeAfterCreation() { + return btnStartVolume.getSelection(); + } + + public Boolean volumeExists(String volumeName) { + List volumes = GlusterDataModelManager.getInstance().getModel().getCluster().getVolumes(); + for (Volume volume : volumes) { + if (volume.getName().equals(volumeName)) { + setErrorMessage("Volume name already exists."); + return false; + } + } + return true; + } + + private void validateForm() { + clearErrors(); + validateVolumeName(); + validateCifsUsers(); + validateAccessControl(); + validateDisks(); + } + + private void validateDisks() { + int diskCount = selectedDevices.size(); + + if(diskCount < 1) { + setError("At least one brick must be selected!"); + } + + VOLUME_TYPE volumeType = (VOLUME_TYPE) ((IStructuredSelection) typeComboViewer + .getSelection()).getFirstElement(); + if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR && diskCount % 2 != 0) { + setError("Mirror type volume requires bricks in multiples of two"); + } else if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE && diskCount % 4 != 0) { + setError("Stripe type volume requires bricks in multiples of four"); + } + } + + private void validateAccessControl() { + String accessControl = txtAccessControl.getText().trim(); + if (accessControl.length() == 0) { + setError("Please enter Access Control"); + return; + } + + if (!ValidationUtil.isValidAccessControl(accessControl)) { + setError("Access control list must be a comma separated list of IP addresses/Host names. Please enter a valid value!"); + } + } + + private void validateCifsUsers() { + if (btnCIFS.getSelection()) { + String cifsUserList = txtCifsUsers.getText().trim(); + if (cifsUserList.length() == 0) { + setError("Please enter cifs user name"); + return; + } + } + } + + private void validateVolumeName() { + String volumeName = txtName.getText().trim(); + String volumeNameToken = "^[a-zA-Z][a-zA-Z0-9\\-]*"; + + if (volumeName.length() > 0) { + linkCustomize.setEnabled(true); + } + + if(volumeName.length() == 0) { + setError("Please enter Volume Name"); + linkCustomize.setEnabled(false); + } + + if (!volumeName.matches(volumeNameToken)) { + setError("Please enter valid Volume Name"); + } + + if(!volumeExists(volumeName)) { + setError("Volume [" + volumeName + "] already exists!"); + } + } + + private void clearErrors() { + setErrorMessage(null); + setPageComplete(true); + } + + private void setError(String errorMsg) { + setPageComplete(false); + setErrorMessage(errorMsg); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumeWizard.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumeWizard.java new file mode 100644 index 00000000..2317db9c --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/CreateVolumeWizard.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class CreateVolumeWizard extends Wizard { + private static final String title = "Gluster Management Console - Create Volume"; + private CreateVolumePage1 page; + + public CreateVolumeWizard() { + setWindowTitle(title); + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + page = new CreateVolumePage1(); + addPage(page); + } + + @Override + public boolean performFinish() { + Volume newVolume = page.getVolume(); + VolumesClient volumesClient = new VolumesClient(); + + try { + volumesClient.createVolume(newVolume); + handleSuccess(newVolume, volumesClient); + } catch(Exception e) { + String errMsg = e.getMessage(); + // the error could be in to post-volume-create processing. check if this is the case. + if (volumesClient.volumeExists(newVolume.getName())) { + handlePartSuccess(newVolume, volumesClient, errMsg); + } else { + MessageDialog.openError(getShell(), title, "Volume creation failed! Error: " + errMsg); + return false; + } + } + + return true; + } + + public void handleSuccess(Volume newVolume, VolumesClient volumesClient) { + String message = "Volume created successfully!"; + newVolume.setStatus(VOLUME_STATUS.OFFLINE); + boolean warning = false; + if (page.startVolumeAfterCreation()) { + try { + volumesClient.startVolume(newVolume.getName()); + newVolume.setStatus(VOLUME_STATUS.ONLINE); + message = "Volume created and started successfully!"; + } catch(Exception e) { + message = "Volume created successfuly, but couldn't be started. Error: " + e.getMessage(); + warning = true; + } + } + + // update the model + GlusterDataModelManager.getInstance().addVolume(newVolume); + if (warning) { + MessageDialog.openWarning(getShell(), title, message); + } else { + MessageDialog.openInformation(getShell(), title, message); + } + } + + public void handlePartSuccess(Volume newVolume, VolumesClient volumesClient, String errMsg) { + // volume exists. error was in post-volume-create + newVolume.setStatus(VOLUME_STATUS.OFFLINE); + boolean error = false; + String message1 = null; + if (page.startVolumeAfterCreation()) { + if (MessageDialog.openConfirm(getShell(), title, "Volume created, but following error(s) occured: " + + errMsg + CoreConstants.NEWLINE + CoreConstants.NEWLINE + + "Do you still want to start the volume [" + newVolume.getName() + "]?")) { + try { + volumesClient.startVolume(newVolume.getName()); + newVolume.setStatus(VOLUME_STATUS.ONLINE); + message1 = "Volume [" + newVolume.getName() + "] started successfully!"; // Only start operation + } catch(Exception e1) { + message1 = "Volume couldn't be started. Error: " + e1.getMessage(); + error = true; + } + } + + if (error) { + MessageDialog.openWarning(getShell(), title, message1); + } else { + MessageDialog.openInformation(getShell(), title, message1); + } + } else { // Start volume is not checked + MessageDialog.openWarning(getShell(), title, + "Volume created, but following error(s) occured: " + errMsg); + } + GlusterDataModelManager.getInstance().addVolume(newVolume); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/InitializeDiskTypeSelection.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/InitializeDiskTypeSelection.java new file mode 100644 index 00000000..060e68ac --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/InitializeDiskTypeSelection.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * + * InitializeDiskTypeSelection.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.GlusterConstants; + +public class InitializeDiskTypeSelection extends Dialog { + + private Combo formatTypeCombo = null; + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Composite initializeDiskTypeComposite; + private Composite composite; + private String fsType; + + public InitializeDiskTypeSelection(Shell parentShell) { + super(parentShell); + // TODO Auto-generated constructor stub + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console - Select FS Type"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + @Override + protected Control createDialogArea(Composite parent) { + // Makes sure that child composites inherit the same background + parent.setBackgroundMode(SWT.INHERIT_FORCE); + + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + createComposite(composite); + return composite; + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 3; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + private void createComposite(Composite composite) { + initializeDiskTypeComposite = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + initializeDiskTypeComposite.setLayout(layout); + + createLabel(initializeDiskTypeComposite, "Format disk using "); + createFormatTypeCombo(initializeDiskTypeComposite); + createLabel(initializeDiskTypeComposite, " file system"); + } + + private void createLabel(Composite composite, String labelText) { + Label formatTypeLabel = new Label(composite, SWT.NONE); + formatTypeLabel.setText(labelText); + formatTypeLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createFormatTypeCombo(Composite composite) { + List fsType = new ArrayList(); + fsType.add(GlusterConstants.FSTYPE_DEFAULT); + fsType.add(GlusterConstants.FSTYPE_EXT_3); + fsType.add(GlusterConstants.FSTYPE_EXT_4); + fsType.add(GlusterConstants.FSTYPE_XFS); + formatTypeCombo = new Combo(composite, SWT.READ_ONLY); + formatTypeCombo.setItems(fsType.toArray(new String[0])); + formatTypeCombo.select(0); + } + + @Override + protected void okPressed() { + fsType = formatTypeCombo.getText(); + super.okPressed(); + } + + @Override + public void cancelPressed() { + super.cancelPressed(); + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + public String getFSType() { + return fsType.trim(); + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/LoginDialog.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/LoginDialog.java new file mode 100644 index 00000000..b2b647e1 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/LoginDialog.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.PojoProperties; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.client.ClustersClient; +import com.gluster.storage.management.client.UsersClient; +import com.gluster.storage.management.console.Activator; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.dialogs.ClusterSelectionDialog.CLUSTER_MODE; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.validators.StringRequiredValidator; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.ConnectionDetails; + +/** + * Login dialog, which prompts for the user's account info, and has Login and Cancel buttons. + */ +public class LoginDialog extends Dialog { + public static final int RETURN_CODE_ERROR = 2; + private Text userIdText = null; + private Text passwordText = null; + private Button okButton; + + private final ConnectionDetails connectionDetails = new ConnectionDetails("gluster", ""); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Composite composite; + + public LoginDialog(Shell parentShell) { + super(parentShell); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + private void createUserIdLabel(Composite composite) { + Label userIdLabel = new Label(composite, SWT.NONE); + userIdLabel.setText("&User ID:"); + userIdLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createUserIdText(Composite composite) { + userIdText = new Text(composite, SWT.BORDER); + userIdText.setText("gluster"); + userIdText.setEnabled(false); + + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + ; + layoutData.widthHint = convertWidthInCharsToPixels(32); + userIdText.setLayoutData(layoutData); + } + + private void createPasswordLabel(Composite composite) { + Label passwordLabel = new Label(composite, SWT.NONE); + passwordLabel.setText("&Password:"); + passwordLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createPasswordText(Composite composite) { + passwordText = new Text(composite, SWT.BORDER | SWT.PASSWORD); + + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + ; + layoutData.widthHint = convertWidthInCharsToPixels(32); + passwordText.setLayoutData(layoutData); + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 2; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + @Override + protected Control createDialogArea(Composite parent) { + parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE)); + parent.setBackgroundMode(SWT.INHERIT_FORCE); // Makes sure that child + // composites inherit + // the same background + + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + + createUserIdLabel(composite); + createUserIdText(composite); + + createPasswordLabel(composite); + createPasswordText(composite); + + return composite; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + okButton = createButton(parent, IDialogConstants.OK_ID, "&Login", true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + + setupDataBinding(); + } + + /** + * Sets up data binding between the text fields and the connection details object. Also attaches a "string required" + * validator to the "password" text field. This validator is configured to do the following on validation failure
    + *
  • show an ERROR decorator
  • disable the "Login" button + */ + private void setupDataBinding() { + DataBindingContext dataBindingContext = new DataBindingContext(SWTObservables.getRealm(Display.getCurrent())); + UpdateValueStrategy passwordBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + + // The Validator shows error decoration and disables OK button on + // validation failure + passwordBindingStrategy.setBeforeSetValidator(new StringRequiredValidator("Please enter password!", guiHelper + .createErrorDecoration(passwordText), okButton)); + + dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(passwordText), + PojoProperties.value("password").observe(connectionDetails), passwordBindingStrategy, + passwordBindingStrategy); + + UpdateValueStrategy userIdBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + dataBindingContext + .bindValue(WidgetProperties.text(SWT.Modify).observe(userIdText), PojoProperties.value("userId") + .observe(connectionDetails), userIdBindingStrategy, userIdBindingStrategy); + } + + protected void okPressed() { + String user = connectionDetails.getUserId(); + String password = connectionDetails.getPassword(); + + UsersClient usersClient = new UsersClient(); + try { + usersClient.authenticate(user, password); + } catch(Exception e) { + MessageDialog.openError(getShell(), "Authentication Failed", e.getMessage()); + setReturnCode(RETURN_CODE_ERROR); + return; + } + + // authentication successful. close the login dialog and open the next one. + close(); + + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + boolean showClusterSelectionDialog = preferenceStore.getBoolean(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG); + + // If the password is default, Let user to change the password + if (password.equalsIgnoreCase(CoreConstants.DEFAULT_PASSWORD)) { + String oldSecurityTokeString = GlusterDataModelManager.getInstance().getSecurityToken(); + ChangePasswordDialog dialog = new ChangePasswordDialog(getShell()); + + if (dialog.open() == Dialog.CANCEL) { + MessageDialog.openError(getShell(), "Change password Cancelled", + "Password must be changed on first login!" + CoreConstants.NEWLINE + "Application will close."); + cancelPressed(); + return; + } + + // after first login, cluster selection dialog must be shown. + showClusterSelectionDialog = true; + } + + ClustersClient clustersClient = new ClustersClient(); + + CLUSTER_MODE mode; + String clusterName = null; + if (!showClusterSelectionDialog) { + clusterName = preferenceStore.getString(PreferenceConstants.P_DEFAULT_CLUSTER_NAME); + if (clusterName == null || clusterName.isEmpty()) { + // Cluster name not available in preferences. Hence we must show the cluster selection dialog. + showClusterSelectionDialog = true; + } else { + mode = CLUSTER_MODE.SELECT; + } + } + + String serverName = null; + + if (showClusterSelectionDialog) { + ClusterSelectionDialog clusterDialog = new ClusterSelectionDialog(getParentShell(), + clustersClient.getClusterNames()); + int userAction = clusterDialog.open(); + if (userAction == Window.CANCEL) { + MessageDialog.openError(getShell(), "Login Cancelled", + "User cancelled login at cluster selection. Application will close!"); + cancelPressed(); + return; + } + mode = clusterDialog.getClusterMode(); + clusterName = clusterDialog.getClusterName(); + serverName = clusterDialog.getServerName(); + } else { + mode = CLUSTER_MODE.SELECT; + } + + try { + createOrRegisterCluster(clustersClient, clusterName, serverName, mode); + + final String clusterName1 = clusterName; + new ProgressMonitorDialog(getShell()).run(true, false, new IRunnableWithProgress() { + + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + GlusterDataModelManager.getInstance().initializeModel(clusterName1, monitor); + } + }); + super.okPressed(); + } catch (Exception e) { + String errMsg; + if(e instanceof InvocationTargetException) { + errMsg = ((InvocationTargetException) e).getTargetException().getMessage(); + } else { + errMsg = e.getMessage(); + } + setReturnCode(RETURN_CODE_ERROR); + MessageDialog.openError(getShell(), "Gluster Management Console", errMsg); + } + } + + public void createOrRegisterCluster(ClustersClient clustersClient, String clusterName, String serverName, + CLUSTER_MODE mode) { + switch (mode) { + case SELECT: + return; + case CREATE: + clustersClient.createCluster(clusterName); + break; + case REGISTER: + clustersClient.registerCluster(clusterName, serverName); + break; + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickPage1.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickPage1.java new file mode 100644 index 00000000..49d30d10 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickPage1.java @@ -0,0 +1,274 @@ +/** + * MigrateBrickPage1.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ + +package com.gluster.storage.management.console.dialogs; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.TableLabelProviderAdapter; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.NumberUtil; + +public class MigrateBrickPage1 extends WizardPage { + private static final String PAGE_NAME = "migrate.disk.page.1"; + + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, BRICK_DIRECTORY, FREE_SPACE, TOTAL_SPACE + } + + private static final String[] DISK_TABLE_COLUMN_NAMES = { "Server", "Brick Directory", "Free Space (GB)", "Total Space (GB)" }; + + private Volume volume; + private Brick fromBrick; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private TableViewer tableViewerTo; + + private TableViewer tableViewerFrom; + + private Button autoCompleteCheckbox; + + private ITableLabelProvider getDiskLabelProvider(final String volumeName) { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Device)) { + return null; + } + Device device = (Device) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? device.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.BRICK_DIRECTORY.ordinal() ? device.getMountPoint() + "/" + volumeName + : columnIndex == DISK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? NumberUtil.formatNumber(device.getFreeSpace() / 1024 ) /* Coverted to GB */ + : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil.formatNumber(device.getSpace() / 1024) : "Invalid"); + } + }; + } + + private void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SERVER, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.BRICK_DIRECTORY, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.FREE_SPACE, SWT.CENTER, 90); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE, SWT.CENTER, 90); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, DISK_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + /** + * Create the wizard. + */ + public MigrateBrickPage1(Volume volume, Brick brick) { + super(PAGE_NAME); + this.volume = volume; + this.fromBrick = brick; + setTitle("Migrate Brick [" + volume.getName() + "]"); + setPageDescription(null, null); + setPageComplete(false); + } + + private void setPageDescription(String source, String target) { + if (source == null || source == "") { + source = "From Brick"; + } + if (target == null || target == "") { + target = "To Brick"; + } + setDescription("Migrate volume data from \"" + source + "\" to \"" + target + "\""); + } + + private Device getSelectedDevice(TableViewer tableViewer) { + TableItem[] selectedItems = tableViewer.getTable().getSelection(); + Device selectedDevice = null; + for (TableItem item : selectedItems) { + selectedDevice = (Device) item.getData(); + } + return selectedDevice; + } + + private void setupPageLayout(Composite container) { + final GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + layout.horizontalSpacing = 10; + layout.marginTop = 10; + layout.marginLeft = 10; + layout.marginRight = 10; + container.setLayout(layout); + } + + private Composite createTableViewerComposite(Composite parent) { + Composite tableViewerComposite = new Composite(parent, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + public String getSourceBrickDir() { + Device sourceDevice = getSelectedDevice(tableViewerFrom); + return sourceDevice.getQualifiedBrickName(volume.getName()); + } + + public String getTargetBrickDir() { + Device targetDevice = getSelectedDevice(tableViewerTo); + return targetDevice.getQualifiedBrickName(volume.getName()); + } + + public Boolean getAutoCommitSelection() { + return autoCompleteCheckbox.getSelection(); + } + + /** + * Create contents of the wizard. + * + * @param parent + */ + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + setControl(container); + + setupPageLayout(container); + + GridData labelLayoutData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); + labelLayoutData.minimumWidth = 100; + labelLayoutData.verticalAlignment = SWT.BOTTOM; + //labelLayoutData.verticalIndent = 10; + + Label lblFromDisk = new Label(container, SWT.NONE); + lblFromDisk.setText("From Brick:"); + lblFromDisk.setLayoutData(labelLayoutData); + Label lblToDisk = new Label(container, SWT.NONE); + lblToDisk.setText("To Brick:"); + lblToDisk.setLayoutData(labelLayoutData); + + Text txtFilterFrom = guiHelper.createFilterText(container); + Text txtFilterTo = guiHelper.createFilterText(container); + + ITableLabelProvider deviceLabelProvider = getDiskLabelProvider(volume.getName()); + + GlusterDataModelManager glusterDataModelManager = GlusterDataModelManager.getInstance(); + List fromBricks = glusterDataModelManager.getReadyDevicesOfVolume(volume); + List toDevices = glusterDataModelManager.getReadyDevicesOfAllServersExcluding( fromBricks ); + + tableViewerFrom = createTableViewer(container, deviceLabelProvider, fromBricks, txtFilterFrom); + + if(fromBrick != null) { + setFromDisk(tableViewerFrom, fromBrick); + } + tableViewerTo = createTableViewer(container, deviceLabelProvider, toDevices, txtFilterTo); + + // Auto commit selection field + Composite autoCommitContainer = new Composite(container, SWT.NONE); + GridData data = new GridData(); + data.horizontalSpan = 2; + autoCommitContainer.setLayoutData(data); + autoCompleteCheckbox = new Button(autoCommitContainer, SWT.CHECK); + autoCompleteCheckbox.setSelection(true); + Label lblAutoComplete = new Label(autoCommitContainer, SWT.NONE); + lblAutoComplete.setText("Auto commit on migration complete"); + autoCommitContainer.setLayout( container.getLayout()); + } + + private void setFromDisk(TableViewer tableViewer, Brick brickToSelect) { + Table table = tableViewer.getTable(); + for (int i = 0; i < table.getItemCount(); i++) { + TableItem item = table.getItem(i); + if (item.getData() == brickToSelect) { + table.select(i); + return; + } + } + } + + private void refreshButtonStatus() { + if(tableViewerFrom.getSelection().isEmpty() || tableViewerTo.getSelection().isEmpty()) { + setPageComplete(false); + } else { + setPageComplete(true); + } + } + + private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, + List bricks, Text txtFilterText) { + Composite tableViewerComposite = createTableViewerComposite(container); + + TableViewer tableViewer = new TableViewer(tableViewerComposite, SWT.SINGLE); + tableViewer.setContentProvider(new ArrayContentProvider()); + tableViewer.setLabelProvider(diskLabelProvider); + + setupDiskTable(tableViewerComposite, tableViewer.getTable()); + guiHelper.createFilter(tableViewer, txtFilterText, false); + + tableViewer.setInput(bricks.toArray()); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + refreshButtonStatus(); + } + }); + return tableViewer; + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickWizard.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickWizard.java new file mode 100644 index 00000000..b52125c7 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/MigrateBrickWizard.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.net.URI; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; + +public class MigrateBrickWizard extends Wizard { + private Volume volume; + private Brick brick; + private MigrateBrickPage1 page; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private Cluster cluster = modelManager.getModel().getCluster(); + + public MigrateBrickWizard(Volume volume, Brick brick) { + setWindowTitle("Gluster Management Console - Migrate Brick [" + volume.getName() + "]"); + this.volume = volume; + this.brick = brick; + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + page = new MigrateBrickPage1(volume, brick); + addPage(page); + } + + @Override + public boolean performFinish() { + + String sourceDir = page.getSourceBrickDir(); + String targetDir = page.getTargetBrickDir(); + Boolean autoCommit = page.getAutoCommitSelection(); + VolumesClient volumesClient = new VolumesClient(); + String dialogTitle = "Brick migration"; + + try { + URI uri = volumesClient.startMigration(volume.getName(), sourceDir, targetDir, autoCommit); + + // To get the object + TasksClient taskClient = new TasksClient(); + TaskInfo taskInfo = taskClient.getTaskInfo(uri); + if (taskInfo != null && taskInfo instanceof TaskInfo) { + cluster.addTaskInfo(taskInfo); + modelManager.refreshVolumeData(cluster.getVolume(taskInfo.getReference())); + + // If auto commit selected and migration operation complete immediately, + if (taskInfo.getStatus().getCode() == TaskStatus.STATUS_CODE_SUCCESS) { + + String volumeName = taskInfo.getReference(); + Volume oldVolume = cluster.getVolume(volumeName); + Volume newVolume = (new VolumesClient()).getVolume(volumeName); + + modelManager.volumeChanged(oldVolume, newVolume); + + MessageDialog.openInformation(getShell(), dialogTitle, "Brick migration completed successfully"); + return true; + } + } + MessageDialog.openInformation(getShell(), dialogTitle, "Brick migration started successfully"); + + } catch (Exception e) { + MessageDialog.openError(getShell(), dialogTitle, "Brick Migration failed! [" + e.getMessage() + "]"); + } + return true; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/SelectDisksDialog.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/SelectDisksDialog.java new file mode 100644 index 00000000..5a5f6046 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/SelectDisksDialog.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.dialogs; + +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Device; + +public class SelectDisksDialog extends Dialog { + + private BricksSelectionPage disksPage; + private List allDevices; + private List selectedDevices; + private String volumeName; + + /** + * Create the dialog. + * + * @param parentShell + */ + public SelectDisksDialog(Shell parentShell, List allDevices, List selectedDevices, String volumeName) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + this.allDevices = allDevices; + this.selectedDevices = selectedDevices; + this.volumeName = volumeName; + } + + /** + * Create contents of the dialog. + * + * @param parent + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + GridLayout containerLayout = new GridLayout(2, false); + container.setLayout(containerLayout); + GridData containerLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + container.setLayoutData(containerLayoutData); + + getShell().setText("Create Volume - Select Bricks"); + + disksPage = new BricksSelectionPage(container, SWT.NONE, allDevices, selectedDevices, volumeName); + return container; + } + + /** + * Create contents of the button bar. + * + * @param parent + */ + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + /** + * Return the initial size of the dialog. + */ + @Override + protected Point getInitialSize() { + return new Point(1024, 600); + } + + @Override + protected void cancelPressed() { + super.cancelPressed(); + } + + @Override + protected void okPressed() { + if (this.getSelectedDevices().size() == 0) { + MessageDialog.openError(getShell(), "Select Brick(s)", "Please select atlease one brick"); + } else { + super.okPressed(); + } + } + + public List getSelectedDevices() { + return disksPage.getChosenDevices(); + } + + public Set getSelectedBricks(String volumeName) { + return disksPage.getChosenBricks(volumeName); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ServerAdditionDialog.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ServerAdditionDialog.java new file mode 100644 index 00000000..e02d42a4 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/dialogs/ServerAdditionDialog.java @@ -0,0 +1,197 @@ +/** + * ServerAdditionDialog.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.dialogs; + +import java.net.URI; +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.GlusterServer; + +public class ServerAdditionDialog extends Dialog { + public static final int RETURN_CODE_ERROR = 2; + private Text serverName; + private Button addButton; + + private GUIHelper guiHelper = GUIHelper.getInstance(); + private ControlDecoration errDecoration; + + private Composite composite; + + public ServerAdditionDialog(Shell shell) { + super(shell); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console - Add Server"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 2; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + // ------------------------------------------ + + private void createLabel(Composite composite, String label) { + Label passwordLabel = new Label(composite, SWT.NONE); + passwordLabel.setText(label); + passwordLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private Text createServerNameText(Composite composite) { + Text field = new Text(composite, SWT.BORDER ); + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + layoutData.widthHint = convertWidthInCharsToPixels(32); + field.setLayoutData(layoutData); + return field; + } + + @Override + protected Control createDialogArea(Composite parent) { + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + + createLabel(composite, "Server Name:"); + serverName = createServerNameText(composite); + errDecoration = guiHelper.createErrorDecoration(serverName); + + createListeners(); + + return composite; + } + + private void createListeners() { + ModifyListener listener = new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + updateButtonStatus(); + } + }; + + serverName.addModifyListener(listener); + } + + private void updateButtonStatus() { + addButton.setEnabled(true); + errDecoration.hide(); + + if(!serverExists(serverName.getText())) { + addButton.setEnabled(false); + errDecoration.setDescriptionText("Server name already exists."); + errDecoration.show(); + } + + if(serverName.getText().isEmpty()) { + addButton.setEnabled(false); + errDecoration.setDescriptionText("Please enter server name!"); + errDecoration.show(); + } + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + addButton = createButton(parent, IDialogConstants.OK_ID, "&Add Server", true); + addButton.setEnabled(false); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + public Boolean serverExists(String serverName) { + List servers = GlusterDataModelManager.getInstance().getModel().getCluster().getServers(); + for (GlusterServer server : servers) { + if (server.getName().equalsIgnoreCase(serverName)) { + return false; + } + } + return true; + } + + protected void okPressed() { + GlusterServersClient serversClient = new GlusterServersClient(); + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + try { + String serverNameText = serverName.getText(); + URI newServerURI = serversClient.addServer(serverNameText); + + modelManager.addGlusterServer(serversClient.getServer(newServerURI)); + + MessageDialog + .openInformation(getShell(), "Add Server", "Server " + serverNameText + " added successfully!"); + } catch (Exception e) { + MessageDialog.openError(getShell(), "Server addition Failed", e.getMessage()); + setReturnCode(RETURN_CODE_ERROR); + } + this.close(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/jobs/DataSyncJob.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/jobs/DataSyncJob.java new file mode 100644 index 00000000..907d7b84 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/jobs/DataSyncJob.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.jobs; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GlusterLogger; +import com.gluster.storage.management.core.model.GlusterDataModel; + +/** + * + */ +public class DataSyncJob extends Job { + private static final GlusterLogger logger = GlusterLogger.getInstance(); + + public DataSyncJob(String name) { + super(name); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected IStatus run(final IProgressMonitor monitor) { + final GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + // fetch the latest model + final GlusterDataModel model = modelManager.fetchModel(monitor); + if(model == null) { + return Status.CANCEL_STATUS; + } + + monitor.beginTask("Notify views", 1); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + modelManager.updateModel(model); + } + }); + monitor.worked(1); + monitor.done(); + + return Status.OK_STATUS; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/AlertsPreferencePage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/AlertsPreferencePage.java new file mode 100644 index 00000000..be8513fc --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/AlertsPreferencePage.java @@ -0,0 +1,38 @@ +package com.gluster.storage.management.console.preferences; + +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IntegerFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import com.gluster.storage.management.console.Activator; + +public class AlertsPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { + + public AlertsPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Gluster Management Console - Alerts"); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors() + */ + @Override + protected void createFieldEditors() { + addField(new IntegerFieldEditor(PreferenceConstants.P_SERVER_CPU_CRITICAL_THRESHOLD, + "&Server CPU usage threshold:", getFieldEditorParent())); + + addField(new IntegerFieldEditor(PreferenceConstants.P_SERVER_MEMORY_USAGE_THRESHOLD, + "&Server memory usage threshold (%):", getFieldEditorParent())); + + addField(new IntegerFieldEditor(PreferenceConstants.P_DISK_SPACE_USAGE_THRESHOLD, + "&Disk space usage threshold (%):", getFieldEditorParent())); + } + + @Override + public void init(IWorkbench workbench) { + // TODO Auto-generated method stub + + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/ChartsPreferencePage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/ChartsPreferencePage.java new file mode 100644 index 00000000..8eeb84ab --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/ChartsPreferencePage.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.preferences; + +import org.eclipse.jface.preference.ComboFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import com.gluster.storage.management.console.Activator; + +/** + * + */ +public class ChartsPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { + + public ChartsPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Gluster Management Console"); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + @Override + public void init(IWorkbench workbench) { + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors() + */ + @Override + protected void createFieldEditors() { + String[][] entryNamesAndValues = new String[][] { + { "1 day", "1d" }, { "1 week", "1w" }, { "1 month", "1m" }, { "1 year", "1y" } }; + addField(new ComboFieldEditor(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD, "Aggregated CPU Usage chart period", entryNamesAndValues, + getFieldEditorParent())); + addField(new ComboFieldEditor(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD, "Aggregated Network Usage chart period", entryNamesAndValues, + getFieldEditorParent())); + addField(new ComboFieldEditor(PreferenceConstants.P_CPU_CHART_PERIOD, "CPU Usage chart period", entryNamesAndValues, + getFieldEditorParent())); + addField(new ComboFieldEditor(PreferenceConstants.P_MEM_CHART_PERIOD, "Memory Usage chart period", entryNamesAndValues, + getFieldEditorParent())); + addField(new ComboFieldEditor(PreferenceConstants.P_NETWORK_CHART_PERIOD, "Network Usage chart period", entryNamesAndValues, + getFieldEditorParent())); + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/GlusterPreferencePage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/GlusterPreferencePage.java new file mode 100644 index 00000000..e382b10a --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/GlusterPreferencePage.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.preferences; + +import java.util.List; + +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.ComboFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IntegerFieldEditor; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import com.gluster.storage.management.client.ClustersClient; +import com.gluster.storage.management.console.Activator; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing FieldEditorPreferencePage, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + *

    + * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ +public class GlusterPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + private List clusterNames; + + public GlusterPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Gluster Management Console"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + addField( + new BooleanFieldEditor( + PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, + "&Show Cluster Selection Dialog on Login:", + getFieldEditorParent())); + + String[][] clusterNamesArr = new String[clusterNames.size()][2]; + for(int i = 0; i < clusterNames.size(); i++) { + String clusterName = clusterNames.get(i);; + clusterNamesArr[i][0] = clusterName; + clusterNamesArr[i][1] = clusterName; + } + + addField(new ComboFieldEditor(PreferenceConstants.P_DEFAULT_CLUSTER_NAME, "Default &Cluster to manage:", + clusterNamesArr, getFieldEditorParent())); + addField(new IntegerFieldEditor(PreferenceConstants.P_DATA_SYNC_INTERVAL, "&Data Sync Interval (sec):", + getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + clusterNames = new ClustersClient().getClusterNames(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceConstants.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceConstants.java new file mode 100644 index 00000000..650ae1a9 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceConstants.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.preferences; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants { + + public static final String P_SHOW_CLUSTER_SELECTION_DIALOG = "show.cluster.selection.dialog"; + public static final String P_DEFAULT_CLUSTER_NAME = "default.cluster.name"; + public static final String P_DATA_SYNC_INTERVAL = "data.sync.interval"; + + public static final String P_SERVER_CPU_CRITICAL_THRESHOLD = "server.cpu.threshold"; + public static final String P_SERVER_MEMORY_USAGE_THRESHOLD = "server.memory.threshold"; + public static final String P_DISK_SPACE_USAGE_THRESHOLD = "disk.space.threshold"; // in percentage + + public static final String P_CPU_CHART_PERIOD = "cpu.chart.period"; + public static final String P_MEM_CHART_PERIOD = "memory.chart.period"; + public static final String P_NETWORK_CHART_PERIOD = "network.chart.period"; + public static final String P_DEFAULT_NETWORK_INTERFACE_PFX = "default.network.interface."; + public static final String P_CPU_AGGREGATED_CHART_PERIOD = "cpu.aggregated.chart.period"; + public static final String P_NETWORK_AGGREGATED_CHART_PERIOD = "network.aggregated.chart.period"; +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceInitializer.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceInitializer.java new file mode 100644 index 00000000..3c192f62 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/preferences/PreferenceInitializer.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.gluster.storage.management.console.Activator; + +/** + * Class used to initialize default preference values. + */ +public class PreferenceInitializer extends AbstractPreferenceInitializer { + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + + store.setDefault(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, true); + + // default data sync interval = 5 minutes + store.setDefault(PreferenceConstants.P_DATA_SYNC_INTERVAL, 300); + + // Default CPU utilisation threshold + store.setDefault(PreferenceConstants.P_SERVER_CPU_CRITICAL_THRESHOLD, 95); + + // Default Memory threshold + store.setDefault(PreferenceConstants.P_SERVER_MEMORY_USAGE_THRESHOLD, 90); + + // Default disk free space threshold + store.setDefault(PreferenceConstants.P_DISK_SPACE_USAGE_THRESHOLD, 90); + + // Default period for server statistics charts + store.setDefault(PreferenceConstants.P_CPU_CHART_PERIOD, "1d"); + store.setDefault(PreferenceConstants.P_MEM_CHART_PERIOD, "1d"); + store.setDefault(PreferenceConstants.P_NETWORK_CHART_PERIOD, "1d"); + store.setDefault(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD, "1d"); + store.setDefault(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD, "1d"); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/GlusterToolbarManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/GlusterToolbarManager.java new file mode 100644 index 00000000..f8bcc446 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/GlusterToolbarManager.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.toolbar; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; + +import com.gluster.storage.management.console.actions.IActionConstants; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.Volume; + +public class GlusterToolbarManager implements ToolbarManager { + private enum ENTITY_TYPE { + CLUSTER, VOLUMES, VOLUME, GLUSTER_SERVERS, GLUSTER_SERVER, DISCOVERED_SERVERS, DISCOVERED_SERVER, TASK + }; + + private IWorkbenchWindow window; + private final Map, ENTITY_TYPE> entityTypeMap = createEntityTypeMap(); + private final Map actionSetMap = createActionSetMap(); + + private Map, ENTITY_TYPE> createEntityTypeMap() { + Map, ENTITY_TYPE> entityTypeMap = new HashMap, GlusterToolbarManager.ENTITY_TYPE>(); + entityTypeMap.put(Cluster.class, ENTITY_TYPE.CLUSTER); + entityTypeMap.put(Volume.class, ENTITY_TYPE.VOLUME); + entityTypeMap.put(Server.class, ENTITY_TYPE.DISCOVERED_SERVER); + entityTypeMap.put(GlusterServer.class, ENTITY_TYPE.GLUSTER_SERVER); + entityTypeMap.put(TaskInfo.class, ENTITY_TYPE.TASK); + + return entityTypeMap; + } + + private Map createActionSetMap() { + Map actionSetMap = new HashMap(); + actionSetMap.put(ENTITY_TYPE.CLUSTER, IActionConstants.ACTION_SET_CLUSTER); + actionSetMap.put(ENTITY_TYPE.VOLUMES, IActionConstants.ACTION_SET_VOLUMES); + actionSetMap.put(ENTITY_TYPE.VOLUME, IActionConstants.ACTION_SET_VOLUME); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVERS, IActionConstants.ACTION_SET_GLUSTER_SERVERS); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVER, IActionConstants.ACTION_SET_GLUSTER_SERVER); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVERS, IActionConstants.ACTION_SET_DISCOVERED_SERVERS); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVER, IActionConstants.ACTION_SET_DISCOVERED_SERVER); + actionSetMap.put(ENTITY_TYPE.TASK, IActionConstants.ACTION_SET_TASK); + + return actionSetMap; + } + + public GlusterToolbarManager(IWorkbenchWindow window) { + this.window = window; + } + + @SuppressWarnings("rawtypes") + private ENTITY_TYPE getEntityType(Entity entity) { + if (entity instanceof EntityGroup) { + EntityGroup entityGroup = (EntityGroup) entity; + if (entityGroup.getEntityType() == Volume.class) { + return ENTITY_TYPE.VOLUMES; + } else if (entityGroup.getEntityType() == GlusterServer.class) { + return ENTITY_TYPE.GLUSTER_SERVERS; + } else { + return ENTITY_TYPE.DISCOVERED_SERVERS; + } + } + + return entityTypeMap.get(entity.getClass()); + } + + @Override + public void updateToolbar(Entity entity) { + ENTITY_TYPE entityType = getEntityType(entity); + IWorkbenchPage page = window.getActivePage(); + + for (ENTITY_TYPE targetEntityType : actionSetMap.keySet()) { + String actionSetId = actionSetMap.get(targetEntityType); + if (entityType == targetEntityType) { + // show only the action set mapped to given entity + page.showActionSet(actionSetId); + } else { + page.hideActionSet(actionSetId); + } + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/ToolbarManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/ToolbarManager.java new file mode 100644 index 00000000..8dc14ffd --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/toolbar/ToolbarManager.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.toolbar; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Whenever the current selection/action demands changes to the toolbar, the toolbar manager is used to update the + * toolbar. + */ +public interface ToolbarManager { + /** + * Updates the toolbar for given entity. This typically means that user is working with the given entity, and hence + * the toolbar actions related to that entity should be made visible, and other un-related actions should be hidden. + * + * @param entity + */ + public void updateToolbar(Entity entity); +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartUtil.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartUtil.java new file mode 100644 index 00000000..57121f5b --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartUtil.java @@ -0,0 +1,339 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.birt.chart.util.CDateTime; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; + +import com.gluster.storage.management.console.Activator; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.ibm.icu.util.Calendar; + +/** + * + */ +public class ChartUtil { + private static final ChartUtil instance = new ChartUtil(); + private static final int CHART_WIDTH = 350; + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + + private ChartUtil() { + } + + public static ChartUtil getInstance() { + return instance; + } + + /** + * @param toolkit + * @param section + * @param stats + * @param dataColumnIndex + * @param unit + * @param timestampFormat + * @param listener + * @param maxValue + * @return The composite containing the various links related to the created chart + */ + public Composite createAreaChart(FormToolkit toolkit, Composite section, ServerStats stats, int dataColumnIndex, + String unit, String timestampFormat, ChartPeriodLinkListener listener, double maxValue, int linkColumnCount) { + if (stats == null) { + toolkit.createLabel(section, "Server statistics not available. Try after some time!"); + return null; + } + + List timestamps = new ArrayList(); + List data = new ArrayList(); + + extractChartData(stats, timestamps, data, dataColumnIndex); + + if (timestamps.size() == 0) { + toolkit.createLabel(section, "Server statistics not available!" + CoreConstants.NEWLINE + + "Check if all services are running properly " + CoreConstants.NEWLINE + + "on the cluster servers, or try after some time!"); + return null; + } + + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, + timestampFormat, maxValue); + + // Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), + // new CDateTime(1000l*1310468700), + // new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new + // CDateTime(1000l*1310469900), + // new CDateTime(1000l*1310470200), new CDateTime(1000l*1310470500), new CDateTime(1000l*1310470800), new + // CDateTime(1000l*1310471100), + // new CDateTime(1000l*1310471400), new CDateTime(1000l*1310471700), new CDateTime(1000l*1310472000), new + // CDateTime(1000l*1310472300), + // new CDateTime(1000l*1310472600), new CDateTime(1000l*1310472900), new CDateTime(1000l*1310473200), new + // CDateTime(1000l*1310473500), + // new CDateTime(1000l*1310473800) }; + // + // Double[] values = new Double[] { 10d, 11.23d, 17.92d, 18.69d, 78.62d, 89.11d, 92.43d, 89.31d, 57.39d, 18.46d, + // 10.44d, 16.28d, 13.51d, 17.53d, 12.21, 20d, 21.43d, 16.45d, 14.86d, 15.27d }; + // createLineChart(section, timestamps, values, "%"); + Composite chartLinksComposite = createChartLinks(toolkit, section, linkColumnCount, listener); + + if (linkColumnCount == 5) { + createNetworkInterfaceCombo(section, chartLinksComposite, toolkit, + (NetworkChartPeriodLinkListener) listener); + } + return chartLinksComposite; + } + + private ChartViewerComposite createAreaChart(Composite section, Calendar timestamps[], Double values[], + String unit, String timestampFormat, double maxValue) { + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, + unit, timestampFormat, maxValue); + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = CHART_WIDTH; + data.heightHint = 250; + data.verticalAlignment = SWT.CENTER; + chartViewerComposite.setLayoutData(data); + return chartViewerComposite; + } + + private void extractChartData(ServerStats stats, List timestamps, List data, int dataColumnIndex) { + for (ServerStatsRow row : stats.getRows()) { + Double cpuUsage = row.getUsageData().get(dataColumnIndex); + if (!cpuUsage.isNaN()) { + timestamps.add(new CDateTime(row.getTimestamp() * 1000)); + data.add(cpuUsage); + } + } + } + + private Composite createChartLinks(FormToolkit toolkit, Composite section, int columnCount, + ChartPeriodLinkListener listener) { + GridLayout layout = new org.eclipse.swt.layout.GridLayout(columnCount, false); + layout.marginBottom = 0; + layout.marginTop = 0; + layout.marginLeft = (CHART_WIDTH - (50 * columnCount)) / 2; + Composite graphComposite = toolkit.createComposite(section, SWT.NONE); + graphComposite.setLayout(layout); + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = CHART_WIDTH; + graphComposite.setLayoutData(data); + + createStatsLink(toolkit, listener, graphComposite, "1 day", GlusterConstants.STATS_PERIOD_1DAY); + createStatsLink(toolkit, listener, graphComposite, "1 week", GlusterConstants.STATS_PERIOD_1WEEK); + createStatsLink(toolkit, listener, graphComposite, "1 month", GlusterConstants.STATS_PERIOD_1MONTH); + createStatsLink(toolkit, listener, graphComposite, "1 year", GlusterConstants.STATS_PERIOD_1YEAR); + + return graphComposite; + } + + private void createStatsLink(FormToolkit toolkit, ChartPeriodLinkListener listener, Composite parent, String label, + String statsPeriod) { + Hyperlink link1 = toolkit.createHyperlink(parent, label, SWT.NONE); + link1.addHyperlinkListener(listener.getInstance(statsPeriod)); + if (listener.getStatsPeriod().equals(statsPeriod)) { + link1.setEnabled(false); + } + } + + public abstract class ChartPeriodLinkListener extends HyperlinkAdapter { + protected String statsPeriod; + protected String unit; + protected int columnCount; + protected double maxValue; + protected FormToolkit toolkit; + protected String serverName; + protected int dataColumnIndex; + + public String getStatsPeriod() { + return this.statsPeriod; + } + + public ChartPeriodLinkListener(String serverName, String statsPeriod, String unit, double maxValue, + int columnCount, int dataColumnIndex, FormToolkit toolkit) { + this.serverName = serverName; + this.statsPeriod = statsPeriod; + this.unit = unit; + this.columnCount = columnCount; + this.maxValue = maxValue; + this.dataColumnIndex = dataColumnIndex; + this.toolkit = toolkit; + } + + public ChartPeriodLinkListener(String serverName, String statsPeriod, FormToolkit toolkit) { + this.statsPeriod = statsPeriod; + this.serverName = serverName; + this.toolkit = toolkit; + } + + @Override + public void linkActivated(HyperlinkEvent e) { + super.linkActivated(e); + Composite section = ((Hyperlink) e.getSource()).getParent().getParent(); + updatePreference(serverName); + } + + public abstract ChartPeriodLinkListener getInstance(String statsPeriod); + + protected abstract void updatePreference(String serverName); + } + + public class CpuChartPeriodLinkListener extends ChartPeriodLinkListener { + public CpuChartPeriodLinkListener(String serverName, String statsPeriod, FormToolkit toolkit) { + super(serverName, statsPeriod, toolkit); + } + + private CpuChartPeriodLinkListener(String serverName, String statsPeriod, String unit, double maxValue, + int columnCount, int dataColumnIndex, FormToolkit toolkit) { + super(serverName, statsPeriod, unit, maxValue, columnCount, dataColumnIndex, toolkit); + } + + @Override + protected void updatePreference(String serverName) { + ServerStats stats; + if (serverName == null) { + preferenceStore.setValue(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD, statsPeriod); + } else { + preferenceStore.setValue(PreferenceConstants.P_CPU_CHART_PERIOD, statsPeriod); + } + } + + @Override + public ChartPeriodLinkListener getInstance(String statsPeriod) { + return new CpuChartPeriodLinkListener(serverName, statsPeriod, "%", 100, 4, dataColumnIndex, toolkit); + } + } + + public class MemoryChartPeriodLinkListener extends ChartPeriodLinkListener { + public MemoryChartPeriodLinkListener(String serverName, String statsPeriod, FormToolkit toolkit) { + super(serverName, statsPeriod, toolkit); + } + + private MemoryChartPeriodLinkListener(String serverName, String statsPeriod, String unit, double maxValue, + int columnCount, int dataColumnIndex, FormToolkit toolkit) { + super(serverName, statsPeriod, unit, maxValue, columnCount, dataColumnIndex, toolkit); + } + + @Override + protected void updatePreference(String serverName) { + preferenceStore.setValue(PreferenceConstants.P_MEM_CHART_PERIOD, statsPeriod); + } + + @Override + public ChartPeriodLinkListener getInstance(String statsPeriod) { + return new MemoryChartPeriodLinkListener(serverName, statsPeriod, "%", 100, 4, dataColumnIndex, toolkit); + } + } + + public class NetworkChartPeriodLinkListener extends ChartPeriodLinkListener { + private GlusterServer server; + + public NetworkChartPeriodLinkListener(GlusterServer server, String statsPeriod, FormToolkit toolkit) { + super(server == null ? null : server.getName(), statsPeriod, toolkit); + this.setServer(server); + } + + private NetworkChartPeriodLinkListener(GlusterServer server, String statsPeriod, String unit, double maxValue, + int columnCount, int dataColumnIndex, FormToolkit toolkit) { + super(server == null ? null : server.getName(), statsPeriod, unit, maxValue, columnCount, dataColumnIndex, + toolkit); + this.setServer(server); + } + + @Override + protected void updatePreference(String serverName) { + if (serverName == null) { + preferenceStore.setValue(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD, statsPeriod); + } else { + preferenceStore.setValue(PreferenceConstants.P_NETWORK_CHART_PERIOD, statsPeriod); + } + } + + @Override + public ChartPeriodLinkListener getInstance(String statsPeriod) { + // if serverName is null, it means we are showing aggregated stats - so the "network interface" combo will + // not be shown in the "links" composite. + int columnCount = (serverName == null ? 4 : 5); + return new NetworkChartPeriodLinkListener(server, statsPeriod, "KiB/s", -1d, columnCount, dataColumnIndex, + toolkit); + } + + public void setServer(GlusterServer server) { + this.server = server; + } + + public GlusterServer getServer() { + return server; + } + } + + public void createNetworkInterfaceCombo(final Composite section, final Composite graphComposite, + final FormToolkit toolkit, final NetworkChartPeriodLinkListener networkChartPeriodLinkListener) { + final GlusterServer server = networkChartPeriodLinkListener.getServer(); + final CCombo interfaceCombo = new CCombo(graphComposite, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER | SWT.FLAT); + final List niList = server.getNetworkInterfaces(); + final String[] interfaces = new String[niList.size()]; + + for (int i = 0; i < interfaces.length; i++) { + interfaces[i] = niList.get(i).getName(); + } + interfaceCombo.setItems(interfaces); + interfaceCombo.select(0); + interfaceCombo.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + preferenceStore.setValue(PreferenceConstants.P_DEFAULT_NETWORK_INTERFACE_PFX + server.getName(), interfaces[interfaceCombo.getSelectionIndex()]); + } + }); + } + + public void refreshChartSection(FormToolkit toolkit, Composite section, ServerStats stats, String statsPeriod, + String unit, double maxValue, int columnCount, ChartPeriodLinkListener linkListener, int dataColumnIndex) { + GUIHelper.getInstance().clearSection(section); + createAreaChart(toolkit, section, stats, dataColumnIndex, unit, getTimestampFormatForPeriod(statsPeriod), + linkListener, maxValue, columnCount); + section.layout(); + } + + public String getTimestampFormatForPeriod(String statsPeriod) { + if (statsPeriod.equals(GlusterConstants.STATS_PERIOD_1DAY)) { + return "HH:mm"; + } else if (statsPeriod.equals(GlusterConstants.STATS_PERIOD_1WEEK)) { + return "dd-MMM HH:mm"; + } else { + return "dd-MMM"; + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartViewerComposite.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartViewerComposite.java new file mode 100644 index 00000000..8da32a60 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ChartViewerComposite.java @@ -0,0 +1,465 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.utils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.eclipse.birt.chart.api.ChartEngine; +import org.eclipse.birt.chart.device.IDeviceRenderer; +import org.eclipse.birt.chart.device.IUpdateNotifier; +import org.eclipse.birt.chart.exception.ChartException; +import org.eclipse.birt.chart.factory.GeneratedChartState; +import org.eclipse.birt.chart.factory.Generator; +import org.eclipse.birt.chart.model.Chart; +import org.eclipse.birt.chart.model.ChartWithoutAxes; +import org.eclipse.birt.chart.model.attribute.Anchor; +import org.eclipse.birt.chart.model.attribute.AxisType; +import org.eclipse.birt.chart.model.attribute.Bounds; +import org.eclipse.birt.chart.model.attribute.ChartDimension; +import org.eclipse.birt.chart.model.attribute.LineAttributes; +import org.eclipse.birt.chart.model.attribute.LineStyle; +import org.eclipse.birt.chart.model.attribute.TickStyle; +import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; +import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; +import org.eclipse.birt.chart.model.attribute.impl.JavaDateFormatSpecifierImpl; +import org.eclipse.birt.chart.model.attribute.impl.LineAttributesImpl; +import org.eclipse.birt.chart.model.attribute.impl.NumberFormatSpecifierImpl; +import org.eclipse.birt.chart.model.component.Axis; +import org.eclipse.birt.chart.model.component.Series; +import org.eclipse.birt.chart.model.component.impl.SeriesImpl; +import org.eclipse.birt.chart.model.data.DateTimeDataElement; +import org.eclipse.birt.chart.model.data.DateTimeDataSet; +import org.eclipse.birt.chart.model.data.NumberDataSet; +import org.eclipse.birt.chart.model.data.SeriesDefinition; +import org.eclipse.birt.chart.model.data.TextDataSet; +import org.eclipse.birt.chart.model.data.impl.DateTimeDataElementImpl; +import org.eclipse.birt.chart.model.data.impl.DateTimeDataSetImpl; +import org.eclipse.birt.chart.model.data.impl.NumberDataElementImpl; +import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl; +import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl; +import org.eclipse.birt.chart.model.data.impl.TextDataSetImpl; +import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl; +import org.eclipse.birt.chart.model.impl.ChartWithoutAxesImpl; +import org.eclipse.birt.chart.model.layout.Legend; +import org.eclipse.birt.chart.model.layout.Plot; +import org.eclipse.birt.chart.model.type.AreaSeries; +import org.eclipse.birt.chart.model.type.PieSeries; +import org.eclipse.birt.chart.model.type.impl.AreaSeriesImpl; +import org.eclipse.birt.chart.model.type.impl.PieSeriesImpl; +import org.eclipse.birt.core.framework.PlatformConfig; +import org.eclipse.core.runtime.Platform; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; + +import com.ibm.icu.util.Calendar; + +/** + * + */ +public final class ChartViewerComposite extends Composite implements PaintListener, IUpdateNotifier { + + public enum CHART_TYPE { + PIE, LINE + }; + + private IDeviceRenderer deviceReader = null; + private Chart chart = null; + private GeneratedChartState generatedChartState = null; + private boolean needsGeneration = true; + + private static Logger logger = Logger.getLogger(ChartViewerComposite.class.getName()); + + /** + * @param parent + * Parent composite of this pie chart viewer composite + * @param style + * SWT style to be used + * @param categories + * Categories of the pie chart + * @param values + * Values of each category in the pie chart Constructs a pie + * chart viewer composite for given categories and values + */ + public ChartViewerComposite(Composite parent, int style, String[] categories, Double[] values) { + super(parent, style); + init(); + + chart = createPieChart(categories, values); + addPaintListener(this); + } + + /** + * @param parent + * Parent composite of this pie chart viewer composite + * @param style + * SWT style to be used + * @param categories + * Categories of the pie chart + * @param values + * Values of each category in the pie chart Constructs a pie + * chart viewer composite for given categories and values + * @param maxValue + */ + public ChartViewerComposite(Composite parent, int style, Calendar[] categories, Double[] values, String unit, String timestampFormat, double maxValue) { + super(parent, style); + init(); + + createSingleAreaChart(categories, values, unit, timestampFormat, maxValue); + addPaintListener(this); + } + + public void init() { + try { + PlatformConfig config = new PlatformConfig(); + config.setBIRTHome(Platform.getInstallLocation().getURL().getPath()); + // Get the connection with SWT device to render the graphics. + deviceReader = ChartEngine.instance(config).getRenderer("dv.SWT");//$NON-NLS-1$ + } catch (ChartException ex) { + logger.log(Level.SEVERE, "Could not create Chart Renderer for SWT", ex); + } + + addControlListener(new ControlListener() { + + public void controlMoved(ControlEvent e) { + needsGeneration = true; + } + + public void controlResized(ControlEvent e) { + needsGeneration = true; + } + }); + } + + private void createSingleAreaChart(Calendar[] timestamps, Double[] values, String unit, String timestampFormat, double maxValue) { + createAreaChart(timestamps, new Double[][] {values}, unit, timestampFormat, maxValue); + } + + /** + * Creates a line chart model as a reference implementation + * @param maxValue + * + * @return An instance of the simulated runtime chart model (containing + * filled datasets) + */ + private final void createAreaChart(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { + chart = ChartWithAxesImpl.create(); + // Plot + chart.getBlock().setBackground(ColorDefinitionImpl.WHITE()); + Plot p = chart.getPlot(); + p.getClientArea().setBackground(ColorDefinitionImpl.WHITE()); + p.setBackground(ColorDefinitionImpl.WHITE()); + + // Title + chart.getTitle().getLabel().getCaption().setValue("Line Chart");//$NON-NLS-1$ + chart.getTitle().setVisible(false); + chart.getTitle().getLabel().setVisible(true); + chart.getTitle().getInsets().set(0, 10, 0, 0); + chart.getTitle().setAnchor(Anchor.SOUTH_LITERAL); + + // Legend + Legend lg = chart.getLegend(); + lg.setVisible(false); + LineAttributes lia = lg.getOutline( ); + lia.setStyle( LineStyle.SOLID_LITERAL ); + lg.getText( ).getFont( ).setSize( 10 ); + //lg.getInsets( ).set( 10, 5, 0, 0 ); + lg.getInsets( ).set( 0, 0, 0, 0 ); + lg.getOutline( ).setVisible( false ); + lg.setAnchor( Anchor.NORTH_LITERAL ); + + updateDataSet(timestamps, values, unit, timestampFormat, maxValue); + } + + private void updateDataSet(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { + Axis xAxisPrimary = setupXAxis(timestamps, timestampFormat); + + if(maxValue <= 0) { + maxValue = getMaxValue(values); + } + Axis yAxisPrimary = setupYAxis(unit, xAxisPrimary, maxValue); + configureXSeries(timestamps, xAxisPrimary); + configureYSeries(values, yAxisPrimary); + } + + private double getMaxValue(Double[][] values) { + double maxValue = -1; + for(Double[] seriesValues : values) { + double seriesMaxVal = Collections.max(Arrays.asList(seriesValues)); + if(seriesMaxVal > maxValue) { + maxValue = Math.round(seriesMaxVal) + 5 - (Math.round(seriesMaxVal) % 5); + } + } + return maxValue; + } + + private void configureYSeries(Double[][] values, Axis yAxisPrimary) { + SeriesDefinition sdY = SeriesDefinitionImpl.create(); + sdY.getSeriesPalette().shift(-3); + yAxisPrimary.getSeriesDefinitions().add(sdY); + + for (int i = 0; i < values.length; i++) { + // Y-Sereis + AreaSeries ls = (AreaSeries) AreaSeriesImpl.create(); + // LineSeries ls = (LineSeries) LineSeriesImpl.create(); + + NumberDataSet orthoValues = NumberDataSetImpl.create(values[i]); + ls.setDataSet(orthoValues); + ls.getLineAttributes().setColor(ColorDefinitionImpl.create(50, 50, 255)); +// for (int j = 0; j < ls.getMarkers().size(); j++) { +// ( (Marker) ls.getMarkers( ).get( j ) ).setType( MarkerType.CIRCLE_LITERAL); +// ((Marker) ls.getMarkers().get(j)).setVisible(true); +// } + ls.setTranslucent(true); + // don't show values on each point on the line chart + ls.getLabel().setVisible(false); + sdY.getSeries().add(ls); + } + } + + private void configureXSeries(Calendar[] timestamps, Axis xAxisPrimary) { + // Data Set + DateTimeDataSet categoryValues = DateTimeDataSetImpl.create(timestamps); + + // X-Series + Series seCategory = SeriesImpl.create(); + seCategory.setDataSet(categoryValues); + SeriesDefinition sdX = SeriesDefinitionImpl.create(); + + xAxisPrimary.getSeriesDefinitions().add(sdX); + sdX.getSeries().add(seCategory); + } + + private Axis setupYAxis(final String unit, Axis xAxisPrimary, double maxValue) { + Axis yAxisPrimary = ((ChartWithAxesImpl)chart).getPrimaryOrthogonalAxis(xAxisPrimary); + if(maxValue > 0) { + yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(maxValue)); + yAxisPrimary.getScale().setStep(maxValue / 5); + } + yAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0)); + yAxisPrimary.setGapWidth(0); + yAxisPrimary.getScale().setMajorGridsStepNumber(1); + yAxisPrimary.getMajorGrid().setTickStyle(TickStyle.LEFT_LITERAL); + yAxisPrimary.getMajorGrid().setLineAttributes(LineAttributesImpl.create(ColorDefinitionImpl.GREY(), LineStyle.SOLID_LITERAL, 1)); + yAxisPrimary.getLabel().setVisible(true); + yAxisPrimary.getLabel().getCaption().getFont().setSize(8); + yAxisPrimary.setFormatSpecifier(new NumberFormatSpecifierImpl() { + @Override + public String getSuffix() { + return " " + unit; + } + }); + return yAxisPrimary; + } + + private Axis setupXAxis(Calendar[] timestamps, final String timestampFormat) { + Axis xAxisPrimary = ((ChartWithAxesImpl)chart).getPrimaryBaseAxes()[0]; + xAxisPrimary.setType(AxisType.TEXT_LITERAL); + DateTimeDataElement dtde = DateTimeDataElementImpl.create(timestamps[timestamps.length-1]); + DateTimeDataElement dtde1 = DateTimeDataElementImpl.create(timestamps[0]); + xAxisPrimary.getScale().setMax(dtde); + xAxisPrimary.getScale().setStep((dtde.getValue() - dtde1.getValue())/ 10); + xAxisPrimary.getScale().setMajorGridsStepNumber(timestamps.length > 10 ? timestamps.length / 10 : 1); + //xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.ABOVE_LITERAL); + xAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false); + xAxisPrimary.getMajorGrid().setLineAttributes(LineAttributesImpl.create(ColorDefinitionImpl.GREY(), LineStyle.SOLID_LITERAL, 1)); + xAxisPrimary.getTitle().setVisible(false); + xAxisPrimary.getTitle().getInsets().set(1, 1, 1, 1); + xAxisPrimary.getLabel().getInsets().set(1, 1, 1, 1); + //xAxisPrimary.getLabel().getCaption().setFont(createChartFont()); + xAxisPrimary.getLabel( ).getCaption( ).getFont( ).setSize(8); + //commenting to check whether this is causing the problem on windows + //xAxisPrimary.getLabel( ).getCaption( ).getFont( ).setRotation( 75 ); + xAxisPrimary.setFormatSpecifier( JavaDateFormatSpecifierImpl.create( timestampFormat ) ); + return xAxisPrimary; + } + + /** + * @param categories + * Categories of the pie chart + * @param values + * Values of each category in the pie chart + * @return The chart object created for given categories and values + */ + public static final Chart createPieChart(String[] categories, Double[] values) { + ChartWithoutAxes pieChart = ChartWithoutAxesImpl.create(); + + // Plot + pieChart.setSeriesThickness(10); + pieChart.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL); + pieChart.getBlock().setBackground(ColorDefinitionImpl.WHITE()); + Plot p = pieChart.getPlot(); + + p.getClientArea().setBackground(null); + p.getClientArea().getOutline().setVisible(false); + p.getOutline().setVisible(false); + + // Legend + Legend lg = pieChart.getLegend(); + lg.setMaxPercent(0.7); + lg.getText().getFont().setSize(9); + lg.setBackground(null); + lg.getOutline().setVisible(false); + lg.setVisible(true); + + // Title + pieChart.getTitle().getLabel().getCaption().setValue("Pie Chart");//$NON-NLS-1$ + pieChart.getTitle().getOutline().setVisible(false); + pieChart.getTitle().setVisible(false); + + TextDataSet categoryValues = TextDataSetImpl.create(categories); + NumberDataSet seriesOneValues = NumberDataSetImpl.create(values); + + // Base Series + Series seCategory = SeriesImpl.create(); + seCategory.setDataSet(categoryValues); + + SeriesDefinition sd = SeriesDefinitionImpl.create(); + pieChart.getSeriesDefinitions().add(sd); + sd.setSeriesPalette(new GlusterChartPalette()); + sd.getSeriesPalette().shift(0); + sd.getSeries().add(seCategory); + + // Orthogonal Series + PieSeries sePie = (PieSeries) PieSeriesImpl.create(); + sePie.setRatio(0.60); + sePie.setDataSet(seriesOneValues); + sePie.setSeriesIdentifier("Chart");//$NON-NLS-1$ + sePie.getTitle().setVisible(false); // no title + sePie.getLabel().setVisible(false); // no label (values) + sePie.setExplosion(0); // no gap between the pie slices + + SeriesDefinition seriesDefinition = SeriesDefinitionImpl.create(); + seriesDefinition.getQuery().setDefinition("query.definition");//$NON-NLS-1$ + sd.getSeriesDefinitions().add(seriesDefinition); + seriesDefinition.getSeries().add(sePie); + + return pieChart; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events + * .PaintEvent) + */ + public final void paintControl(PaintEvent e) { + Rectangle d = ((Composite) e.getSource()).getBounds(); + Image imgChart = new Image(this.getDisplay(), d); + GC gcImage = new GC(imgChart); + deviceReader.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, gcImage); + deviceReader.setProperty(IDeviceRenderer.UPDATE_NOTIFIER, this); + + Bounds bo = BoundsImpl.create(0, 0, d.width, d.height); + bo.scale(71d / deviceReader.getDisplayServer().getDpiResolution()); + + Generator gr = Generator.instance(); + if (needsGeneration) { + needsGeneration = false; + try { + generatedChartState = gr.build(deviceReader.getDisplayServer(), chart, bo, null, null, null); + } catch (ChartException ce) { + ce.printStackTrace(); + } + } + + try { + gr.render(deviceReader, generatedChartState); + GC gc = e.gc; + gc.drawImage(imgChart, d.x, d.y); + } catch (ChartException gex) { + logger.log(Level.SEVERE, "Exception while rendering pie chart [" + gex.getMessage() + "]", gex); + } + } + +// public void chartRefresh(Calendar[] timestamps, Double[][] values, String unit, String timestampFormat) +// { +// if ( !isDisposed( ) ) +// { +// final Generator gr = Generator.instance( ); +// updateDataSet( timestamps, values, unit, timestampFormat); +// +// // Refresh +// try +// { +// gr.refresh( generatedChartState ); +// } +// catch ( ChartException ex ) +// { +// // TODO: log the exception +// ex.printStackTrace( ); +// } +// redraw( ); +// } +// } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#getDesignTimeModel() + */ + public Chart getDesignTimeModel() { + return chart; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#getRunTimeModel() + */ + public Chart getRunTimeModel() { + return generatedChartState.getChartModel(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#peerInstance() + */ + public Object peerInstance() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#regenerateChart() + */ + public void regenerateChart() { + redraw(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#repaintChart() + */ + public void repaintChart() { + redraw(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/EntityViewerFilter.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/EntityViewerFilter.java new file mode 100644 index 00000000..60161324 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/EntityViewerFilter.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.utils; + +import java.util.Map.Entry; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import com.gluster.storage.management.core.model.Filterable; +import com.gluster.storage.management.core.utils.StringUtil; + +public class EntityViewerFilter extends ViewerFilter { + + private String filterString; + private boolean caseSensitive = false; + + public EntityViewerFilter(String filterString, boolean caseSensitive) { + this.filterString = filterString; + this.caseSensitive = caseSensitive; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public String getFilterString() { + return filterString; + } + + public void setFilterString(String filterString) { + this.filterString = filterString; + } + + @SuppressWarnings("unchecked") + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (filterString == null || filterString.isEmpty()) { + // No filter string. select everything + return true; + } + + if (element instanceof Filterable) { + return ((Filterable) element).filter(filterString, caseSensitive); + } + + if(element instanceof Entry) { + Entry entry = (Entry)element; + return StringUtil.filterString(entry.getKey() + entry.getValue(), filterString, caseSensitive); + } + + if(element instanceof String) { + return StringUtil.filterString((String)element, filterString, caseSensitive); + } + + return false; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GUIHelper.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GUIHelper.java new file mode 100644 index 00000000..9f53c047 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GUIHelper.java @@ -0,0 +1,492 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.utils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuCreator; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnLayoutData; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.events.ExpansionAdapter; +import org.eclipse.ui.forms.events.ExpansionEvent; +import org.eclipse.ui.forms.widgets.ColumnLayout; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.progress.IProgressConstants; + +import com.gluster.storage.management.console.Application; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.views.NavigationView; +import com.gluster.storage.management.console.views.TasksView; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.utils.JavaUtil; + +public class GUIHelper { + private static final GUIHelper instance = new GUIHelper(); + private static final ImageUtil imageUtil = new ImageUtil(); + + private GUIHelper() { + + } + + public static GUIHelper getInstance() { + return instance; + } + + public ScrolledForm setupForm(Composite parent, FormToolkit toolkit, final String formName) { + return setupForm(toolkit, formName, toolkit.createScrolledForm(parent)); + } + + public ScrolledForm setupForm(FormToolkit toolkit, final String formName, ScrolledForm form) { + form.setText(formName); + toolkit.decorateFormHeading(form.getForm()); + + ColumnLayout layout = new ColumnLayout(); + + // layout.topMargin = 0; + // layout.bottomMargin = 5; + // layout.leftMargin = 10; + // layout.rightMargin = 10; + // layout.horizontalSpacing = 10; + // layout.verticalSpacing = 10; + // layout.maxNumColumns = 4; + // layout.minNumColumns = 1; + + form.getBody().setLayout(layout); + return form; + } + + public Composite createSection(final ScrolledForm form, FormToolkit toolkit, String title, String desc, + int numColumns, boolean collapsible) { + int style = Section.TITLE_BAR | Section.EXPANDED; + if (desc != null && !desc.isEmpty()) { + style |= Section.DESCRIPTION; + } + if (collapsible) { + style |= Section.TWISTIE; + } + + Section section = toolkit.createSection(form.getBody(), style); + section.setText(title); + section.setDescription(desc); + + // toolkit.createCompositeSeparator(section); + Composite client = toolkit.createComposite(section); + GridLayout layout = new GridLayout(); + layout.marginWidth = layout.marginHeight = 0; + layout.numColumns = numColumns; + layout.verticalSpacing = 10; + layout.marginBottom = 15; + layout.marginTop = 10; + + client.setLayout(layout); + section.setClient(client); + + section.addExpansionListener(new ExpansionAdapter() { + public void expansionStateChanged(ExpansionEvent e) { + form.reflow(false); + } + }); + return client; + } + + public Composite createTab(TabFolder tabFolder, String title, String imageKey) { + TabItem item = new TabItem(tabFolder, SWT.NONE); + item.setText(title); + item.setImage(getImage(imageKey)); + + Composite composite = new Composite(tabFolder, SWT.NONE); + composite.setLayout(new FillLayout()); + + item.setControl(composite); + + return composite; + } + + public ImageDescriptor getImageDescriptor(String imagePath) { + return imageUtil.getImageDescriptor(imagePath); + } + + public Image getImage(String imagePath) { + return imageUtil.getImage(imagePath); + } + + public Action createPullDownMenu(String menuName, String iconPath, final MenuManager menuManager) { + Action action = new Action(menuName, IAction.AS_DROP_DOWN_MENU) { + public void run() { + } + }; + action.setMenuCreator(new IMenuCreator() { + + @Override + public Menu getMenu(Menu menu) { + return null; + } + + @Override + public Menu getMenu(Control control) { + return menuManager.createContextMenu(control); + } + + @Override + public void dispose() { + } + }); + action.setImageDescriptor(getImageDescriptor(iconPath)); + return action; + } + + public TableColumnLayout createTableColumnLayout(Table table, String[] columns) { + TableColumnLayout tableColumnLayout = new TableColumnLayout(); + ColumnLayoutData defaultColumnLayoutData = new ColumnWeightData(100); + + for (String columnName : columns) { + TableColumn column = new TableColumn(table, SWT.LEFT); + column.setText(columnName); + + tableColumnLayout.setColumnData(column, defaultColumnLayoutData); + } + + return tableColumnLayout; + } + + /** + * Creates a filter for given structured viewer that will filter the contents of the viewer based on the current + * text of the text field + * + * @param viewer + * Structured viewer for which the filter is to be created + * @param filterText + * The text field whose contents are to be used for filtering + * @param caseSensitive + * Flag indicating whether the filtering should be case sensitive + * @return The newly created filter + */ + public EntityViewerFilter createFilter(final StructuredViewer viewer, final Text filterText, boolean caseSensitive) { + final String initialFilterString = filterText.getText(); + + final EntityViewerFilter filter = new EntityViewerFilter(initialFilterString, caseSensitive); + // On every keystroke inside the text field, update the filter string + filterText.addKeyListener(new KeyAdapter() { + private String filterString = initialFilterString; + + @Override + public void keyReleased(KeyEvent e) { + String enteredString = filterText.getText(); + if (enteredString.equals(filterString)) { + // Filter string has not changed. don't do anything + return; + } + + // Update filter string + filterString = enteredString; + filter.setFilterString(filterString); + + // Refresh viewer with newly filtered content + viewer.refresh(true); + if(viewer instanceof TreeViewer) { + ((TreeViewer)viewer).expandAll(); + } + } + }); + + viewer.addFilter(filter); + return filter; + } + + public IViewPart getView(String viewId) { + IViewReference[] views = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getViewReferences(); + for (IViewReference view : views) { + if (view.getId().equals(viewId)) { + return view.getView(false); + } + } + return null; + } + + public IWorkbenchPart getActiveView() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart(); + } + + public ControlDecoration createErrorDecoration(Control control) { + ControlDecoration passwordErrorDecoration = new ControlDecoration(control, SWT.LEFT | SWT.TOP); + passwordErrorDecoration.setImage(FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage()); + return passwordErrorDecoration; + } + + public void centerShellInScreen(Shell shell) { + Rectangle monitorBounds = shell.getMonitor().getBounds(); + Rectangle myBounds = shell.getBounds(); + + int x = monitorBounds.x + (monitorBounds.width - myBounds.width) / 2; + int y = monitorBounds.y + (monitorBounds.height - myBounds.height) / 2; + shell.setLocation(x, y); + } + + public Text createFilterText(FormToolkit toolkit, Composite parent) { + final String tooltipMessage = "Start typing to filter table contents."; + final Text filterText = toolkit.createText(parent, "", SWT.FLAT); + + GridData data = new GridData(SWT.RIGHT, SWT.CENTER, false, false); + data.widthHint = 300; + filterText.setLayoutData(data); + + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.LEFT); + searchDecoration.setImage(getImage(IImageKeys.SEARCH_22x22)); + searchDecoration.show(); + searchDecoration.setShowHover(true); + searchDecoration.setDescriptionText(tooltipMessage); + searchDecoration.setMarginWidth(5); + + filterText.setToolTipText(tooltipMessage); + return filterText; + } + + public Text createFilterText(Composite parent) { + final String tooltipMessage = "Start typing to filter table contents."; + final Text filterText = new Text(parent, SWT.FLAT); + + GridData data = new GridData(SWT.LEFT, SWT.CENTER, false, false); + data.widthHint = 300; + filterText.setLayoutData(data); + + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.RIGHT); + searchDecoration.setImage(getImage(IImageKeys.SEARCH_22x22)); + searchDecoration.show(); + searchDecoration.setShowHover(true); + searchDecoration.setDescriptionText(tooltipMessage); + + filterText.setToolTipText(tooltipMessage); + return filterText; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, int columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + * + * @return The table viewer column created + */ + public TableViewerColumn setColumnProperties(TableViewer tableViewer, int columnIndex, int style, int weight) { + TableViewerColumn column = new TableViewerColumn(tableViewer, style, columnIndex); + TableColumnLayout tableColumnLayout = (TableColumnLayout) tableViewer.getTable().getParent().getLayout(); + tableColumnLayout.setColumnData(column.getColumn(), new ColumnWeightData(weight)); + column.setLabelProvider(new ColumnLabelProvider()); + return column; + } + + /** + * Fetches the currently selected objects from the workbench site and returns the one of given type. If none of the + * selected objects are of given type, returns null + * + * @param site + * The workbench site + * @param expectedType + * Type of the selected object to look for + * @return The selected object of given type if found, else null + */ + public T getSelectedEntity(IWorkbenchSite site, Class expectedType) { + return getSelectedEntity(site.getWorkbenchWindow(), expectedType); + } + + @SuppressWarnings({ "unchecked" }) + public T getSelectedEntity(IWorkbenchWindow window, Class expectedType) { + ISelection selection = window.getSelectionService().getSelection(NavigationView.ID); + if (selection instanceof IStructuredSelection) { + Iterator iter = ((IStructuredSelection) selection).iterator(); + while (iter.hasNext()) { + Object selectedObj = iter.next(); + if (selectedObj.getClass() == expectedType) { + return (T)selectedObj; + } + } + } + return null; + } + + /** + * Fetches the currently selected objects from the workbench site and returns those of given type. If none of the + * selected objects are of given type, returns null + * + * @param site + * The workbench site + * @param expectedType + * Type of the selected objects to look for + * @return The selected objects of given type if found, else null + */ + public Set getSelectedEntities(IWorkbenchSite site, Class expectedType) { + return getSelectedEntities(site.getWorkbenchWindow(), expectedType); + } + + @SuppressWarnings("unchecked") + public Set getSelectedEntities(IWorkbenchWindow window, Class expectedType) { + Set selectedEntities = new HashSet(); + ISelection selection = window.getSelectionService().getSelection(); + if (selection instanceof IStructuredSelection) { + Iterator iter = ((IStructuredSelection) selection).iterator(); + while (iter.hasNext()) { + Object selectedObj = iter.next(); + if (selectedObj.getClass() == expectedType) { + selectedEntities.add((T) selectedObj); + } + } + } + return selectedEntities; + } + + + public void configureCheckboxTableViewer(final CheckboxTableViewer tableViewer) { + tableViewer.addCheckStateListener(new ICheckStateListener() { + + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + tableViewer.setSelection(new StructuredSelection(tableViewer.getCheckedElements())); + } + }); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @SuppressWarnings("unchecked") + @Override + public void selectionChanged(SelectionChangedEvent event) { + List checkedElements = Arrays.asList(tableViewer.getCheckedElements()); + List selectedElements = ((IStructuredSelection)event.getSelection()).toList(); + + if (JavaUtil.listsDiffer(checkedElements, selectedElements)) { + tableViewer.setSelection(new StructuredSelection(tableViewer.getCheckedElements())); + } + } + }); + } + + public void showProgressView() { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .showView(IProgressConstants.PROGRESS_VIEW_ID); + } catch (PartInitException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Could not open the progress view!", e); + } + } + + public void showTaskView() { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .showView( TasksView.ID ); + } catch (PartInitException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Could not open the task progress view!", e); + } + } + + public void setStatusMessage(String message) { + Application.getApplication().getStatusLineManager().setMessage(message); + } + + public void clearStatusMessage() { + Application.getApplication().getStatusLineManager().setMessage(null); + } + + public String getDiskToolTip(Disk disk) { + return disk.getQualifiedName() + " - " + disk.getDescription(); + } + + public void clearSection(Composite section) { + if (section.isDisposed()) { + return; + } + for(Control control : section.getChildren()) { + if(! control.isDisposed()) { + control.dispose(); + } + } + section.layout(true); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterChartPalette.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterChartPalette.java new file mode 100644 index 00000000..3c5b0b62 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterChartPalette.java @@ -0,0 +1,479 @@ +/*********************************************************************** + * Copyright (c) 2004 Actuate Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Actuate Corporation - initial API and implementation + ***********************************************************************/ + +package com.gluster.storage.management.console.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.birt.chart.engine.i18n.Messages; +import org.eclipse.birt.chart.log.ILogger; +import org.eclipse.birt.chart.log.Logger; +import org.eclipse.birt.chart.model.attribute.AttributeFactory; +import org.eclipse.birt.chart.model.attribute.AttributePackage; +import org.eclipse.birt.chart.model.attribute.ColorDefinition; +import org.eclipse.birt.chart.model.attribute.Fill; +import org.eclipse.birt.chart.model.attribute.Palette; +import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.NotificationChain; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.emf.ecore.impl.ENotificationImpl; +import org.eclipse.emf.ecore.impl.EObjectImpl; +import org.eclipse.emf.ecore.util.EObjectContainmentEList; +import org.eclipse.emf.ecore.util.InternalEList; + +import com.ibm.icu.util.ULocale; + +/** + * An implementation of the model object ' + * Palette'. + *

    + * The following features are implemented: + *

      + *
    • {@link org.eclipse.birt.chart.model.attribute.impl.GlusterChartPalette#getName Name}
    • + *
    • {@link org.eclipse.birt.chart.model.attribute.impl.GlusterChartPalette#getEntries Entries}
    • + *
    + *

    + * + * @generated + */ +public class GlusterChartPalette extends EObjectImpl implements Palette +{ + + /** + * The default value of the '{@link #getName() Name}' attribute. + * + * @see #getName() + * @generated + * @ordered + */ + protected static final String NAME_EDEFAULT = null; + + /** + * The cached value of the '{@link #getName() Name}' attribute. + * + * @see #getName() + * @generated + * @ordered + */ + protected String name = NAME_EDEFAULT; + + /** + * The cached value of the '{@link #getEntries() Entries}' containment reference list. + * + * @see #getEntries() + * @generated + * @ordered + */ + protected EList entries; + + private static ILogger logger = Logger.getLogger( "org.eclipse.birt.chart.engine/model.attribute.impl" ); //$NON-NLS-1$ + + private static List colorLib = new ArrayList( 32 ); + static + { + colorLib.add( ColorDefinitionImpl.create ( 0, 1, 252) ); + colorLib.add( ColorDefinitionImpl.create ( 255, 0, 255) ); + //colorLib.add( ColorDefinitionImpl.BLUE() ); + //colorLib.add( ColorDefinitionImpl.create( 232, 172, 57 ) ); + } + + /** + * + * @generated + */ + public GlusterChartPalette( ) + { + super( ); + } + + /** + * + * @generated + */ + @Override + protected EClass eStaticClass( ) + { + return AttributePackage.Literals.PALETTE; + } + + /** + * + * @generated + */ + public String getName( ) + { + return name; + } + + /** + * + * @generated + */ + public void setName( String newName ) + { + String oldName = name; + name = newName; + if ( eNotificationRequired( ) ) + eNotify( new ENotificationImpl( this, + Notification.SET, + AttributePackage.PALETTE__NAME, + oldName, + name ) ); + } + + /** + * + * @generated + */ + public EList getEntries( ) + { + if ( entries == null ) + { + entries = new EObjectContainmentEList( Fill.class, + this, + AttributePackage.PALETTE__ENTRIES ); + } + return entries; + } + + /** + * + * + * @generated + */ + @Override + public NotificationChain eInverseRemove( InternalEObject otherEnd, + int featureID, NotificationChain msgs ) + { + switch ( featureID ) + { + case AttributePackage.PALETTE__ENTRIES : + return ( (InternalEList) getEntries( ) ).basicRemove( otherEnd, + msgs ); + } + return super.eInverseRemove( otherEnd, featureID, msgs ); + } + + /** + * + * + * @generated + */ + @Override + public Object eGet( int featureID, boolean resolve, boolean coreType ) + { + switch ( featureID ) + { + case AttributePackage.PALETTE__NAME : + return getName( ); + case AttributePackage.PALETTE__ENTRIES : + return getEntries( ); + } + return super.eGet( featureID, resolve, coreType ); + } + + /** + * + * + * @generated + */ + @SuppressWarnings("unchecked") + @Override + public void eSet( int featureID, Object newValue ) + { + switch ( featureID ) + { + case AttributePackage.PALETTE__NAME : + setName( (String) newValue ); + return; + case AttributePackage.PALETTE__ENTRIES : + getEntries( ).clear( ); + getEntries( ).addAll( (Collection) newValue ); + return; + } + super.eSet( featureID, newValue ); + } + + /** + * + * + * @generated + */ + @Override + public void eUnset( int featureID ) + { + switch ( featureID ) + { + case AttributePackage.PALETTE__NAME : + setName( NAME_EDEFAULT ); + return; + case AttributePackage.PALETTE__ENTRIES : + getEntries( ).clear( ); + return; + } + super.eUnset( featureID ); + } + + /** + * + * + * @generated + */ + @Override + public boolean eIsSet( int featureID ) + { + switch ( featureID ) + { + case AttributePackage.PALETTE__NAME : + return NAME_EDEFAULT == null ? name != null + : !NAME_EDEFAULT.equals( name ); + case AttributePackage.PALETTE__ENTRIES : + return entries != null && !entries.isEmpty( ); + } + return super.eIsSet( featureID ); + } + + /** + * + * @generated + */ + @Override + public String toString( ) + { + if ( eIsProxy( ) ) + return super.toString( ); + + StringBuffer result = new StringBuffer( super.toString( ) ); + result.append( " (name: " ); //$NON-NLS-1$ + result.append( name ); + result.append( ')' ); + return result.toString( ); + } + + /** + * A convenience method provided to create an empty or pre-initialized + * palette + * + * NOTE: Manually written + * + * @param bEmpty + */ + public static final Palette create( int iIndex, boolean bEmpty ) + { + final Palette p = AttributeFactory.eINSTANCE.createPalette( ); + + if ( !bEmpty ) + { + p.shift( iIndex ); + } + return p; + } + + /** + * A convenience method provided to create a palette with a single color + * entry + * + * NOTE: Manually written + * + * @param f + */ + public static final Palette create( Fill f ) + { + final Palette p = AttributeFactory.eINSTANCE.createPalette( ); + p.getEntries( ).add( f ); + return p; + } + + /** + * Shift the list content from tail to head. + * + * @param lst + * @param pos + */ + private static final void shiftList( final List lst, int pos ) + { + int size = lst.size( ); + + if ( pos < 1 ) + { + pos = 0; + } + + if ( pos >= size ) + { + pos = pos % size; + } + + if ( pos == 0 ) + { + return; + } + + Object[] array = lst.toArray( ); + + lst.clear( ); + + for ( int i = pos; i < array.length; i++ ) + { + lst.add( array[i] ); + } + + for ( int i = 0; i < pos; i++ ) + { + lst.add( array[i] ); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.model.attribute.Palette#update(int) + */ + public final void update( int iIndex ) + { + final EList el = getEntries( ); + el.clear( ); + if ( iIndex < 0 ) + { + // a rotation version of palette-0, rataion pos is the negatvie + // index. + ArrayList al = new ArrayList( ); + + al.add( ColorDefinitionImpl.create( 80, 166, 218 ) ); + al.add( ColorDefinitionImpl.create( 242, 88, 106 ) ); + al.add( ColorDefinitionImpl.create( 232, 172, 57 ) ); + al.add( ColorDefinitionImpl.create( 128, 255, 128 ) ); + al.add( ColorDefinitionImpl.create( 64, 128, 128 ) ); + al.add( ColorDefinitionImpl.create( 128, 128, 192 ) ); + al.add( ColorDefinitionImpl.create( 170, 85, 85 ) ); + al.add( ColorDefinitionImpl.create( 128, 128, 0 ) ); + + shiftList( al, -iIndex ); + + el.addAll( al ); + } + else if ( iIndex == 0 ) + { + el.add( ColorDefinitionImpl.create( 80, 166, 218 ) ); + el.add( ColorDefinitionImpl.create( 242, 88, 106 ) ); + el.add( ColorDefinitionImpl.create( 232, 172, 57 ) ); + el.add( ColorDefinitionImpl.create( 128, 255, 128 ) ); + el.add( ColorDefinitionImpl.create( 64, 128, 128 ) ); + el.add( ColorDefinitionImpl.create( 128, 128, 192 ) ); + el.add( ColorDefinitionImpl.create( 170, 85, 85 ) ); + el.add( ColorDefinitionImpl.create( 128, 128, 0 ) ); + } + else if ( iIndex == 1 ) + { + el.add( ColorDefinitionImpl.create( 225, 225, 255 ) ); + el.add( ColorDefinitionImpl.create( 223, 197, 41 ) ); + el.add( ColorDefinitionImpl.create( 249, 225, 191 ) ); + el.add( ColorDefinitionImpl.create( 255, 205, 225 ) ); + el.add( ColorDefinitionImpl.create( 225, 255, 225 ) ); + el.add( ColorDefinitionImpl.create( 255, 191, 255 ) ); + el.add( ColorDefinitionImpl.create( 185, 185, 221 ) ); + el.add( ColorDefinitionImpl.create( 40, 255, 148 ) ); + } + else + { + logger.log( ILogger.WARNING, + Messages.getString( "error.unknown.palette", //$NON-NLS-1$ + new Object[]{ + Integer.valueOf( iIndex ) + }, + ULocale.getDefault( ) ) ); + update( 0 ); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.model.attribute.Palette#update(org.eclipse.birt.chart.model.attribute.Fill) + */ + public final void update( Fill f ) + { + final EList el = getEntries( ); + el.clear( ); + el.add( f ); + } + + public void shift( int step ) + { + shift( step, colorLib.size( ) ); + } + + public void shift( int step, int size ) + { + if ( size <= 0 || size > colorLib.size( ) ) + { + size = colorLib.size( ); + } + + final EList el = getEntries( ); + el.clear( ); + + if ( step == 0 || Math.abs( step ) >= size ) + { + // Do nothing + step = 0; + } + else if ( step < 0 ) + { + // Move to the left side + step = -step; + } + else if ( step > 0 ) + { + // Move to the right side + step = size - step; + } + + for ( int i = step; i < size; i++ ) + { + el.add( ( (ColorDefinition) colorLib.get( i ) ).copyInstance( ) ); + } + for ( int i = 0; i < step; i++ ) + { + el.add( ( (ColorDefinition) colorLib.get( i ) ).copyInstance( ) ); + } + } + + /** + * A convenient method to get an instance copy. This is much faster than the + * ECoreUtil.copy(). + */ + public Palette copyInstance( ) + { + GlusterChartPalette dest = new GlusterChartPalette( ); + dest.set( this ); + return dest; + } + + protected void set( Palette src ) + { + if ( src.getEntries( ) != null ) + { + EList list = getEntries( ); + for ( Fill element : src.getEntries( ) ) + { + list.add( element.copyInstance( ) ); + } + } + name = src.getName( ); + } + +} // GlusterChartPalette diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterLogger.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterLogger.java new file mode 100644 index 00000000..b633678a --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/GlusterLogger.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.utils; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.Status; + +import com.gluster.storage.management.console.Activator; + +/** + * + */ +public class GlusterLogger { + private static final ILog log = Activator.getDefault().getLog(); + private static GlusterLogger instance = new GlusterLogger(); + + private GlusterLogger() { + } + + public static GlusterLogger getInstance() { + return instance; + } + + private void log(String message, int severity, Throwable t) { + log.log(new Status(severity, Activator.PLUGIN_ID, message, t)); + } + + public void error(String message) { + log(message, Status.ERROR, null); + } + + public void error(String message, Throwable t) { + log(message, Status.ERROR, t); + } + + public void warn(String message) { + log(message, Status.WARNING, null); + } + + public void warn(String message, Throwable t) { + log(message, Status.WARNING, t); + } + + public void info(String message) { + log(message, Status.INFO, null); + } + + public void info(String message, Throwable t) { + log(message, Status.INFO, t); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ImageUtil.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ImageUtil.java new file mode 100644 index 00000000..d278704b --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/utils/ImageUtil.java @@ -0,0 +1,52 @@ +/** + * ImageUtil.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.utils; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.console.Application; +import com.gluster.storage.management.core.utils.LRUCache; + +/** + * + */ +public class ImageUtil { + private static final LRUCache imageCache = new LRUCache(20); + + public ImageDescriptor getImageDescriptor(String imagePath) { + return AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, imagePath); + } + + public synchronized Image getImage(String imagePath) { + if(imageCache.containsKey(imagePath)) { + return imageCache.get(imagePath); + } + return createImage(imagePath); + } + + private Image createImage(String imagePath) { + Image image = getImageDescriptor(imagePath).createImage(); + imageCache.put(imagePath, image); + return image; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/validators/StringRequiredValidator.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/validators/StringRequiredValidator.java new file mode 100644 index 00000000..cac65829 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/validators/StringRequiredValidator.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.validators; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.widgets.Control; + +public class StringRequiredValidator implements IValidator { + protected final String errorText; + protected final ControlDecoration controlDecoration; + protected final Control linkedControl; + + public StringRequiredValidator(String errorText, ControlDecoration controlDecoration, Control linkedControl) { + super(); + this.errorText = errorText; + this.controlDecoration = controlDecoration; + this.linkedControl = linkedControl; + } + + public StringRequiredValidator(String errorText, ControlDecoration controlDecoration) { + this(errorText, controlDecoration, null); + } + + public IStatus validate(Object value) { + if (value instanceof String) { + if (((String) value).isEmpty()) { + controlDecoration.setDescriptionText(errorText); + controlDecoration.show(); + if (linkedControl != null) { + linkedControl.setEnabled(false); + } + return ValidationStatus.error(errorText); + } + } + if(linkedControl != null) { + linkedControl.setEnabled(true); + } + controlDecoration.hide(); + return Status.OK_STATUS; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterAdapterFactory.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterAdapterFactory.java new file mode 100644 index 00000000..d904c8f3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterAdapterFactory.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.console.Application; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +public class ClusterAdapterFactory implements IAdapterFactory { + private IWorkbenchAdapter entityAdapter = new IWorkbenchAdapter() { + + @Override + public Object getParent(Object o) { + return ((Entity) o).getParent(); + } + + @Override + public String getLabel(Object o) { + return ((Entity)o).getName(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public ImageDescriptor getImageDescriptor(Object object) { + String iconPath = null; + + if(object instanceof GlusterDataModel || object instanceof Cluster) { + iconPath = IImageKeys.CLUSTER_16x16; + } + + if(object instanceof EntityGroup) { + Class entityType = ((EntityGroup) object).getEntityType(); + if(entityType == Volume.class) { + iconPath = IImageKeys.VOLUMES_16x16; + } else { + iconPath = IImageKeys.SERVERS_16x16; + } + } + + if(object instanceof Volume) { + iconPath = IImageKeys.VOLUME_16x16; + } + + if(object instanceof Server || object instanceof GlusterServer) { + iconPath = IImageKeys.SERVER_16x16; + } + + return AbstractUIPlugin.imageDescriptorFromPlugin( + Application.PLUGIN_ID, iconPath); + } + + @Override + public Object[] getChildren(Object o) { + return ((Entity)o).getChildren().toArray(); + } + }; + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (adapterType == IWorkbenchAdapter.class) { + if (adaptableObject instanceof Entity) { + return entityAdapter; + } + } + return null; + } + + @SuppressWarnings("rawtypes") + @Override + public Class[] getAdapterList() { + return new Class[] { IWorkbenchAdapter.class }; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterSummaryView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterSummaryView.java new file mode 100644 index 00000000..436b7134 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ClusterSummaryView.java @@ -0,0 +1,433 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.Activator; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.actions.IActionConstants; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.console.utils.ChartUtil; +import com.gluster.storage.management.console.utils.ChartViewerComposite; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.utils.ChartUtil.ChartPeriodLinkListener; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.utils.NumberUtil; + +/** + * + */ +public class ClusterSummaryView extends ViewPart { + public static final String ID = ClusterSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Cluster cluster; + private Composite cpuChartSection; + private Composite networkChartSection; + private GlusterDataModel model = GlusterDataModelManager.getInstance().getModel(); + private ClusterListener clusterListener; + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + private Composite alertsSection; + private Composite tasksSection; + private static final ChartUtil chartUtil = ChartUtil.getInstance(); + private IPropertyChangeListener propertyChangeListener; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (cluster == null) { + cluster = model.getCluster(); + } + setPartName("Summary"); + createSections(parent); + + createListeners(); + } + + private void createListeners() { + createClusterListener(); + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + createPropertyChangeListener(); + preferenceStore.addPropertyChangeListener(propertyChangeListener ); + } + + private void createPropertyChangeListener() { + propertyChangeListener = new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + String preferenceName = event.getProperty(); + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + if(preferenceName.equals(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD)) { + modelManager.initializeAggregatedCpuStats(cluster); + String cpuStatsPeriod = (String)event.getNewValue(); + refreshChartSection(cpuChartSection, cluster.getAggregatedCpuStats(), cpuStatsPeriod, "%", 100, 4, + chartUtil.new CpuChartPeriodLinkListener(null, cpuStatsPeriod, toolkit), 2); + } else if(preferenceName.equals(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD)) { + modelManager.initializeAggregatedNetworkStats(cluster); + String networkStatsPeriod = (String)event.getNewValue(); + refreshChartSection(networkChartSection, cluster.getAggregatedNetworkStats(), networkStatsPeriod, "KiB/s", -1, + 4, chartUtil.new NetworkChartPeriodLinkListener(null, networkStatsPeriod, toolkit), 2); + } + } + }; + } + + private void createClusterListener() { + clusterListener = new DefaultClusterListener() { + @Override + public void aggregatedStatsChanged() { + super.aggregatedStatsChanged(); + refreshCharts(); + } + + @Override + public void alertsGenerated() { + super.alertsGenerated(); + guiHelper.clearSection(alertsSection); + populateAlerts(); + } + + @Override + public void taskAdded(TaskInfo taskInfo) { + super.taskAdded(taskInfo); + updateTaskSection(); + } + + @Override + public void taskRemoved(TaskInfo taskInfo) { + super.taskRemoved(taskInfo); + updateTaskSection(); + } + + @Override + public void taskUpdated(TaskInfo taskInfo) { + super.taskUpdated(taskInfo); + updateTaskSection(); + } + + private void updateTaskSection() { + guiHelper.clearSection(tasksSection); + populateTasksSection(); + } + }; + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + preferenceStore.removePropertyChangeListener(propertyChangeListener); + } + + private void refreshCharts() { + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD); + refreshChartSection(cpuChartSection, cluster.getAggregatedCpuStats(), cpuStatsPeriod, "%", 100, 4, + chartUtil.new CpuChartPeriodLinkListener(null, cpuStatsPeriod, toolkit), 2); + refreshChartSection(networkChartSection, cluster.getAggregatedNetworkStats(), networkStatsPeriod, "KiB/s", -1, + 4, chartUtil.new NetworkChartPeriodLinkListener(null, networkStatsPeriod, toolkit), 2); + } + + private int getServerCountByStatus(Cluster cluster, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createServersSection() { + Composite section = guiHelper.createSection(form, toolkit, "Servers", null, 2, false); + + int onlineServerCount = getServerCountByStatus(cluster, SERVER_STATUS.ONLINE); + int offlineServerCount = getServerCountByStatus(cluster, SERVER_STATUS.OFFLINE); + + toolkit.createLabel(section, "Online : "); + Label label = toolkit.createLabel(section, "" + onlineServerCount); + label.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN)); + + toolkit.createLabel(section, "Offline : "); + label = toolkit.createLabel(section, "" + offlineServerCount); + label.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); + } + + private void createDiskSpaceSection() { + Composite section = guiHelper.createSection(form, toolkit, "Disk Space", null, 3, false); + if (cluster.getServers().size() == 0) { + toolkit.createLabel(section, "This section will be populated after at least" + CoreConstants.NEWLINE + + "one server is added to the storage cloud."); + return; + } + + double totalDiskSpace = cluster.getTotalDiskSpace(); + double diskSpaceInUse = cluster.getDiskSpaceInUse(); + Double[] values = new Double[] { diskSpaceInUse, totalDiskSpace - diskSpaceInUse }; + createDiskSpaceChart(section, values); + } + + private void createDiskSpaceChart(Composite section, Double[] values) { + String[] categories = new String[] { "Used Space: " + NumberUtil.formatNumber((values[0] / 1024)) + " GB", + "Free Space: " + NumberUtil.formatNumber((values[1] / 1024)) + " GB" }; + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = 400; + data.heightHint = 170; + data.verticalAlignment = SWT.CENTER; + chartViewerComposite.setLayoutData(data); + } + + private void createAlertsSection() { + alertsSection = guiHelper.createSection(form, toolkit, "Alerts", null, 1, false); + populateAlerts(); + } + + private void populateAlerts() { + List alerts = cluster.getAlerts(); + for (Alert alert : alerts) { + addAlertLabel(alertsSection, alert); + } + alertsSection.layout(); + form.reflow(true); + } + + private void addAlertLabel(Composite section, Alert alert) { + CLabel lblAlert = new CLabel(section, SWT.FLAT); + Image alertImage = null; + switch (alert.getType()) { + case OFFLINE_VOLUME_BRICKS_ALERT: + alertImage = guiHelper.getImage(IImageKeys.BRICK_OFFLINE_22x22); + break; + case DISK_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.LOW_DISK_SPACE_22x22); + break; + case OFFLINE_SERVERS_ALERT: + alertImage = guiHelper.getImage(IImageKeys.SERVER_OFFLINE_22x22); + break; + case MEMORY_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.MEMORY_USAGE_ALERT_22x22); + break; + case CPU_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.SERVER_WARNING_22x22); + break; + } + lblAlert.setImage(alertImage); + lblAlert.setText(alert.getMessage()); + lblAlert.redraw(); + } + + private void createActionsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Actions", null, 1, false); + + ImageHyperlink imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Create Volume"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.CREATE_VOLUME_48x48)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(HyperlinkEvent e) { + IHandlerService hs = (IHandlerService) getSite().getService(IHandlerService.class); + try { + hs.executeCommand(IActionConstants.COMMAND_CREATE_VOLUME, null); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + }); + + imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Add Server(s)"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.ADD_SERVER_48x48)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(HyperlinkEvent e) { + // Open the "discovered servers" view by selecting the corresponding entity in the navigation view + EntityGroup autoDiscoveredServersEntityGroup = GlusterDataModelManager.getInstance().getModel() + .getCluster().getEntityGroup(Server.class); + + NavigationView navigationView = (NavigationView) guiHelper.getView(NavigationView.ID); + navigationView.selectEntity(autoDiscoveredServersEntityGroup); + } + }); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Cluster Summary"); + + if (cluster.getServers().size() > 0 + && (cluster.getAggregatedCpuStats().getRows() == null || cluster.getAggregatedNetworkStats().getRows() == null)) { + // cluster has servers, but stats are null. Happens when user logs in to a new cluster, ' + // and then adds the first server. + GlusterDataModelManager.getInstance().initializeAggregatedCpuStats(cluster); + GlusterDataModelManager.getInstance().initializeAggregatedNetworkStats(cluster); + } + + createServersSection(); + createDiskSpaceSection(); + createCPUUsageSection(); + createNetworkUsageSection(); + createActionsSection(); + createAlertsSection(); + createRunningTasksSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private Composite createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit, String timestampFormat, ChartPeriodLinkListener listener, double maxValue, int chartLinkColumnCount) { + Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); + if (cluster.getServers().size() == 0) { + toolkit.createLabel(section, "This section will be populated after at least" + CoreConstants.NEWLINE + + "one server is added to the storage cloud."); + return null; + } + + ChartUtil.getInstance().createAreaChart(toolkit, section, stats, dataColumnIndex, unit, timestampFormat, listener, maxValue, chartLinkColumnCount); + return section; + } + + private void createCPUUsageSection() { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_AGGREGATED_CHART_PERIOD); + + // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. + cpuChartSection = createAreaChartSection(cluster.getAggregatedCpuStats(), "CPU Usage (Aggregated)", 2, "%", + getTimestampFormatForPeriod(cpuStatsPeriod), chartUtil.new CpuChartPeriodLinkListener(null, + cpuStatsPeriod, toolkit), 100, 4); + } + + private String getTimestampFormatForPeriod(String statsPeriod) { + if(statsPeriod.equals(GlusterConstants.STATS_PERIOD_1DAY)) { + return "HH:mm"; + } else if (statsPeriod.equals(GlusterConstants.STATS_PERIOD_1WEEK)) { + return "dd-MMM HH:mm"; + } else { + return "dd-MMM"; + } + } + + private void createNetworkUsageSection() { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_AGGREGATED_CHART_PERIOD); + + // in case of network usage, there are three elements in usage data: received, transmitted and total. we use total. + networkChartSection = createAreaChartSection(cluster.getAggregatedNetworkStats(), "Network Usage (Aggregated)", + 2, "KiB/s", getTimestampFormatForPeriod(networkStatsPeriod), + chartUtil.new NetworkChartPeriodLinkListener(null, networkStatsPeriod, toolkit), -1, 4); + } + + private void createRunningTasksSection() { + tasksSection = guiHelper.createSection(form, toolkit, "Running Tasks", null, 1, false); + populateTasksSection(); + } + + private void populateTasksSection() { + for (TaskInfo taskInfo : cluster.getTaskInfoList()) { + addTaskLabel(tasksSection, taskInfo); + } + tasksSection.layout(); + form.reflow(true); + } + + private void addTaskLabel(Composite section, TaskInfo taskInfo) { + //TODO: create link and open the task progress view + CLabel lblAlert = new CLabel(section, SWT.NONE); + lblAlert.setText(taskInfo.getDescription()); + + Image taskImage = null; + switch(taskInfo.getType()) { + case DISK_FORMAT: + taskImage = guiHelper.getImage(IImageKeys.DISK_INITIALIZING_22x22); + break; + case BRICK_MIGRATE: + taskImage = guiHelper.getImage(IImageKeys.BRICK_MIGRATE_22x22); + break; + case VOLUME_REBALANCE: + taskImage = guiHelper.getImage(IImageKeys.VOLUME_REBALANCE_22x22); + break; + } + lblAlert.setImage(taskImage); + lblAlert.redraw(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } + + private void refreshChartSection(Composite section, ServerStats stats, String statsPeriod, String unit, + double maxValue, int columnCount, ChartPeriodLinkListener linkListener, int dataColumnIndex) { + for (Control control : section.getChildren()) { + if (!control.isDisposed()) { + control.dispose(); + } + } + chartUtil.createAreaChart(toolkit, section, stats, dataColumnIndex, unit, + getTimestampFormatForPeriod(statsPeriod), linkListener, maxValue, columnCount); + section.layout(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServerView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServerView.java new file mode 100644 index 00000000..96a2ca2a --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServerView.java @@ -0,0 +1,90 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; + +/** + * @author root + * + */ +public class DiscoveredServerView extends ViewPart { + public static final String ID = DiscoveredServerView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Server server; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (Server) guiHelper.getSelectedEntity(getSite(), Server.class); + } + createSections(parent); + } + + private void createServerSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber((server.getTotalMemory() / 1024)), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber((server.getTotalDiskSpace() / 1024)), SWT.NONE); + } + + private void createSections(Composite parent) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(); + + parent.layout(); // IMP: lays out the form properly + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServersView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServersView.java new file mode 100644 index 00000000..ab3cd556 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DiscoveredServersView.java @@ -0,0 +1,83 @@ +/** + * DiscoveredServersView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.ServersPage; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; + +/** + * + */ +public class DiscoveredServersView extends ViewPart implements IDoubleClickListener { + public static final String ID = DiscoveredServersView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup servers; + private ServersPage page; + + public DiscoveredServersView() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Server.class) { + servers = (EntityGroup)selectedObj; + } + } + + page = new ServersPage(parent, getSite(), servers); + page.addDoubleClickListener(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DisksView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DisksView.java new file mode 100644 index 00000000..b0cf33b2 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/DisksView.java @@ -0,0 +1,45 @@ +package com.gluster.storage.management.console.views; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.DisksPage; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; + +public class DisksView extends ViewPart { + public static final String ID = DisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup servers; + private DisksPage page; + + @SuppressWarnings("unchecked") + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + page = new DisksPage(parent, SWT.NONE, getSite(), getAllDisks(servers)); + //page.layout(); // IMP: lays out the form properly + } + + private List getAllDisks(EntityGroup servers) { + List disks = new ArrayList(); + for(GlusterServer server : (List)servers.getEntities()) { + disks.addAll(server.getDisks()); + } + return disks; + } + + @Override + public void setFocus() { + page.setFocus(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerDisksView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerDisksView.java new file mode 100644 index 00000000..951b5a91 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerDisksView.java @@ -0,0 +1,84 @@ +/** + * GlusterServerDisksView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.ServerDisksPage; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterServer; + +public class GlusterServerDisksView extends ViewPart { + public static final String ID = GlusterServerDisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private ClusterListener clusterListener; + private GlusterServer server; + private ServerDisksPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + page = new ServerDisksPage(parent, SWT.NONE, getSite(), server.getDisks()); + + final ViewPart thisView = this; + clusterListener = new DefaultClusterListener() { + @Override + public void serverChanged(GlusterServer server, Event event) { + super.serverChanged(server, event); + if(event.getEventType() == EVENT_TYPE.GLUSTER_SERVER_CHANGED) { + if(!server.isOnline()) { + getViewSite().getPage().hideView(thisView); + } + } + } + }; + + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerLogsView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerLogsView.java new file mode 100644 index 00000000..660da5a3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerLogsView.java @@ -0,0 +1,59 @@ +/** + * GlusterServerLogsView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.ServerLogsPage; +import com.gluster.storage.management.core.model.GlusterServer; + +public class GlusterServerLogsView extends ViewPart { + public static final String ID = GlusterServerLogsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private GlusterServer server; + private ServerLogsPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + + page = new ServerLogsPage(parent, SWT.NONE, server); + + parent.layout(); // IMP: lays out the form properly + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerSummaryView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerSummaryView.java new file mode 100644 index 00000000..662ca16f --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServerSummaryView.java @@ -0,0 +1,513 @@ +/** + * GlusterServerSummaryView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.birt.chart.util.CDateTime; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.console.Activator; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.console.preferences.PreferenceConstants; +import com.gluster.storage.management.console.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.console.utils.ChartUtil; +import com.gluster.storage.management.console.utils.ChartViewerComposite; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.utils.GlusterLogger; +import com.gluster.storage.management.console.utils.ChartUtil.ChartPeriodLinkListener; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.ibm.icu.util.Calendar; +import com.richclientgui.toolbox.gauges.CoolGauge; + +public class GlusterServerSummaryView extends ViewPart { + public static final String ID = GlusterServerSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private GlusterServer server; + private ClusterListener clusterListener; + private static final int CHART_WIDTH = 350; + private static final int CHART_HEIGHT = 250; + private static final GlusterLogger logger = GlusterLogger.getInstance(); + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + + public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { + INTERFACE, MODEL, SPEED, IP_ADDRESS, NETMASK, GATEWAY + }; + + private static final String[] NETWORK_INTERFACE_TABLE_COLUMN_NAMES = { "Interface", "Model", "Speed", "IP Address", + "Netmask", "Gateway" }; + private CoolGauge cpuGauge; + private IPropertyChangeListener propertyChangeListener; + private Composite cpuUsageSection; + private Composite networkUsageSection; + private Composite memoryUsageSection; + private static final ChartUtil chartUtil = ChartUtil.getInstance(); + private Composite serverSummarySection; + private Label numCpus; + private ProgressBar memoryUsageBar; + private ProgressBar diskUsageBar; + private CLabel lblServerStatus; + + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + setPartName("Summary"); + createSections(parent); + + createListeners(); + } + + private void createListeners() { + // Refresh the server details whenever the server has changed + createClusterListener(); + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + createPropertyChangeListener(); + preferenceStore.addPropertyChangeListener(propertyChangeListener); + } + + private void createPropertyChangeListener() { + propertyChangeListener = new IPropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent event) { + String propertyName = event.getProperty(); + if(propertyName.equals(PreferenceConstants.P_CPU_CHART_PERIOD)) { + refreshCpuChart(); + } else if(propertyName.equals(PreferenceConstants.P_MEM_CHART_PERIOD)) { + refreshMemoryChart(); + } else if (propertyName.equals(PreferenceConstants.P_NETWORK_CHART_PERIOD) + || propertyName.equals(PreferenceConstants.P_DEFAULT_NETWORK_INTERFACE_PFX + server.getName())) { + refreshNetworkChart(); + } + } + }; + } + + private void createClusterListener() { + final GlusterToolbarManager toolbarManager = new GlusterToolbarManager(getSite().getWorkbenchWindow()); + final GlusterServer thisServer = server; + clusterListener = new DefaultClusterListener() { + + @Override + public void serverChanged(GlusterServer server, Event event) { + if (event.getEventType() == EVENT_TYPE.GLUSTER_SERVER_CHANGED && server == thisServer) { + updateServerDetails(); + toolbarManager.updateToolbar(server); + refreshCharts(); + } + } + }; + } + + private void refreshCharts() { + refreshCpuChart(); + refreshMemoryChart(); + refreshNetworkChart(); + } + + private void refreshNetworkChart() { + guiHelper.clearSection(networkUsageSection); + String statsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); + String networkInterface = preferenceStore.getString(PreferenceConstants.P_DEFAULT_NETWORK_INTERFACE_PFX + server.getName()); + if(networkInterface == null || networkInterface.isEmpty()) { + networkInterface = server.getNetworkInterfaces().get(0).getName(); + } + ServerStats stats = new GlusterServersClient().getNetworkStats(server.getName(), networkInterface, statsPeriod); + chartUtil.refreshChartSection(toolkit, networkUsageSection, stats, statsPeriod, "KiB/s", -1, 5, chartUtil.new NetworkChartPeriodLinkListener(server, statsPeriod, toolkit), 2); + } + + private void refreshMemoryChart() { + guiHelper.clearSection(memoryUsageSection); + String statsPeriod = preferenceStore.getString(PreferenceConstants.P_MEM_CHART_PERIOD); + ServerStats stats = new GlusterServersClient().getMemoryStats(server.getName(), statsPeriod); + chartUtil.refreshChartSection(toolkit, memoryUsageSection, stats, statsPeriod, "%", 100, 4, chartUtil.new MemoryChartPeriodLinkListener(server.getName(), statsPeriod, toolkit), 0); + } + + private void refreshCpuChart() { + guiHelper.clearSection(cpuUsageSection); + String statsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + ServerStats stats = new GlusterServersClient().getCpuStats(server.getName(), statsPeriod); + chartUtil.refreshChartSection(toolkit, cpuUsageSection, stats, statsPeriod, "%", 100, 4, + chartUtil.new CpuChartPeriodLinkListener(server.getName(), statsPeriod, toolkit), 2); + } + + private void updateServerDetails() { + // TODO: Update the server details (cpu usage, memory usage) + populateServerSummarySection(server); + + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + preferenceStore.removePropertyChangeListener(propertyChangeListener); + } + + private void createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit) { + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, "HH:mm", 100); + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = CHART_WIDTH; + data.heightHint = CHART_HEIGHT; + chartViewerComposite.setLayoutData(data); + } + + private void extractChartData(ServerStats stats, List timestamps, List data, int dataColumnIndex) { + for(ServerStatsRow row : stats.getRows()) { + Double cpuUsage = row.getUsageData().get(dataColumnIndex); + if(!cpuUsage.isNaN()) { + timestamps.add(new CDateTime(row.getTimestamp() * 1000)); + data.add(cpuUsage); + } + } + } + + private void createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit) { + List timestamps = new ArrayList(); + List data = new ArrayList(); + extractChartData(stats, timestamps, data, dataColumnIndex); + + if(timestamps.size() == 0) { + // Log a message saying no CPU stats available + return; + } + + Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit); + +// Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), new CDateTime(1000l*1310468700), +// new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new CDateTime(1000l*1310469900), +// new CDateTime(1000l*1310470200), new CDateTime(1000l*1310470500), new CDateTime(1000l*1310470800), new CDateTime(1000l*1310471100), +// new CDateTime(1000l*1310471400), new CDateTime(1000l*1310471700), new CDateTime(1000l*1310472000), new CDateTime(1000l*1310472300), +// new CDateTime(1000l*1310472600), new CDateTime(1000l*1310472900), new CDateTime(1000l*1310473200), new CDateTime(1000l*1310473500), +// new CDateTime(1000l*1310473800) }; +// +// Double[] values = new Double[] { 10d, 11.23d, 17.92d, 18.69d, 78.62d, 89.11d, 92.43d, 89.31d, 57.39d, 18.46d, 10.44d, 16.28d, 13.51d, 17.53d, 12.21, 20d, 21.43d, 16.45d, 14.86d, 15.27d }; +// createLineChart(section, timestamps, values, "%"); + createChartLinks(section, 4); + } + + private void createMemoryUsageSection() { + String memStatsPeriod = preferenceStore.getString(PreferenceConstants.P_MEM_CHART_PERIOD); + memoryUsageSection = guiHelper.createSection(form, toolkit, "Memory Usage", null, 1, false); + + ServerStats stats; + try { + stats = new GlusterServersClient().getMemoryStats(server.getName(), memStatsPeriod); + } catch(Exception e) { + logger.error("Couldn't fetch memory usage statistics for server [" + server.getName() + "]", e); + toolkit.createLabel(memoryUsageSection, "Couldn't fetch memory usage statistics for server [" + server.getName() + "]! Error: [" + e.getMessage() + "]"); + return; + } + + // in case of memory usage, there are four elements in usage data: user, free, cache, buffer and total. we use "user". + ChartUtil chartUtil = ChartUtil.getInstance(); + chartUtil.createAreaChart(toolkit, memoryUsageSection, stats, 0, "%", chartUtil + .getTimestampFormatForPeriod(memStatsPeriod), + chartUtil.new MemoryChartPeriodLinkListener(server.getName(), memStatsPeriod, toolkit), 100, 4); + } + + private void createCPUUsageSection() { + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + cpuUsageSection = guiHelper.createSection(form, toolkit, "CPU Usage", null, 1, false); + + ServerStats stats; + try { + stats = new GlusterServersClient().getCpuStats(server.getName(), cpuStatsPeriod); + } catch(Exception e) { + logger.error("Couldn't fetch CPU usage statistics for server [" + server.getName() + "]", e); + toolkit.createLabel(cpuUsageSection, "Couldn't fetch CPU usage statistics for server [" + server.getName() + "]! Error: [" + e.getMessage() + "]"); + return; + } + + // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. + chartUtil.createAreaChart(toolkit, cpuUsageSection, stats, 2, "%", chartUtil + .getTimestampFormatForPeriod(cpuStatsPeriod), + chartUtil.new CpuChartPeriodLinkListener(server.getName(), cpuStatsPeriod, toolkit), 100, 4); + } + + private void createNetworkUsageSection() { + final String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); + networkUsageSection = guiHelper.createSection(form, toolkit, "Network Usage", null, 1, false); + + String networkInterface = server.getNetworkInterfaces().get(0).getName(); + ServerStats stats; + try { + stats = new GlusterServersClient().getNetworkStats(server.getName(), networkInterface, networkStatsPeriod); + } catch(Exception e) { + logger.error("Couldn't fetch Network usage statistics for server [" + server.getName() + "] network interface [" + networkInterface + "]", e); + toolkit.createLabel(networkUsageSection, "Couldn't fetch CPU usage statistics for server [" + server.getName() + "]! Error: [" + e.getMessage() + "]"); + return; + } + + // in case of network usage, there are three elements in usage data: received, transmitted and total. we use total. + final ChartUtil chartUtil = ChartUtil.getInstance(); + final ChartPeriodLinkListener networkChartPeriodLinkListener = chartUtil.new NetworkChartPeriodLinkListener(server, networkStatsPeriod, toolkit); + chartUtil.createAreaChart(toolkit, networkUsageSection, stats, 2, "KiB/s", chartUtil + .getTimestampFormatForPeriod(networkStatsPeriod), + networkChartPeriodLinkListener , -1, 5); + } + + private Composite createChartLinks(Composite section, int columnCount) { + GridLayout layout = new org.eclipse.swt.layout.GridLayout(columnCount, false); + layout.marginBottom = 0; + layout.marginTop = 0; + layout.marginLeft = (CHART_WIDTH - (50*columnCount)) / 2; + Composite graphComposite = toolkit.createComposite(section, SWT.NONE); + graphComposite.setLayout(layout); + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = CHART_WIDTH; + graphComposite.setLayoutData(data); + + Label label1 = toolkit.createLabel(graphComposite, "1 day"); + Hyperlink link1 = toolkit.createHyperlink(graphComposite, "1 week", SWT.NONE); + Hyperlink link2 = toolkit.createHyperlink(graphComposite, "1 month", SWT.NONE); + Hyperlink link3 = toolkit.createHyperlink(graphComposite, "1 year", SWT.NONE); + + return graphComposite; + } + + private void createSections(Composite parent) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + if (server.getStatus() == SERVER_STATUS.ONLINE) { + createMemoryUsageSection(); + createNetworkUsageSection(); + createCPUUsageSection(); + createNetworkInterfacesSection(server, toolkit, form); + } + + parent.layout(); // IMP: lays out the form properly + } + + private void createServerSummarySection(GlusterServer server, FormToolkit toolkit, final ScrolledForm form) { + serverSummarySection = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + // toolkit.createLabel(section, "Preferred Network: ", SWT.NONE); + // toolkit.createLabel(section, server.getPreferredNetworkInterface().getName(), SWT.NONE); + + if (server.isOnline()) { + toolkit.createLabel(serverSummarySection, "Number of CPUs: ", SWT.NONE); + numCpus = toolkit.createLabel(serverSummarySection, "" + server.getNumOfCPUs(), SWT.NONE); + + toolkit.createLabel(serverSummarySection, "% CPU Usage (avg): ", SWT.NONE); + cpuGauge = new CoolGauge(serverSummarySection, guiHelper.getImage(IImageKeys.GAUGE_SMALL)); + + toolkit.createLabel(serverSummarySection, "Memory Usage: ", SWT.NONE); + memoryUsageBar = new ProgressBar(serverSummarySection, SWT.SMOOTH); + + // toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + // final CoolProgressBar bar = new CoolProgressBar(section,SWT.HORIZONTAL, + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_LEFT), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_FILLED), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_EMPTY), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_RIGHT)); + // bar.updateProgress(server.getMemoryInUse() / server.getTotalMemory()); + + // toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getTotalDiskSpace() : "NA", SWT.NONE); + // + // toolkit.createLabel(section, "Disk Space in Use (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getDiskSpaceInUse() : "NA", SWT.NONE); + + toolkit.createLabel(serverSummarySection, "Disk Usage: ", SWT.NONE); + diskUsageBar = new ProgressBar(serverSummarySection, SWT.SMOOTH); + } + + toolkit.createLabel(serverSummarySection, "Status: ", SWT.NONE); + lblServerStatus = new CLabel(serverSummarySection, SWT.NONE); + populateServerSummarySection(server); + } + + private void populateServerSummarySection(GlusterServer server) { + if (server.isOnline()) { + numCpus.setText("" + server.getNumOfCPUs()); + numCpus.redraw(); + + cpuGauge.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); + cpuGauge.setGaugeNeedleColour(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + cpuGauge.setGaugeNeedleWidth(2); + cpuGauge.setGaugeNeedlePivot(new Point(66, 65)); + + cpuGauge.setPoints(getPnts()); + cpuGauge.setLevel(server.getCpuUsage() / 100); + cpuGauge.setToolTipText(server.getCpuUsage() + "%"); + cpuGauge.redraw(); + + memoryUsageBar.setMinimum(0); + memoryUsageBar.setMaximum((int) Math.round(server.getTotalMemory())); + memoryUsageBar.setSelection((int) Math.round(server.getMemoryInUse())); + memoryUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber((server.getTotalMemory() / 1024)) + + "GB, In Use: " + NumberUtil.formatNumber((server.getMemoryInUse() / 1024)) + "GB"); + + diskUsageBar.setMinimum(0); + diskUsageBar.setMaximum((int) Math.round(server.getTotalDiskSpace())); + diskUsageBar.setSelection((int) Math.round(server.getDiskSpaceInUse())); + diskUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber((server.getTotalDiskSpace() / 1024)) + + "GB, In Use: " + NumberUtil.formatNumber((server.getDiskSpaceInUse() / 1024)) + "GB"); + + } + lblServerStatus.setText(server.getStatusStr()); + lblServerStatus.setImage(server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE_16x16) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE_16x16)); + toolkit.adapt(lblServerStatus, true, true); + + serverSummarySection.layout(); + form.reflow(true); + } + + private List getPnts() { + final List pnts = new ArrayList(); + pnts.add(new Point(47, 98)); + pnts.add(new Point(34, 84)); + pnts.add(new Point(29, 65)); + pnts.add(new Point(33, 48)); + pnts.add(new Point(48, 33)); + pnts.add(new Point(66, 28)); + pnts.add(new Point(83, 32)); + pnts.add(new Point(98, 47)); + pnts.add(new Point(103, 65)); + pnts.add(new Point(98, 83)); + pnts.add(new Point(84, 98)); + return pnts; + } + + private Composite createNetworkInterfacesSection(GlusterServer server, FormToolkit toolkit, ScrolledForm form) { + final Composite section = guiHelper.createSection(form, toolkit, "Network Interfaces", null, 1, false); + createNetworkInterfacesTableViewer(createTableViewerComposite(section), server); + // Hyperlink changePreferredNetworkLink = toolkit.createHyperlink(section, "Change Preferred Network", + // SWT.NONE); + // changePreferredNetworkLink.addHyperlinkListener(new HyperlinkAdapter() { + // + // @Override + // public void linkActivated(HyperlinkEvent e) { + // new MessageDialog( + // section.getShell(), + // "Gluster Storage Platform", + // guiHelper.getImage(IImageKeys.SERVER), + // "This will show additional controls to help user choose a new network interface. TO BE IMPLEMENTED.", + // MessageDialog.INFORMATION, new String[] { "OK" }, 0).open(); + // } + // }); + return section; + } + + private TableViewer createNetworkInterfacesTableViewer(final Composite parent, GlusterServer server) { + TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new NetworkInterfaceTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupNetworkInterfaceTable(parent, tableViewer.getTable()); + tableViewer.setInput(server.getNetworkInterfaces().toArray()); + + return tableViewer; + } + + private void setupNetworkInterfaceTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, + NETWORK_INTERFACE_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.MODEL, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.SPEED, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.IP_ADDRESS, SWT.CENTER, 100); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.NETMASK, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.GATEWAY, SWT.CENTER, 70); + } + + private Composite createTableViewerComposite(Composite parent) { + Composite tableViewerComposite = new Composite(parent, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData tableLayoutData = new GridData(SWT.FILL, SWT.FILL, true, false); + tableLayoutData.widthHint = 400; + tableLayoutData.minimumWidth = 400; + // tableLayoutData.grabExcessHorizontalSpace = true; + tableViewerComposite.setLayoutData(tableLayoutData); + return tableViewerComposite; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES columnIndex, int alignment, + int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + @Override + public void setFocus() { + form.setFocus(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersSummaryView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersSummaryView.java new file mode 100644 index 00000000..3d33a1eb --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersSummaryView.java @@ -0,0 +1,276 @@ +/** + * GlusterServersSummaryView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.utils.ChartViewerComposite; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Alert.ALERT_TYPES; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; + +/** + * + */ +public class GlusterServersSummaryView extends ViewPart { + public static final String ID = GlusterServersSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private ClusterListener clusterListener; + private EntityGroup servers; + private Composite alertsSection; + private Composite serversAvailabilitySection; + private Composite tasksSection; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @SuppressWarnings("unchecked") + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + setPartName("Summary"); + createSections(parent); + + clusterListener = new DefaultClusterListener() { + @Override + public void serverAdded(GlusterServer server) { + super.serverAdded(server); + updateServerAvailabilitySection(); + } + + @Override + public void serverRemoved(GlusterServer server) { + super.serverRemoved(server); + updateServerAvailabilitySection(); + } + + @Override + public void serverChanged(GlusterServer server, Event event) { + super.serverChanged(server, event); + updateServerAvailabilitySection(); + } + + private void updateServerAvailabilitySection() { + guiHelper.clearSection(serversAvailabilitySection); + populateAvailabilitySection(); + } + + @Override + public void alertsGenerated() { + super.alertsGenerated(); + guiHelper.clearSection(alertsSection); + populateAlertSection(); + } + + @Override + public void taskAdded(TaskInfo taskInfo) { + super.taskAdded(taskInfo); + updateTasksSection(); + } + + @Override + public void taskRemoved(TaskInfo taskInfo) { + super.taskRemoved(taskInfo); + updateTasksSection(); + } + + @Override + public void taskUpdated(TaskInfo taskInfo) { + super.taskUpdated(taskInfo); + updateTasksSection(); + } + + private void updateTasksSection() { + guiHelper.clearSection(tasksSection); + populateTasksSection(); + } + }; + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + + /** + * @param parent + */ + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Servers - Summary"); + + createSummarySection(); + createRunningTasksSection(); + createAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createSummarySection() { + serversAvailabilitySection = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + populateAvailabilitySection(); + } + + private void populateAvailabilitySection() { + if (servers.getEntities().size() == 0) { + toolkit.createLabel(serversAvailabilitySection, "This section will be populated after at least" + + CoreConstants.NEWLINE + "one server is added to the storage cloud."); + return; + } + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.OFFLINE)) }; + createStatusChart(serversAvailabilitySection, values); + } + + private int getServerCountByStatus(EntityGroup servers, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : (List)servers.getEntities()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createStatusChart(Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = 300; + data.heightHint = 150; + chartViewerComposite.setLayoutData(data); + } + + private void createAlertsSection() { + alertsSection = guiHelper.createSection(form, toolkit, "Alerts", null, 1, false); + populateAlertSection(); + } + + private void populateAlertSection() { + List alerts = GlusterDataModelManager.getInstance().getModel().getCluster().getAlerts(); + + for (Alert alert : alerts) { + if (alert.getType() != ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT) { + addAlertLabel(alertsSection, alert); + } + } + alertsSection.pack(true); + form.reflow(true); + } + + private void addAlertLabel(Composite section, Alert alert) { + CLabel lblAlert = new CLabel(section, SWT.FLAT); + Image alertImage = null; + switch (alert.getType()) { + case OFFLINE_VOLUME_BRICKS_ALERT: + alertImage = guiHelper.getImage(IImageKeys.BRICK_OFFLINE_22x22); + break; + case DISK_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.LOW_DISK_SPACE_22x22); + break; + case OFFLINE_SERVERS_ALERT: + alertImage = guiHelper.getImage(IImageKeys.SERVER_OFFLINE_22x22); + break; + case MEMORY_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.MEMORY_USAGE_ALERT_22x22); + break; + case CPU_USAGE_ALERT: + alertImage = guiHelper.getImage(IImageKeys.SERVER_WARNING_22x22); + break; + } + lblAlert.setImage(alertImage); + lblAlert.setText(alert.getMessage()); + lblAlert.redraw(); + } + + private void createRunningTasksSection() { + tasksSection = guiHelper.createSection(form, toolkit, "Running Tasks", null, 1, false); + populateTasksSection(); + + } + + private void populateTasksSection() { + for (TaskInfo taskInfo : GlusterDataModelManager.getInstance().getModel().getCluster().getTaskInfoList()) { + // Exclude volume related tasks + if (taskInfo.getType() != TASK_TYPE.VOLUME_REBALANCE && taskInfo.getType() != TASK_TYPE.BRICK_MIGRATE) { + addTaskLabel(tasksSection, taskInfo); + } + } + tasksSection.layout(); + form.reflow(true); + } + + private void addTaskLabel(Composite section, TaskInfo taskInfo) { + CLabel lblAlert = new CLabel(section, SWT.NONE); + lblAlert.setText(taskInfo.getDescription()); + + Image taskImage = null; + switch(taskInfo.getType()) { + case DISK_FORMAT: + taskImage = guiHelper.getImage(IImageKeys.DISK_INITIALIZING_22x22); + break; + case BRICK_MIGRATE: + taskImage = guiHelper.getImage(IImageKeys.BRICK_MIGRATE_22x22); + break; + case VOLUME_REBALANCE: + taskImage = guiHelper.getImage(IImageKeys.VOLUME_REBALANCE_22x22); + break; + } + lblAlert.setImage(taskImage); + lblAlert.redraw(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + form.setFocus(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersView.java new file mode 100644 index 00000000..566befc3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterServersView.java @@ -0,0 +1,78 @@ +/** + * GlusterServersView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.GlusterServersPage; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; + +/** + * @author root + * + */ +public class GlusterServersView extends ViewPart implements IDoubleClickListener { + public static final String ID = GlusterServersView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup servers; + private GlusterServersPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @SuppressWarnings("unchecked") + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup) guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + page = new GlusterServersPage(getSite(), parent, SWT.NONE, servers); + page.addDoubleClickListener(this); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) + */ + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterViewsManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterViewsManager.java new file mode 100644 index 00000000..f55e72b9 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/GlusterViewsManager.java @@ -0,0 +1,130 @@ +/** + * GlusterViewsManager.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +/** + * @see ViewsManager + */ +public class GlusterViewsManager implements ViewsManager { + private IWorkbenchPage page; + + public GlusterViewsManager(IWorkbenchPage page) { + this.page = page; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.ViewsManager#updateViews(com.gluster.storage.management.core.model.Entity) + */ + @Override + public void updateViews(Entity entity) { + closeAllViews(); + + try { + if (entity instanceof EntityGroup) { + showViewsForEntityGroup((EntityGroup)entity); + } else if (entity.getClass() == Server.class) { + showViewsForDiscoveredServer((Server)entity); + } else if (entity.getClass() == GlusterServer.class) { + showViewsForGlusterServer((GlusterServer)entity); + } else if (entity instanceof Volume) { + showViewsForVolume((Volume)entity); + } else if (entity instanceof Cluster) { + showViewsForCluster((Cluster)entity); + } + } catch (PartInitException e) { + e.printStackTrace(); + } + } + + /** + * + */ + private void closeAllViews() { + IViewReference[] viewReferences = page.getViewReferences(); + for (final IViewReference viewReference : viewReferences) { + if (!viewReference.getId().equals(NavigationView.ID)) { + page.hideView(viewReference); + } + } + } + + private void showViewsForCluster(Cluster cluster) throws PartInitException { + page.showView(ClusterSummaryView.ID); + page.showView(TasksView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewsForVolume(Volume volume) throws PartInitException { + page.showView(VolumeSummaryView.ID); + page.showView(VolumeBricksView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(VolumeOptionsView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(VolumeLogsView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewsForGlusterServer(GlusterServer server) throws PartInitException { + page.showView(GlusterServerSummaryView.ID); + if (server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE) { + page.showView(GlusterServerDisksView.ID, null, IWorkbenchPage.VIEW_CREATE); + //page.showView(GlusterServerLogsView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + } + + private void showViewsForDiscoveredServer(Server server) throws PartInitException { + page.showView(DiscoveredServerView.ID); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private void showViewsForEntityGroup(EntityGroup entityGroup) throws PartInitException { + Class entityType = entityGroup.getEntityType(); + if (entityType == Server.class) { + showViewForServers(entityGroup); + } else if (entityType == Volume.class) { + showViewsForVolumes(entityGroup); + } else if (entityType == GlusterServer.class) { + showViewsForGlusterServers(entityGroup); + } + } + + private void showViewsForGlusterServers(EntityGroup server) throws PartInitException { + page.showView(GlusterServersSummaryView.ID); + page.showView(GlusterServersView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(DisksView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewsForVolumes(EntityGroup volumes) throws PartInitException { + page.showView(VolumesSummaryView.ID); + page.showView(VolumesView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewForServers(EntityGroup servers) throws PartInitException { + page.showView(DiscoveredServersView.ID); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationTreeLabelDecorator.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationTreeLabelDecorator.java new file mode 100644 index 00000000..d7448e76 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationTreeLabelDecorator.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views; + +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ILightweightLabelDecorator; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.console.Application; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +public class NavigationTreeLabelDecorator implements ILightweightLabelDecorator { + + @Override + public void addListener(ILabelProviderListener listener) { + } + + @Override + public void dispose() { + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + } + + @SuppressWarnings("rawtypes") + @Override + public void decorate(Object element, IDecoration decoration) { + if (element instanceof Volume) { + Volume volume = (Volume) element; + if (volume.getStatus() == Volume.VOLUME_STATUS.OFFLINE) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_OFFLINE_8x8)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE_8x8)); + } + } + + if (element instanceof GlusterServer) { + GlusterServer server = (GlusterServer) element; + if (server.getStatus() == GlusterServer.SERVER_STATUS.OFFLINE) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_OFFLINE_8x8)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE_8x8)); + } + } + + if (element instanceof Server) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR_8x8)); + } + + if(element instanceof EntityGroup && ((EntityGroup)element).getEntityType() == Server.class) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR_8x8)); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationView.java new file mode 100644 index 00000000..9fd080e8 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/NavigationView.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.model.BaseWorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Volume; + +public class NavigationView extends ViewPart implements ISelectionListener { + public static final String ID = NavigationView.class.getName(); + private TreeViewer treeViewer; + private IAdapterFactory adapterFactory = new ClusterAdapterFactory(); + private GlusterToolbarManager toolbarManager; + private Entity entity; + private GlusterViewsManager viewsManager; + private DefaultClusterListener clusterListener; + + @Override + public void createPartControl(Composite parent) { + createNavigationTree(parent); + + // Create the views and toolbar managers + toolbarManager = new GlusterToolbarManager(getSite().getWorkbenchWindow()); + viewsManager = new GlusterViewsManager(getSite().getPage()); + + // listen to selection events to update views/toolbar accordingly + getSite().getPage().addSelectionListener(this); + } + + private void createNavigationTree(Composite parent) { + GlusterDataModel model = GlusterDataModelManager.getInstance().getModel(); + + Platform.getAdapterManager().registerAdapters(adapterFactory, Entity.class); + treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + treeViewer.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider()); + treeViewer.setContentProvider(new BaseWorkbenchContentProvider()); + treeViewer.setInput(model); + treeViewer.expandAll(); + // select the first element by default + treeViewer.setSelection(new StructuredSelection(model.getChildren().get(0))); + + setupContextMenu(); + + // register as selection provider so that other views can listen to any selection events on the tree + getSite().setSelectionProvider(treeViewer); + + clusterListener = new DefaultClusterListener() { + public void modelChanged() { + treeViewer.refresh(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + if (volume == entity) { + // this makes sure that the toolbar buttons get updated according to new status + selectEntity(volume); + } + } + + @Override + public void volumeDeleted(Volume volume) { + super.volumeDeleted(volume); + if(volume == entity) { + // volume selected was deleted. select the root element in the tree. + selectEntity(GlusterDataModelManager.getInstance().getModel().getCluster()); + } + } + + @Override + public void serverRemoved(GlusterServer server) { + super.serverRemoved(server); + if(server == entity) { + // server selected was removed. select the root element in the tree. + selectEntity(GlusterDataModelManager.getInstance().getModel().getCluster()); + } + }; + }; + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + } + + private void setupContextMenu() { + MenuManager menuManager = new MenuManager("&Gluster", "gluster.context.menu"); + Menu contextMenu = menuManager.createContextMenu(treeViewer.getControl()); + treeViewer.getTree().setMenu(contextMenu); + getSite().registerContextMenu(menuManager, treeViewer); + } + + public void selectEntity(Entity entity) { + treeViewer.setSelection(new StructuredSelection(entity)); + treeViewer.reveal(entity); + setFocus(); // this ensures that the "selection changed" event gets fired + } + + @Override + public void setFocus() { + treeViewer.getControl().setFocus(); + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (selectedEntity != null && selectedEntity != entity) { + entity = selectedEntity; + + // update views and toolbar buttons visibility based on selected entity + viewsManager.updateViews(entity); + toolbarManager.updateToolbar(entity); + + // Opening of other views may cause navigation tree to lose focus; get it back. + setFocus(); + } + } + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/TasksView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/TasksView.java new file mode 100644 index 00000000..e408e64e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/TasksView.java @@ -0,0 +1,39 @@ +package com.gluster.storage.management.console.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.views.pages.TasksPage; +import com.gluster.storage.management.core.model.TaskInfo; + +public class TasksView extends ViewPart { + + public static final String ID = TasksView.class.getName(); + private TasksPage page; + + + public TasksView() { + // TODO Auto-generated constructor stub + } + + @Override + public void createPartControl(Composite parent) { + page = new TasksPage(getSite(), parent, SWT.NONE, getAllTasks()); + page.layout(); // IMP: lays out the form properly + } + + + private List getAllTasks() { + return GlusterDataModelManager.getInstance().getModel().getCluster().getTaskInfoList(); + } + + @Override + public void setFocus() { + page.setFocus(); + } + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ViewsManager.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ViewsManager.java new file mode 100644 index 00000000..5b19ea98 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/ViewsManager.java @@ -0,0 +1,38 @@ +/** + * ViewsManager.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Whenever the current selection/action demands opening different set of views, the views manager is used to open + * appropriate views. + */ +public interface ViewsManager { + /** + * Updates the views for given entity. This typically means that user is working with the given entity, and hence + * the views related to that entity should be made visible, and other un-related views should be hidden. + * + * @param entity + * The entity for which views are to be updated + */ + public void updateViews(Entity entity); +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeBricksView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeBricksView.java new file mode 100644 index 00000000..0c494945 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeBricksView.java @@ -0,0 +1,39 @@ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.BricksPage; +import com.gluster.storage.management.core.model.Volume; + +public class VolumeBricksView extends ViewPart { + public static final String ID = VolumeBricksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private BricksPage page; + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + /** + * @param parent + */ + private void createPage(Composite parent) { + page = new BricksPage(parent, SWT.NONE, getSite(), volume.getBricks()); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeLogsView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeLogsView.java new file mode 100644 index 00000000..e6a5370f --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeLogsView.java @@ -0,0 +1,35 @@ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.VolumeLogsPage; +import com.gluster.storage.management.core.model.Volume; + +public class VolumeLogsView extends ViewPart { + VolumeLogsPage logsPage; + public static final String ID = VolumeLogsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + private void createPage(Composite parent) { + logsPage = new VolumeLogsPage(parent, SWT.NONE, volume); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + logsPage.setFocus(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeOptionsView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeOptionsView.java new file mode 100644 index 00000000..7be16f48 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeOptionsView.java @@ -0,0 +1,36 @@ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.VolumeOptionsPage; +import com.gluster.storage.management.core.model.Volume; + +public class VolumeOptionsView extends ViewPart { + public static final String ID = VolumeOptionsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private VolumeOptionsPage page; + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + private void createPage(Composite parent) { + page = new VolumeOptionsPage(parent, SWT.NONE, volume); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeSummaryView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeSummaryView.java new file mode 100644 index 00000000..92b4b22e --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeSummaryView.java @@ -0,0 +1,750 @@ +package com.gluster.storage.management.console.views; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormText; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Partition; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.core.utils.StringUtil; +import com.gluster.storage.management.core.utils.ValidationUtil; + +public class VolumeSummaryView extends ViewPart { + public static final String ID = VolumeSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Volume volume; + private CLabel lblStatusValue; + private DefaultClusterListener volumeChangedListener; + private Hyperlink changeLink; + private Hyperlink CifsChangeLink; + private Text accessControlText; + private Text cifsUsersText; + private ControlDecoration errDecoration; + private ControlDecoration errCifsDecoration; + private Composite parent; + private static final String COURIER_FONT = "Courier"; + private Cluster cluster = GlusterDataModelManager.getInstance().getModel().getCluster(); + private Button nfsCheckBox; + private FormText glusterNfsMountText; + private String nfsMountInfo; + private Label nfsLabel; + private String nfs; + + private Label numberOfBricks; + private Label totalDiskSpace; + private Composite alertsSection; + private Button cifsCheckbox; + private Label cifsLabel; + private Composite cifsUpdateLinkComposite; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + this.parent = parent; + setPartName("Summary"); + createSections(); + + final GlusterToolbarManager toolbarManager = new GlusterToolbarManager(getSite().getWorkbenchWindow()); + // Refresh the navigation tree whenever there is a change to the data model + volumeChangedListener = new DefaultClusterListener() { + @Override + public void volumeChanged(Volume volume, Event event) { + updateVolumeStatusLabel(); + populateAccessControlText(); + changeNFSStatus(volume.isNfsEnabled()); + updateBrickChanges(volume); + toolbarManager.updateToolbar(volume); + } + + @Override + public void alertsGenerated() { + super.alertsGenerated(); + guiHelper.clearSection(alertsSection); + populateAlertSection(); + alertsSection.layout(); + } + }; + GlusterDataModelManager.getInstance().addClusterListener(volumeChangedListener); + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(volumeChangedListener); + } + + private void createSections() { + form = guiHelper.setupForm(parent, toolkit, "Volume Properties [" + volume.getName() + "]"); + + createVolumePropertiesSection(); + createVolumeMountingInfoSection(); + createVolumeAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createVolumeAlertsSection() { + alertsSection = guiHelper.createSection(form, toolkit, "Alerts", null, 1, false); + populateAlertSection(); + } + + private void populateAlertSection() { + List alerts = GlusterDataModelManager.getInstance().getModel().getCluster().getAlerts(); + + for (int i = 0; i < alerts.size(); i++) { + if (alerts.get(i).getType() == Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT + && alerts.get(i).getReference().split(":")[0].trim().equals(volume.getName())) { + addAlertLabel(alertsSection, alerts.get(i)); + } + } + } + + private void addAlertLabel(Composite section, Alert alert) { + CLabel lblAlert = new CLabel(section, SWT.NONE); + lblAlert.setImage(guiHelper.getImage(IImageKeys.BRICK_OFFLINE_22x22)); + lblAlert.setText(alert.getMessage()); + lblAlert.redraw(); + } + + private FormText setFormTextStyle(FormText formText, String fontName, int size, int style) { + Font font = new Font(Display.getCurrent(), new FontData(fontName, size, style)); + formText.setFont(font); + return formText; + } + + private void createVolumeMountingInfoSection() { + String glusterFs = "Gluster:"; + nfs = "NFS:"; + String onlineServers = getOnlineServers(10); // Limited to 10 servers + String firstOnlineServer = onlineServers.split(",")[0].trim(); + String glusterFsMountInfo = "mount -t glusterfs " + firstOnlineServer + ":/" + volume.getName() + + " "; + nfsMountInfo = "mount -t nfs " + firstOnlineServer + ":/" + volume.getName() + " "; + // TODO: if more than 10 servers... + String info = "Server can be any server name in the storage cloud eg. <" + onlineServers + ">"; + + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 3, false); + + toolkit.createLabel(section, glusterFs, SWT.NORMAL); + FormText glusterfsMountText = setFormTextStyle(toolkit.createFormText(section, true), COURIER_FONT, 10, + SWT.NONE); + glusterfsMountText.setText(glusterFsMountInfo, false, false); + glusterfsMountText.setLayoutData(new GridData(GridData.BEGINNING, GridData.VERTICAL_ALIGN_CENTER, false, false, + 2, 0)); // Label spanned two column + + nfsLabel = toolkit.createLabel(section, nfs, SWT.NONE); + GridData data = new GridData(); + data.horizontalAlignment = SWT.FILL; + nfsLabel.setLayoutData(data); + + glusterNfsMountText = setFormTextStyle(toolkit.createFormText(section, true), COURIER_FONT, 10, SWT.NONE); + glusterNfsMountText.setText(nfsMountInfo, false, false); + glusterNfsMountText.setLayoutData(new GridData(GridData.BEGINNING, GridData.VERTICAL_ALIGN_CENTER, false, + false, 2, 0)); + + changeNFSStatus( nfsCheckBox.getSelection()); + + toolkit.createLabel(section, ""); + Label infoLabel = toolkit.createLabel(section, info, SWT.NONE); + infoLabel.setLayoutData(new GridData(GridData.BEGINNING, GridData.VERTICAL_ALIGN_CENTER, false, false, 2, 0)); + + // TODO: implement a logic to identify the corresponding glusterfs client download link + String message = "You can download gluster FS client from"; + String glusterClientDownloadlinkText = "here."; + final String glusterClientDownloadlink = "http://www.gluster.com"; + + toolkit.createLabel(section, ""); + toolkit.createLabel(section, message); + Hyperlink link = toolkit.createHyperlink(section, glusterClientDownloadlinkText, SWT.NORMAL); + link.addHyperlinkListener(new HyperlinkAdapter() { + public void linkActivated(HyperlinkEvent e) { + try { + System.out.println(e.getLabel() + " [" + e.getHref() + "]"); + PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser() + .openURL(new URL(glusterClientDownloadlink)); + } catch (PartInitException e1) { + e1.printStackTrace(); + } catch (MalformedURLException e1) { + e1.printStackTrace(); + } + } + }); + } + + private String getOnlineServers(int maxServers) { + List OnlineServers = new ArrayList(); + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == SERVER_STATUS.ONLINE) { + OnlineServers.add(server.getName()); + if (OnlineServers.size() >= maxServers) { + break; + } + } + } + return StringUtil.collectionToString(OnlineServers, ", ") + ((OnlineServers.size() > maxServers) ? "..." : ""); + } + + /** + * + */ + private void createVolumePropertiesSection() { + Composite section = guiHelper.createSection(form, toolkit, "Properties", null, 3, false); + + createVolumeTypeField(section); + + VOLUME_TYPE volumeType = volume.getVolumeType(); + if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + createReplicaCountField(section); + } + + if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + createStripeCountField(section); + } + + createNumOfBricksField(section); + createDiskSpaceField(section); + // createTransportTypeField(section); + createNASProtocolField(section); + createCifsField(section); + createAccessControlField(section); + createStatusField(section); + } + + private GridData createDefaultLayoutData() { + GridData layoutData = new GridData(); + layoutData.minimumWidth = 300; + layoutData.widthHint = 300; + return layoutData; + } + + private void createCifsField(Composite section) { + GridData data = new GridData(); + data.heightHint = 0; + + cifsLabel = toolkit.createLabel(section, "CIFS: ", SWT.NONE); + cifsLabel.setLayoutData(data); + cifsLabel.setVisible(false); + + cifsUsersText = toolkit.createText(section, volume.getAccessControlList(), SWT.BORDER); + populateCifsUsersText(); + addKeyListenerForCifsUser(); + cifsUsersText.setLayoutData(createDefaultLayoutData()); + cifsUsersText.setEnabled(true); + cifsUsersText.setLayoutData(data); + cifsUsersText.setVisible(false); + + cifsUpdateLinkComposite = toolkit.createComposite(section, SWT.NONE); + cifsUpdateLinkComposite.setVisible(false); + cifsUpdateLinkComposite.setLayoutData(data); + cifsUpdateLinkComposite.setLayout(new FillLayout()); + + createChangeLinkForCifs(cifsUpdateLinkComposite); + + // error decoration used while validating the cifs users text + errCifsDecoration = guiHelper.createErrorDecoration(cifsUsersText); + errCifsDecoration.hide(); + } + + private void createAccessControlField(Composite section) { + toolkit.createLabel(section, "Access Control: ", SWT.NONE); + accessControlText = toolkit.createText(section, volume.getAccessControlList(), SWT.BORDER); + + populateAccessControlText(); + addKeyListenerForAccessControl(); + accessControlText.setLayoutData(createDefaultLayoutData()); + accessControlText.setEnabled(false); + createChangeLinkForAccessControl(section); + + // error decoration used while validating the access control text + errDecoration = guiHelper.createErrorDecoration(accessControlText); + errDecoration.hide(); + createAccessControlInfoLabel(section); // info text + } + + private void createAccessControlInfoLabel(Composite section) { + toolkit.createLabel(section, "", SWT.NONE); + Label accessControlInfoLabel = toolkit.createLabel(section, "(Comma separated list of IP addresses/hostnames)"); + GridData data = new GridData(SWT.LEFT, SWT.CENTER, true, false); + data.horizontalSpan = 2; + accessControlInfoLabel.setLayoutData(data); + } + + private void createChangeLinkForAccessControl(Composite section) { + changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + saveAccessControlList(); + } + + private void startEdit() { + accessControlText.setEnabled(true); + accessControlText.setFocus(); + accessControlText.selectAll(); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (accessControlText.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void saveAccessControlList() { + final String newACL = accessControlText.getText(); + + guiHelper.setStatusMessage("Setting access control list to [" + newACL + "]..."); + parent.update(); + + if (newACL.equals(volume.getAccessControlList())) { + accessControlText.setEnabled(false); + changeLink.setText("change"); + } else if (ValidationUtil.isValidAccessControl(newACL)) { + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + try { + new VolumesClient().setVolumeOption(volume.getName(), Volume.OPTION_AUTH_ALLOW, newACL); + accessControlText.setEnabled(false); + changeLink.setText("change"); + + GlusterDataModelManager.getInstance().setAccessControlList(volume, newACL); + } catch (Exception e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Access control", e.getMessage()); + } + } + }); + } else { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Access control", "Invalid IP / Host name "); + } + guiHelper.clearStatusMessage(); + parent.update(); + } + + private void createChangeLinkForCifs(Composite section) { + CifsChangeLink = toolkit.createHyperlink(section, "Update", SWT.NONE); + CifsChangeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + saveCifsConfiguration(); + } + + private void startEdit() { + cifsUsersText.setEnabled(true); + cifsUsersText.setFocus(); + cifsUsersText.selectAll(); + CifsChangeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (cifsUsersText.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void saveCifsConfiguration() { + final String cifsUsers = cifsUsersText.getText(); + + guiHelper.setStatusMessage("Setting Cifs Configuration..."); + parent.update(); + + List userList = volume.getCifsUsers(); + String configuredUsers = ""; + if (userList != null) { + configuredUsers = StringUtil.collectionToString(userList, ","); + } + + if (cifsUsersText.equals(configuredUsers)) { + cifsUsersText.setEnabled(false); + CifsChangeLink.setText("change"); + // There is no change in the users list + } else if(isvalidCifsUser()) { + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + try { + new VolumesClient().setCifsConfig(volume.getName(), cifsCheckbox.getSelection(), cifsUsers); + cifsUsersText.setEnabled(false); + CifsChangeLink.setText("change"); + + GlusterDataModelManager.getInstance().setCifsConfig(volume, cifsCheckbox.getSelection(), + Arrays.asList(cifsUsers.split(","))); + } catch (Exception e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Cifs Configuration", e.getMessage()); + populateCifsUsersText(); + } + } + }); + } else { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Cifs Configuration", "Please enter cifs user name "); + cifsUsersText.setFocus(); + } + guiHelper.clearStatusMessage(); + parent.update(); + } + + private void saveNFSOption() { + guiHelper.setStatusMessage("Setting NFS option..."); + parent.update(); + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + try { + boolean enableNfs = nfsCheckBox.getSelection(); + new VolumesClient().setVolumeOption(volume.getName(), Volume.OPTION_NFS_DISABLE, + (enableNfs) ? GlusterConstants.OFF : GlusterConstants.ON); + GlusterDataModelManager.getInstance().setNfsEnabled(volume, enableNfs); + } catch (Exception e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "NFS Option", e.getMessage()); + } + } + }); + guiHelper.clearStatusMessage(); + parent.update(); + } + + private void addKeyListenerForAccessControl() { + accessControlText.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent key) { + switch (key.keyCode) { + case SWT.ESC: + // Reset to default + populateAccessControlText(); + changeLink.setText("change"); + accessControlText.setEnabled(false); + break; + case 13: + // User has pressed enter. Save the new value + saveAccessControlList(); + break; + } + + validateAccessControlList(); + } + }); + } + + private void populateAccessControlText() { + String accessControlList = volume.getAccessControlList(); + if (accessControlList == null) { + // if not set, show default value + accessControlList = GlusterDataModelManager.getInstance().getVolumeOptionDefaultValue( + Volume.OPTION_AUTH_ALLOW); + } + accessControlText.setText(accessControlList); + } + + private void addKeyListenerForCifsUser() { + cifsUsersText.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent key) { + switch (key.keyCode) { + case SWT.ESC: + // Reset to default + populateCifsUsersText(); + break; + case 13: + // User has pressed enter. Save the new value + saveCifsConfiguration(); + break; + } + validateCifsUsers(); + } + }); + } + + private void populateCifsUsersText() { + List userList = volume.getCifsUsers(); + if (userList == null) { + cifsUsersText.setText(""); + } else { + String users = StringUtil.collectionToString(userList, ","); + cifsUsersText.setText(users); + } + } + + private void createNASProtocolField(final Composite section) { + toolkit.createLabel(section, "Access Protocols: ", SWT.NONE); + + Composite nasProtocolsComposite = toolkit.createComposite(section); + nasProtocolsComposite.setLayout(new FillLayout()); + + createCheckbox(nasProtocolsComposite, "Gluster", true, false); + + nfsCheckBox = createCheckbox(nasProtocolsComposite, "NFS", volume.isNfsEnabled(), true); + + nfsCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + saveNFSOption(); + } + }); + + // CIFS checkbox + cifsCheckbox = createCheckbox(nasProtocolsComposite, "CIFS", volume.isCifsEnable(), true); + cifsCheckboxListner(cifsCheckbox); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void cifsCheckboxListner(final Button cifsCheckbox) { + cifsCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (cifsCheckbox.getSelection()) { + GridData data = new GridData(); + data.heightHint = 20; + data.widthHint = 100; + + cifsLabel.setVisible(true); + cifsLabel.setLayoutData(data); + + GridData data1 = new GridData(); + data1.heightHint = 20; + data1.widthHint = 300; + cifsUsersText.setVisible(true); + cifsUsersText.setLayoutData(data1); + + GridData data2 = new GridData(); + data2.heightHint = 25; + data2.widthHint = 75; + cifsUpdateLinkComposite.setVisible(true); + cifsUpdateLinkComposite.setLayoutData(data2); + form.reflow(true); + } else { + GridData data = new GridData(); + data.heightHint = 0; + + cifsUsersText.setVisible(false); + cifsUsersText.setLayoutData(data); + + cifsLabel.setVisible(false); + cifsLabel.setLayoutData(data); + + cifsUpdateLinkComposite.setVisible(false); + cifsUpdateLinkComposite.setLayoutData(data); + + form.reflow(true); + } + } + }); + } + + private Button createCheckbox(Composite parent, String label, boolean checked, boolean enabled) { + final Button checkBox = toolkit.createButton(parent, label, SWT.CHECK); + checkBox.setSelection(checked); + checkBox.setEnabled(enabled); + return checkBox; + } + + private void changeNFSStatus(Boolean isNFSExported) { + glusterNfsMountText.setVisible(isNFSExported); + nfsLabel.setVisible(isNFSExported); + nfsCheckBox.setSelection(isNFSExported); + } + + + private void updateBrickChanges(Volume volume) { + numberOfBricks.setText("" + volume.getNumOfBricks()); + totalDiskSpace.setText("" + NumberUtil.formatNumber((getTotalDiskSpace() / 1024))); + } + + private double getDiskSize(String serverName, String deviceName) { + double diskSize = 0; + GlusterServer server = cluster.getServer(serverName); + if (server.getStatus() == SERVER_STATUS.ONLINE) { + for (Disk disk : server.getDisks()) { + if (disk.getName().equals(deviceName)) { + diskSize = disk.getSpace(); + break; + } + + if (disk.hasPartitions()) { + for (Partition partition : disk.getPartitions()) { + if (partition.getName().equals(deviceName)) { + diskSize = partition.getSpace(); + break; + } + } + } + } + } + return diskSize; + } + + private double getTotalDiskSpace() { + double diskSize = 0; + for (Brick brick : volume.getBricks()) { + diskSize += getDiskSize(brick.getServerName(), + GlusterDataModelManager.getInstance().getDeviceForBrickDir(brick).getName()); + } + return diskSize; + } + + private void createDiskSpaceField(Composite section) { + Label diskSpaceLabel = toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + diskSpaceLabel.setToolTipText("boldnormal"); + totalDiskSpace = toolkit.createLabel(section, "" + NumberUtil.formatNumber((getTotalDiskSpace() / 1024)), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStatusField(Composite section) { + toolkit.createLabel(section, "Status: ", SWT.NONE); + + lblStatusValue = new CLabel(section, SWT.NONE); + updateVolumeStatusLabel(); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void updateVolumeStatusLabel() { + lblStatusValue.setText(volume.getStatusStr()); + lblStatusValue.setImage((volume.getStatus() == Volume.VOLUME_STATUS.ONLINE) ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE_16x16) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE_16x16)); + GridData data = new GridData(); + data.horizontalAlignment = SWT.FILL; + lblStatusValue.setLayoutData(data); + lblStatusValue.redraw(); + } + + private void createTransportTypeField(Composite section) { + toolkit.createLabel(section, "Transport Type: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getTransportTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createNumOfBricksField(Composite section) { + toolkit.createLabel(section, "Number of Bricks: ", SWT.NONE); + numberOfBricks = toolkit.createLabel(section, "" + volume.getNumOfBricks(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStripeCountField(Composite section) { + toolkit.createLabel(section, "Stripe Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getStripeCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createReplicaCountField(Composite section) { + toolkit.createLabel(section, "Replica Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getReplicaCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createVolumeTypeField(Composite section) { + toolkit.createLabel(section, "Volume Type: ", SWT.NONE); + toolkit.createLabel(section, volume.getVolumeTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); + } + + @Override + public void setFocus() { + form.setFocus(); + } + + private void validateAccessControlList() { + errDecoration.hide(); + + if (accessControlText.getText().length() == 0) { + errDecoration.setDescriptionText("Access control list cannot be empty!"); + errDecoration.show(); + return; + } + + if (!ValidationUtil.isValidAccessControl(accessControlText.getText())) { + errDecoration + .setDescriptionText("Access control list must be a comma separated list of IP addresses/Host names. Please enter a valid value!"); + errDecoration.show(); + } + } + + private void validateCifsUsers() { + if (cifsCheckbox.getSelection()) { + String cifsUserList = cifsUsersText.getText().trim(); + if (cifsUserList.length() == 0) { + errCifsDecoration.setDescriptionText("Please enter cifs user name"); + errCifsDecoration.show(); + } else { + errCifsDecoration.hide(); + } + } + } + + private boolean isvalidCifsUser() { + if (cifsCheckbox.getSelection()) { + String cifsUserList = cifsUsersText.getText().trim(); + if (cifsUserList.length() == 0) { + return false; + } else { + return true; + } + } + return true; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeView.java new file mode 100644 index 00000000..0c9ef92b --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumeView.java @@ -0,0 +1,90 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; + +/** + * @author root + * + */ +public class VolumeView extends ViewPart { + public static final String ID = VolumeView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Server server; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (Server) guiHelper.getSelectedEntity(getSite(), Server.class); + } + createSections(parent, server, toolkit); + } + + private void createServerSummarySection(Server server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + server.getTotalMemory(), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(server.getTotalDiskSpace()), SWT.NONE); + } + + private void createSections(Composite parent, Server server, FormToolkit toolkit) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + parent.layout(); // IMP: lays out the form properly + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesSummaryView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesSummaryView.java new file mode 100644 index 00000000..51ca834c --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesSummaryView.java @@ -0,0 +1,264 @@ +/** + * VolumesSummaryView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IImageKeys; +import com.gluster.storage.management.console.utils.ChartViewerComposite; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +/** + * + */ +public class VolumesSummaryView extends ViewPart { + public static final String ID = VolumesSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private EntityGroup volumes; + private Cluster cluster = GlusterDataModelManager.getInstance().getModel().getCluster(); + private ClusterListener clusterListener; + + private static final String ALERTS = "Alerts"; + private static final String RUNNING_TASKS = "Running Tasks"; + private static final String VOLUMES_SUMMARY = "Volumes - Summary"; + private static final String AVAILABILITY = "Availability"; + private Composite alertsSection; + private Composite tasksSection; + private Composite summarySection; + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets + * .Composite) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void createPartControl(Composite parent) { + if (volumes == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Volume.class) { + volumes = (EntityGroup) selectedObj; + } + } + + setPartName("Summary"); + createSections(parent); + + clusterListener = new DefaultClusterListener() { + @Override + public void volumeCreated(Volume volume) { + super.volumeCreated(volume); + updateSummarySection(); + } + + @Override + public void volumeDeleted(Volume volume) { + super.volumeDeleted(volume); + updateSummarySection(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + updateSummarySection(); + } + + private void updateSummarySection() { + guiHelper.clearSection(summarySection); + populateSummarySection(); + summarySection.layout(); + form.reflow(true); + } + + @Override + public void alertsGenerated() { + super.alertsGenerated(); + guiHelper.clearSection(alertsSection); + populateAlertSection(); + } + + @Override + public void taskAdded(TaskInfo taskInfo) { + super.taskAdded(taskInfo); + updateTasksSection(); + } + + @Override + public void taskRemoved(TaskInfo taskInfo) { + super.taskRemoved(taskInfo); + updateTasksSection(); + } + + @Override + public void taskUpdated(TaskInfo taskInfo) { + super.taskUpdated(taskInfo); + updateTasksSection(); + } + + private void updateTasksSection() { + guiHelper.clearSection(tasksSection); + populateTasks(); + } + }; + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, VOLUMES_SUMMARY); + createSummarySection(); + createRunningTasksSection(); + createAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createAlertsSection() { + alertsSection = guiHelper.createSection(form, toolkit, ALERTS, null, 1, false); + populateAlertSection(); + } + + private void populateAlertSection() { + for (Alert alert : cluster.getAlerts()) { + if (alert.getType() == Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT) { + addAlertLabel(alertsSection, alert); + } + } + alertsSection.pack(true); + form.reflow(true); + } + + private void addAlertLabel(Composite section, Alert alert) { + CLabel lblAlert = new CLabel(section, SWT.NONE); + lblAlert.setImage((alert.getType() == Alert.ALERT_TYPES.DISK_USAGE_ALERT) ? guiHelper + .getImage(IImageKeys.LOW_DISK_SPACE_22x22) : guiHelper.getImage(IImageKeys.BRICK_OFFLINE_22x22)); + lblAlert.setText(alert.getMessage()); + lblAlert.redraw(); + } + + private void createRunningTasksSection() { + tasksSection = guiHelper.createSection(form, toolkit, RUNNING_TASKS, null, 1, false); + populateTasks(); + } + + private void populateTasks() { + for (TaskInfo taskInfo : cluster.getTaskInfoList()) { + if (taskInfo.getType() == TASK_TYPE.BRICK_MIGRATE || taskInfo.getType() == TASK_TYPE.VOLUME_REBALANCE) + addTaskLabel(tasksSection, taskInfo); + } + tasksSection.pack(true); + form.reflow(true); + } + + private void addTaskLabel(Composite section, TaskInfo taskInfo) { + // Task related to Volumes context + if (taskInfo.getType() == TASK_TYPE.BRICK_MIGRATE + || taskInfo.getType() == TASK_TYPE.VOLUME_REBALANCE) { + if (taskInfo.getStatus().isPercentageSupported()) { + // TODO Progress bar or link to progress view + } + CLabel lblAlert = new CLabel(section, SWT.NONE); + lblAlert.setText(taskInfo.getDescription()); + lblAlert.setImage((taskInfo.getType() == TASK_TYPE.BRICK_MIGRATE) ? guiHelper + .getImage(IImageKeys.BRICK_MIGRATE_32x32) : guiHelper.getImage(IImageKeys.VOLUME_REBALANCE_32x32)); + lblAlert.redraw(); + } + } + + private void createSummarySection() { + summarySection = guiHelper.createSection(form, toolkit, AVAILABILITY, null, 2, false); + populateSummarySection(); + } + + private void populateSummarySection() { + if(volumes.getEntities().size() == 0) { + toolkit.createLabel(summarySection, + "This section will be populated after at least" + CoreConstants.NEWLINE +"one volume is created the storage cloud."); + return; + } + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, summarySection, values); + } + + private int getVolumeCountByStatus(EntityGroup volumes, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : (List) volumes.getEntities()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); + data.widthHint = 300; + data.heightHint = 150; + chartViewerComposite.setLayoutData(data); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesView.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesView.java new file mode 100644 index 00000000..4deeace2 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/VolumesView.java @@ -0,0 +1,80 @@ +/** + * DiscoveredServersView.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.console.views.pages.VolumesPage; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; + +/** + * + */ +public class VolumesView extends ViewPart implements IDoubleClickListener { + public static final String ID = VolumesView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup volumes; + private VolumesPage page; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void createPartControl(Composite parent) { + if (volumes == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Volume.class) { + volumes = (EntityGroup)selectedObj; + } + } + + page = new VolumesPage(parent, getSite(), volumes); + page.addDoubleClickListener(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractDisksPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractDisksPage.java new file mode 100644 index 00000000..62bbd871 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractDisksPage.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.net.URI; +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.TreeEditor; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.ImageHyperlink; + +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.client.TasksClient; +import com.gluster.storage.management.console.Application; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.IEntityListener; +import com.gluster.storage.management.console.dialogs.InitializeDiskTypeSelection; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Device; +import com.gluster.storage.management.core.model.Device.DEVICE_STATUS; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public abstract class AbstractDisksPage extends AbstractTableTreeViewerPage implements IEntityListener { + protected List disks; + + /** + * @return Index of the "status" column in the table. Return -1 if status column is not displayed + */ + protected abstract int getStatusColumnIndex(); + + public AbstractDisksPage(final Composite parent, int style, IWorkbenchSite site, List disks) { + super(site, parent, style, false, true, disks); + this.disks = disks; + + // creates hyperlinks for "unitialized" disks + setupStatusCellEditor(); + // Listen for disk status change events + Application.getApplication().addEntityListener(this); + } + + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @Override + public void serverChanged(GlusterServer server, Event event) { + super.serverChanged(server, event); + EVENT_TYPE eventType = event.getEventType(); + switch (eventType) { + case DEVICES_REMOVED: + case DEVICES_ADDED: + case DEVICES_CHANGED: + treeViewer.refresh(); + default: + break; + } + } + }; + } + + private void createInitializeLink(final TreeItem item, final int rowNum, final Device uninitializedDevice) { + final Tree tree = treeViewer.getTree(); + final TreeEditor editor = new TreeEditor(tree); + editor.grabHorizontal = true; + editor.horizontalAlignment = SWT.RIGHT; + + tree.addPaintListener(new PaintListener() { + private TreeItem myItem = item; + private int myRowNum = rowNum; + private ImageHyperlink myLink = null; + private TreeEditor myEditor = null; + + private void createLinkFor(Device uninitializedDevice, TreeItem item1, int rowNum1) { + myItem = item1; + myRowNum = rowNum1; + + myEditor = new TreeEditor(tree); + myEditor.grabHorizontal = true; + myEditor.horizontalAlignment = SWT.RIGHT; + + myLink = toolkit.createImageHyperlink(tree, SWT.NONE); + // link.setImage(guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED)); + myLink.setText("Initialize"); + myLink.addHyperlinkListener(new StatusLinkListener(myLink, myEditor, treeViewer, uninitializedDevice)); + + myEditor.setEditor(myLink, item1, getStatusColumnIndex()); + + myItem.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + myLink.dispose(); + myEditor.dispose(); + } + }); + } + + @Override + public void paintControl(PaintEvent e) { + int itemCount = tree.getItemCount(); + + // Find the table item corresponding to our disk + + Device device = null; + int rowNum1 = -1; + TreeItem item1 = null; + + mainloop: + for (int i = 0; i < itemCount; i++) { + item1 = tree.getItem(i); + + device = (Device) item1.getData(); + if (device != null && device == uninitializedDevice) { + // this is an uninitialized "disk" + rowNum1 = i; + break; + } + + int partitionCount = item1.getItemCount(); + for(int j = 0; j < partitionCount; j++) { + TreeItem partitionItem = item1.getItem(j); + // check each partition + Device partition = (Device)partitionItem.getData(); + if(partition != null && partition == uninitializedDevice) { + // this is an uninitialized "partition" + rowNum1 = i + j; + item1 = partitionItem; + device = partition; + // found the uninitialized device. break out. + break mainloop; + } + } + } + + if (rowNum1 == -1) { + // item disposed and disk not visible. nothing to do. + return; + } + + if (myEditor == null || myItem.isDisposed()) { + // item visible, and + // either editor never created, OR + // old item disposed. create the link for it + createLinkFor(device, item1, rowNum1); + } + + if (rowNum1 != myRowNum) { + // disk visible, but at a different row num. re-create the link + myLink.dispose(); + myEditor.dispose(); + createLinkFor(device, item1, rowNum1); + } + + myEditor.layout(); // IMPORTANT. Without this, the link location goes for a toss on maximize + restore + } + }); + } + + private void setupStatusCellEditor() { + final TreeViewer viewer = treeViewer; + final Tree tree = viewer.getTree(); + int rowNum = 0; + for (int i = 0; i < tree.getItemCount(); i++, rowNum++) { + final TreeItem item = tree.getItem(i); + if (item.isDisposed() || item.getData() == null) { + continue; + } + final Disk disk = (Disk) item.getData(); + if (disk.isUninitialized()) { + createInitializeLink(item, rowNum, disk); + } + + if (disk.hasPartitions()) { + for(int j = 0; j < disk.getPartitions().size(); j++, rowNum++) { + TreeItem partitionItem = item.getItem(j); + // check each partition + Device partition = (Device)partitionItem.getData(); + if (partition.isUninitialized()) { + createInitializeLink(partitionItem, rowNum, partition); + } + } + } + } + } + + private final class StatusLinkListener extends HyperlinkAdapter { + private final Device device; + private final TreeEditor myEditor; + private final ImageHyperlink myLink; + private final TreeViewer viewer; + + private StatusLinkListener(ImageHyperlink link, TreeEditor editor, TreeViewer viewer, Device device) { + this.device = device; + this.viewer = viewer; + this.myEditor = editor; + this.myLink = link; + } + + private void updateStatus(final DEVICE_STATUS status, final boolean disposeEditor) { + if (disposeEditor) { + myLink.dispose(); + myEditor.dispose(); + } + device.setStatus(status); + viewer.update(device, new String[] { "status" }); + Application.getApplication().entityChanged(device, new String[] { "status" }); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + InitializeDiskTypeSelection formatDialog = new InitializeDiskTypeSelection(getShell()); + int userAction = formatDialog.open(); + if (userAction == Window.CANCEL) { + formatDialog.cancelPressed(); + return; + } + + GlusterServersClient serversClient = new GlusterServersClient(); + try { + + URI uri = serversClient.initializeDisk(device.getServerName(), device.getName(), formatDialog.getFSType()); + + TasksClient taskClient = new TasksClient(); + TaskInfo taskInfo = taskClient.getTaskInfo(uri); + + if (taskInfo != null && taskInfo instanceof TaskInfo) { + GlusterDataModelManager.getInstance().getModel().getCluster().addTaskInfo(taskInfo); + } + + if (taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING) { + updateStatus(DEVICE_STATUS.INITIALIZING, true); + } else if (taskInfo.getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + updateStatus(DEVICE_STATUS.INITIALIZED, true); + GlusterDataModelManager.getInstance().updateDeviceStatus(device.getServerName(), device.getName(), + DEVICE_STATUS.INITIALIZED); + } + + } catch (Exception e1) { + MessageDialog.openError(getShell(), "Error: Initialize disk", e1.getMessage()); + } + } + } + + @Override + public void entityChanged(final Entity entity, final String[] paremeters) { + if (!(entity instanceof Device)) { + return; + } + final Device device = (Device) entity; + + Display.getDefault().syncExec(new Runnable() { + public void run() { + treeViewer.update(device, paremeters); + + if (device.isUninitialized()) { + Tree tree = treeViewer.getTree(); + + for (int rowNum = 0; rowNum < tree.getItemCount(); rowNum++) { + TreeItem item = tree.getItem(rowNum); + if (item.getData() == device) { + createInitializeLink(item, rowNum, device); + } + } + } + } + }); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableTreeViewerPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableTreeViewerPage.java new file mode 100644 index 00000000..7414bbc3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableTreeViewerPage.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TreeColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.Disk; + +public abstract class AbstractTableTreeViewerPage extends Composite implements ISelectionListener { + + protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + protected TreeViewer treeViewer; + protected GUIHelper guiHelper = GUIHelper.getInstance(); + protected Composite parent; + protected IWorkbenchSite site; + private ClusterListener clusterListener; + + private Text filterText; + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private Composite createTreeViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + GridData layoutData = new GridData(); + layoutData.horizontalSpan=5; + layoutData.grabExcessHorizontalSpace = true; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.verticalAlignment = SWT.FILL; + layoutData.grabExcessVerticalSpace = true; + tableViewerComposite.setLayoutData(layoutData); + + return tableViewerComposite; + } + + + public AbstractTableTreeViewerPage(IWorkbenchSite site, final Composite parent, int style, boolean useChechboxes, + boolean multiSelection, List allDisks) { + super(parent, style); + + setupPageLayout(); + //new FormToolkit(Display.getCurrent()).createButton(this, "test1", SWT.PUSH); + + this.parent = parent; + this.site = site; + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + parent.setLayoutData(data); + + filterText = guiHelper.createFilterText(toolkit, this); + + Composite tableViewerComposite = createTreeViewerComposite(); + createTreeViewer(allDisks, tableViewerComposite); + parent.layout(); // Important - this actually paints the table + + createListeners(parent); + } + + private void createListeners(final Composite parent) { + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + + clusterListener = createClusterListener(); + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + }); + } + + protected abstract ClusterListener createClusterListener(); + protected abstract IBaseLabelProvider getLabelProvider(); + protected abstract IContentProvider getContentProvider(); + + private void createTreeViewer(List allDisks, Composite tableViewerComposite) { + treeViewer = new TreeViewer(tableViewerComposite); + treeViewer.getTree().setHeaderVisible(true); + treeViewer.getTree().setLinesVisible(true); + + TreeColumnLayout ad = new TreeColumnLayout(); + tableViewerComposite.setLayout(ad); + + TreeColumn column = new TreeColumn(treeViewer.getTree(),SWT.NONE); + column.setWidth(100); + column.setText("Disk"); + ad.setColumnData(column, new ColumnWeightData(50, 100)); + + column = new TreeColumn(treeViewer.getTree(),SWT.NONE); + column.setWidth(100); + column.setText("Partition"); + ad.setColumnData(column,new ColumnWeightData(50, 100)); + + column = new TreeColumn(treeViewer.getTree(),SWT.NONE); + column.setWidth(100); + column.setText("Free Space (GB)"); + ad.setColumnData(column, new ColumnWeightData(50, 100)); + + column = new TreeColumn(treeViewer.getTree(),SWT.NONE); + column.setWidth(100); + column.setText("Total Space (GB)"); + ad.setColumnData(column,new ColumnWeightData(50, 100)); + + column = new TreeColumn(treeViewer.getTree(),SWT.NONE); + column.setWidth(100); + column.setText("Status"); + ad.setColumnData(column,new ColumnWeightData(50, 100)); + + treeViewer.setLabelProvider(getLabelProvider()); + treeViewer.setContentProvider(getContentProvider()); + treeViewer.setInput(allDisks); + + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(treeViewer, filterText, false); + + treeViewer.expandAll(); + } + + + /* (non-Javadoc) + * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableViewerPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableViewerPage.java new file mode 100644 index 00000000..91780403 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/AbstractTableViewerPage.java @@ -0,0 +1,234 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.ClusterListener; + +public abstract class AbstractTableViewerPage extends Composite implements ISelectionListener { + + private boolean useCheckboxes; + private boolean multiSelection; + + protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + protected TableViewer tableViewer; + protected GUIHelper guiHelper = GUIHelper.getInstance(); + protected Composite parent; + protected IWorkbenchSite site; + + private Hyperlink linkAll, linkNone; + private ClusterListener clusterListener; + + public AbstractTableViewerPage(IWorkbenchSite site, final Composite parent, int style, boolean useChechboxes, boolean multiSelection, Object model) { + super(parent, style); + this.parent = parent; + this.site = site; + + this.useCheckboxes = useChechboxes; + this.multiSelection = multiSelection; + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + + createCheckboxSelectionLinks(); + + Text filterText = guiHelper.createFilterText(toolkit, this); + + setupTableViewer(site, filterText); + tableViewer.setInput(model); + // register as selection provider so that other views can listen to any selection events on the tree + site.setSelectionProvider(tableViewer); + site.getPage().addSelectionListener(this); + + + parent.layout(); // Important - this actually paints the table + + createListeners(parent); + } + + public void createCheckboxSelectionLinks() { + if (useCheckboxes) { + // create the "select all/none" links + toolkit.createLabel(this, "Select"); + linkAll = toolkit.createHyperlink(this, "all", SWT.NONE); + linkAll.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + ((CheckboxTableViewer) tableViewer).setAllChecked(true); + tableViewer.setSelection(new StructuredSelection(getAllEntities())); + } + }); + + toolkit.createLabel(this, " / "); + + linkNone = toolkit.createHyperlink(this, "none", SWT.NONE); + linkNone.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + ((CheckboxTableViewer) tableViewer).setAllChecked(false); + tableViewer.setSelection(null); + } + }); + } else { + // create dummy labels to maintain layout + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + } + } + + private void createListeners(final Composite parent) { + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + + clusterListener = createClusterListener(); + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + }); + } + + protected abstract ClusterListener createClusterListener(); + protected abstract String[] getColumnNames(); + protected abstract void setColumnProperties(Table table); + protected abstract IBaseLabelProvider getLabelProvider(); + protected abstract IContentProvider getContentProvider(); + protected abstract List getAllEntities(); + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(5, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + protected void setupTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, getColumnNames()); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table); + } + + private void createTableViewer(Composite parent) { + int style = SWT.FLAT | SWT.FULL_SELECTION; + style |= (multiSelection ? SWT.MULTI : SWT.SINGLE); + + if(useCheckboxes) { + tableViewer = CheckboxTableViewer.newCheckList(parent, style); + } else { + tableViewer = new TableViewer(parent, style); + } + + tableViewer.setLabelProvider(getLabelProvider()); + tableViewer.setContentProvider(getContentProvider()); + setupTable(parent, tableViewer.getTable()); + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + GridData layoutData = new GridData(); + layoutData.horizontalSpan=5; + layoutData.grabExcessHorizontalSpace = true; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.verticalAlignment = SWT.FILL; + layoutData.grabExcessVerticalSpace = true; + tableViewerComposite.setLayoutData(layoutData); + + return tableViewerComposite; + } + + private void setupTableViewer(IWorkbenchSite site, final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + createTableViewer(tableViewerComposite); + site.setSelectionProvider(tableViewer); + + if(useCheckboxes) { + // make sure that table selection is driven by checkbox selection + guiHelper.configureCheckboxTableViewer((CheckboxTableViewer)tableViewer); + } + + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/BricksPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/BricksPage.java new file mode 100644 index 00000000..39e79beb --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/BricksPage.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.BrickTableLabelProvider; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Volume; + +public class BricksPage extends AbstractTableViewerPage { + private List bricks; + + public enum BRICK_TABLE_COLUMN_INDICES { + SERVER, BRICK, FREE_SPACE, TOTAL_SPACE, STATUS + }; + + private static final String[] DISK_TABLE_COLUMN_NAMES = new String[] { "Server", "Brick Directory", "Free Space (GB)", + "Total Space (GB)", "Status" }; + + public BricksPage(Composite parent, int style, IWorkbenchSite site, final List bricks) { + super(site, parent, style, true, true, bricks); + this.bricks = bricks; + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @SuppressWarnings("unchecked") + @Override + public void volumeChanged(Volume volume, Event event) { + switch (event.getEventType()) { + case BRICKS_ADDED: + tableViewer.add(((Collection) event.getEventData()).toArray()); + parent.update(); + break; + + case BRICKS_REMOVED: + tableViewer.remove(((Collection) event.getEventData()).toArray()); + parent.update(); + break; + + case BRICKS_CHANGED: + Object eventData = event.getEventData(); + Brick[] updatedBricks; + if(eventData instanceof Map) { + updatedBricks = ((Map) eventData).keySet().toArray(new Brick[0]); + } else { + updatedBricks = ((Collection)eventData).toArray(new Brick[0]); + } + tableViewer.update(updatedBricks, null); + parent.update(); + default: + break; + } + } + }; + } + + @Override + protected String[] getColumnNames() { + return DISK_TABLE_COLUMN_NAMES; + } + + @Override + protected void setColumnProperties(Table table) { + guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.SERVER.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.BRICK.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal(), SWT.CENTER, 90); + } + + @Override + protected ITableLabelProvider getLabelProvider() { + return new BrickTableLabelProvider(); + } + + @Override + protected IContentProvider getContentProvider() { + return new ArrayContentProvider(); + } + + @Override + protected List getAllEntities() { + return bricks; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DiskTreeContentProvider.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DiskTreeContentProvider.java new file mode 100644 index 00000000..4081d614 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DiskTreeContentProvider.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Partition; + +public class DiskTreeContentProvider implements ITreeContentProvider { + + private List disks = new ArrayList(); + + public DiskTreeContentProvider(List disks) { + this.disks = disks; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return ((List) inputElement).toArray(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) { + if(parentElement instanceof Disk) { + return ((Disk)parentElement).getPartitions().toArray(); + } else { + return null; + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) { + if (element == null) { + return null; + } + + if(element instanceof Partition) { + // find the disk of this partition and return + return getDiskForPartition((Partition)element); + } else { + return null; + } + } + + private Disk getDiskForPartition(Partition partition) { + for(Disk disk : disks) { + for(Partition diskPartition : disk.getPartitions()) { + if(partition.getName().equals(diskPartition.getName())) { + return disk; + } + } + } + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + if(element instanceof Disk && ((Disk)element).getPartitions().size() > 0) { + return true; + } else { + return false; + } + } + + + +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DisksPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DisksPage.java new file mode 100644 index 00000000..8501bef3 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/DisksPage.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.DeviceTableLabelProvider; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; + +public class DisksPage extends AbstractDisksPage { + + public enum DISK_TABLE_COLUMN_INDICES { + DISK, PARTITION, FREE_SPACE, TOTAL_SPACE, STATUS + }; + + private static final String[] DISK_TABLE_COLUMN_NAMES = new String[] { "Disk", "Partition", "Free Space (GB)", + "Total Space (GB)", "Status" }; + + public DisksPage(final Composite parent, int style, IWorkbenchSite site, List disks) { + super(parent, style, site, disks); + } + + private String getDiskTableColumnDesc(DISK_TABLE_COLUMN_INDICES idx) { + return DISK_TABLE_COLUMN_NAMES[idx.ordinal()]; + } + + @Override + protected DeviceTableLabelProvider getLabelProvider() { + return new DeviceTableLabelProvider(); + } + + + @Override + protected IContentProvider getContentProvider() { + return new DiskTreeContentProvider(disks); + } + + @Override + protected int getStatusColumnIndex() { + return DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } + + @Override + public void entityChanged(Entity entity, String[] paremeters) { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/GlusterServersPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/GlusterServersPage.java new file mode 100644 index 00000000..8be17b24 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/GlusterServersPage.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.EntityGroupContentProvider; +import com.gluster.storage.management.console.GlusterServerTableLabelProvider; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterServer; + +public class GlusterServersPage extends AbstractTableViewerPage { + private List glusterServers; + + public enum GLUSTER_SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_CPUS, TOTAL_MEMORY, TOTAL_FREE_SPACE, TOTAL_DISK_SPACE, STATUS // Removed PREFERRED_NETWORK + }; + + private static final String[] GLUSTER_SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", "IP Address(es)", + "Number" + CoreConstants.NEWLINE + "of CPUs", "Total" + CoreConstants.NEWLINE + "Memory (GB)", + "Free Space (GB)", "Total " + CoreConstants.NEWLINE + " Space (GB)", "Status" }; // Removed "Preferred\nNetwork", + + public GlusterServersPage(IWorkbenchSite site, final Composite parent, int style, final EntityGroup servers) { + super(site, parent, style, true, true, servers); + this.glusterServers = servers.getEntities(); + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + + @Override + public void serverAdded(GlusterServer server) { + tableViewer.add(server); + parent.update(); + } + + @Override + public void serverRemoved(GlusterServer server) { + tableViewer.remove(server); + parent.update(); + } + + @Override + public void serverChanged(GlusterServer server, Event event) { + tableViewer.update(server, null); + parent.update(); + } + }; + } + + @Override + protected void setColumnProperties(Table table) { + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 100); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS, SWT.CENTER, 70); + // setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.PREFERRED_NETWORK, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_FREE_SPACE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new GlusterServerTableLabelProvider(); + } + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider(); + } + + @Override + protected String[] getColumnNames() { + return GLUSTER_SERVER_TABLE_COLUMN_NAMES; + } + + @Override + protected List getAllEntities() { + return glusterServers; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, GLUSTER_SERVER_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionKeyEditingSupport.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionKeyEditingSupport.java new file mode 100644 index 00000000..393b4f28 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionKeyEditingSupport.java @@ -0,0 +1,120 @@ +/** + * + */ +package com.gluster.storage.management.console.views.pages; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ComboBoxCellEditor; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.VolumeOption; +import com.gluster.storage.management.core.model.VolumeOptionInfo; +import com.gluster.storage.management.core.model.VolumeOptions; + +/** + * Editing support for the "value" column in volume options table viewer. + */ +public class OptionKeyEditingSupport extends EditingSupport { + private CellEditor cellEditor; + private Volume volume; + private List defaults = GlusterDataModelManager.getInstance().getVolumeOptionsDefaults(); + private String[] allowedKeys; + private ColumnViewer viewer; + + public OptionKeyEditingSupport(ColumnViewer viewer, Volume volume) { + super(viewer); + this.volume = volume; + this.viewer = viewer; + } + + /** + * @return array of option keys that are not already set on the volume + */ + private String[] getAllowedKeys() { + ArrayList keys = new ArrayList(); + VolumeOptions volumeOptions = volume.getOptions(); + for(VolumeOptionInfo optionInfo : defaults) { + String optionName = optionInfo.getName(); + if(!volumeOptions.containsKey(optionName) || volumeOptions.get(optionName).isEmpty()) { + // key not set => available for setting + // value not set => this is the row being edited + keys.add(optionName); + } + } + return keys.toArray(new String[0]); + } + + @Override + protected void setValue(final Object element, final Object value) { + VolumeOption oldEntry = (VolumeOption)element; + Integer newValue = (Integer)value; + String newKey = allowedKeys[newValue]; + + if (((VolumeOption)element).getKey().equals(newKey)) { + // selected value is same as old one. + return; + } + + // value has changed. set new value and refresh the viewer. + volume.getOptions().remove(oldEntry.getKey()); + volume.setOption(newKey, ""); + getViewer().refresh(); + } + + @Override + protected Object getValue(Object element) { + VolumeOption entryBeingAdded = getEntryBeingAdded(); + if(entryBeingAdded == null) { + return cellEditor.getValue(); + } + + if(entryBeingAdded.getKey().isEmpty()) { + // editing just about to start. set first element as default. + return 0; + } + + return getIndexOfEntry(entryBeingAdded); + } + + @Override + protected CellEditor getCellEditor(Object element) { + allowedKeys = getAllowedKeys(); + cellEditor = new ComboBoxCellEditor((Composite) viewer.getControl(), allowedKeys, SWT.READ_ONLY); + return cellEditor; + } + + private int getIndexOfEntry(VolumeOption entryBeingAdded) { + for(int index = 0; index < allowedKeys.length; index++) { + if(allowedKeys[index].equals(entryBeingAdded.getKey())) { + return index; + } + } + return -1; + } + + protected VolumeOption getEntryBeingAdded() { + List options = volume.getOptions().getOptions(); + int size = options.size(); + String lastValue = options.get(size - 1).getValue(); + if(lastValue == null || lastValue.isEmpty()) { + // it's the LAST entry, and it's value is empty. + // means this is a new row being added in the table viewer. + return options.get(size - 1); + } + return null; + } + + @Override + protected boolean canEdit(Object element) { + VolumeOption entry = (VolumeOption)element; + return (entry.getKey().isEmpty() || entry.getValue().isEmpty()); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionValueEditingSupport.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionValueEditingSupport.java new file mode 100644 index 00000000..6bce3997 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/OptionValueEditingSupport.java @@ -0,0 +1,110 @@ +/** + * + */ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.VolumeOption; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +/** + * Editing support for the "value" column in volume options table viewer. + */ +public class OptionValueEditingSupport extends EditingSupport { + private CellEditor cellEditor; + private Volume volume; + private List defaults = GlusterDataModelManager.getInstance().getVolumeOptionsDefaults(); + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public OptionValueEditingSupport(ColumnViewer viewer, Volume volume) { + super(viewer); + this.volume = volume; + this.cellEditor = new TextCellEditor((Composite) viewer.getControl()); + } + + @Override + protected void setValue(final Object element, final Object value) { + final VolumeOption entry = (VolumeOption)element; + final String optionKey = entry.getKey(); + final String optionValue = (String)value; + final String oldValue = entry.getValue(); + + // It is not allowed to change value to empty string + if(optionValue.isEmpty()) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Set Volume Option", + "Option value can't be empty! Please enter a valid value."); + cellEditor.setFocus(); + return; + } + + if (oldValue.equals(optionValue)) { + // value is same as that present in the model. return without doing anything. + return; + } + + // value has changed. set volume option at back-end and update model accordingly + guiHelper.setStatusMessage("Setting option [" + optionKey + " = " + optionValue + "]..."); + getViewer().getControl().update(); + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + + @Override + public void run() { + VolumesClient client = new VolumesClient(); + try { + client.setVolumeOption(volume.getName(), optionKey, optionValue); + GlusterDataModelManager.getInstance().setVolumeOption(volume, optionKey, optionValue); + } catch(Exception e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "Set Volume Option", e.getMessage()); + } + getViewer().update(entry, null); + } + }); + + guiHelper.clearStatusMessage(); + getViewer().getControl().update(); + } + + /** + * @param key Key whose default value is to be fetched + * @return Default value of the volume option with given key + */ + private String getDefaultValue(String key) { + for(VolumeOptionInfo optionInfo : defaults) { + if(optionInfo.getName().equals(key)) { + return optionInfo.getDefaultValue(); + } + } + return ""; + } + + @Override + protected Object getValue(Object element) { + VolumeOption entry = (VolumeOption) element; + return entry.getValue().isEmpty() ? getDefaultValue(entry.getKey()) : entry.getValue(); + } + + @Override + protected CellEditor getCellEditor(Object element) { + return cellEditor; + } + + @Override + protected boolean canEdit(Object element) { + return true; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerDisksPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerDisksPage.java new file mode 100644 index 00000000..a2982590 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerDisksPage.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.ServerDiskTableLabelProvider; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; + +public class ServerDisksPage extends AbstractDisksPage { + + public ServerDisksPage(Composite parent, int style, IWorkbenchSite site, List disks) { + super(parent, style, site, disks); + } + + public enum SERVER_DISK_TABLE_COLUMN_INDICES { + DISK, PARTITION, FREE_SPACE, TOTAL_SPACE, STATUS + }; + + private static final String[] SERVER_DISK_TABLE_COLUMN_NAMES = new String[] { "Disk", "Partition", "Free Space (GB)", + "Total Space (GB)", "Status" }; + + @Override + protected int getStatusColumnIndex() { + return SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } + + @Override + protected ServerDiskTableLabelProvider getLabelProvider() { + // return new DeviceTableLabelProvider(); + return new ServerDiskTableLabelProvider(); + } + + + @Override + protected IContentProvider getContentProvider() { + return new DiskTreeContentProvider(disks); + } + + @Override + public void entityChanged(Entity entity, String[] paremeters) { + // TODO Auto-generated method stub + + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerLogsPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerLogsPage.java new file mode 100644 index 00000000..7b3f3946 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServerLogsPage.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.model.GlusterServer; + +public class ServerLogsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Text text; + private Table table; + + public enum LOG_TABLE_COLUMN_INDICES { + DATE, TIME, DISK, SEVERITY, MESSAGE + }; + + private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Disk", "Severity", "Message" }; + + /** + * Create the composite. + * + * @param parent + * @param style + */ + public ServerLogsPage(Composite parent, int style, GlusterServer server) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setLayout(new GridLayout(1, false)); + GridData layoutData = new GridData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + setLayoutData(layoutData); + + Composite composite = toolkit.createComposite(this, SWT.NONE); + toolkit.paintBordersFor(composite); + + Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE); + lblScanLast.setBounds(0, 15, 80, 20); + + text = toolkit.createText(composite, "100", SWT.NONE); + text.setBounds(85, 15, 60, 20); + text.setTextLimit(4); + text.addVerifyListener(new VerifyListener() { + + @Override + public void verifyText(VerifyEvent event) { + // Assume we allow it + event.doit = true; + + String text = event.text; + char[] chars = text.toCharArray(); + + // Don't allow if text contains non-digit characters + for (int i = 0; i < chars.length; i++) { + if (!Character.isDigit(chars[i])) { + event.doit = false; + break; + } + } + + } + }); + + Label lblMessagesAndFilter = toolkit.createLabel(composite, " messages from ", SWT.CENTER); + lblMessagesAndFilter.setBounds(160, 15, 110, 20); + + Combo combo = new Combo(composite, SWT.CENTER); + combo.setBounds(295, 15, 100, 20); + combo.setItems(new String[] { "syslog", "dmesg" }); + toolkit.adapt(combo); + toolkit.paintBordersFor(combo); + combo.select(0); + + Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE); + btngo.setBounds(410, 13, 50, 30); + + Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL); + separator.setBounds(0, 50, 500, 2); + + Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT); + lblFilterString.setBounds(0, 65, 100, 20); + + text = guiHelper.createFilterText(toolkit, composite); + text.setBounds(105, 65, 250, 20); + + Composite logContentsComposite = createLogContentsComposite(toolkit); + // Text logContentsText = toolkit.createText(logContentsComposite, "", SWT.MULTI | SWT.FLAT | SWT.BORDER); + // logContentsText.setEditable(false); + // populateDummyLogContent(logContentsText); + + ListViewer logViewer = new ListViewer(logContentsComposite, SWT.BORDER | SWT.V_SCROLL | SWT.NO); + logViewer.setContentProvider(new ArrayContentProvider()); + guiHelper.createFilter(logViewer, text, false); + logViewer.setInput(getDummyLogContents()); + + // TODO: Link the filter string with the contents text + } + + private Composite createLogContentsComposite(FormToolkit toolkit) { + Composite tableViewerComposite = toolkit.createComposite(this, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.verticalIndent = 10; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; + } + + private String[] getDummyLogContents() { + + String[] logMessages = { + "Jan 19 13:43:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:44:08 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:44:47 shireesh-laptop dhclient: last message repeated 2 times", + "Jan 19 13:44:47 shireesh-laptop dhclient: DHCPREQUEST of 192.168.1.174 on eth1 to 255.255.255.255 port 67", + "Jan 19 13:45:49 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:46:59 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:48:01 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:49:02 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:50:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:51:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:52:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:53:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:54:08 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:55:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:56:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:57:08 shireesh-laptop dhclient: last message repeated 3 times", + "Jan 19 13:58:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:59:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:59:40 shireesh-laptop dhclient: last message repeated 3 times", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: DHCP: device eth1 state changed bound -> expire", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 8", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: DHCP: device eth1 state changed expire -> preinit", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPOFFER of 192.168.1.174 from 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPREQUEST of 192.168.1.174 on eth1 to 255.255.255.255 port 67", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPACK of 192.168.1.174 from 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop dhclient: bound to 192.168.1.174 -- renewal in 3205 seconds.", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: DHCP: device eth1 state changed preinit -> bound", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: address 192.168.1.174", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: prefix 24 (255.255.255.0)", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: gateway 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: nameserver '192.168.1.1'", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: domain name 'in.gluster.com'", + "Jan 19 14:03:53 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:53 shireesh-laptop avahi-daemon[1098]: Received response from host 192.168.1.155 with invalid source port 37219 on interface 'eth0.0'", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Received response from host 192.168.1.155 with invalid source port 37219 on interface 'eth0.0'", + "Jan 19 14:05:09 shireesh-laptop avahi-daemon[1098]: last message repeated 8 times", + "Jan 19 14:12:48 shireesh-laptop NetworkManager: [1295426568.002642] periodic_update(): Roamed from BSSID E0:CB:4E:C0:0B:7F (glfs) to (none) ((none))", + "Jan 19 14:12:54 shireesh-laptop NetworkManager: [1295426574.002448] periodic_update(): Roamed from BSSID (none) ((none)) to E0:CB:4E:C0:0B:7F (glfs)", + "Jan 19 14:17:01 shireesh-laptop CRON[5321]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)" }; + + return logMessages; + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServersPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServersPage.java new file mode 100644 index 00000000..99945b31 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/ServersPage.java @@ -0,0 +1,131 @@ + /******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.EntityGroupContentProvider; +import com.gluster.storage.management.console.ServerTableLabelProvider; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Server; + +public class ServersPage extends AbstractTableViewerPage { + private List servers; + + public enum SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_DISKS, TOTAL_DISK_SPACE + }; + + private static final String[] SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", "IP Address(es)", "Number of Disks", "Total Disk Space (GB)" }; + + public ServersPage(final Composite parent, IWorkbenchSite site, EntityGroup serversGroup) { + super(site, parent, SWT.NONE, true, true, serversGroup); + this.servers = serversGroup.getEntities(); + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @Override + public void discoveredServerRemoved(Server server) { + tableViewer.remove(server); + parent.update(); + } + + @Override + public void discoveredServerAdded(Server server) { + tableViewer.add(server); + parent.update(); + } + + @Override + public void discoveredServerChanged(Server server, Event event) { + tableViewer.update(server, null); + parent.update(); + } + }; + } + + public void setInput(EntityGroup servers) { + tableViewer.setInput(servers); + tableViewer.refresh(); + } + + @Override + protected void setColumnProperties(Table table) { + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 70); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES, SWT.CENTER, 100); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NUM_OF_DISKS, SWT.CENTER, 70); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE, SWT.CENTER, 70); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.NUM_OF_CPUS, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.TOTAL_MEMORY, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + @Override + protected String[] getColumnNames() { + return SERVER_TABLE_COLUMN_NAMES; + } + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new ServerTableLabelProvider(); + } + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider(); + } + + @Override + protected List getAllEntities() { + return servers; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + private void setColumnProperties(Table table, SERVER_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/TasksPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/TasksPage.java new file mode 100644 index 00000000..4c399a4c --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/TasksPage.java @@ -0,0 +1,144 @@ +/** + * TasksPage.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.TasksTableLabelProvider; +import com.gluster.storage.management.console.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.TaskInfo; + +public class TasksPage extends AbstractTableViewerPage { + private List taskInfoList; + private TaskInfo selectedTask; + + public enum TASK_TABLE_COLUMN_INDICES { + TASK, STATUS + }; + + private static final String[] TASK_TABLE_COLUMN_NAMES = new String[] { "Task", "Status"}; + + + public TasksPage(IWorkbenchSite site, Composite parent, int style, List taskInfo) { + super(site, parent, style, false, false, taskInfo); + this.taskInfoList = taskInfo; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#createClusterListener() + */ + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @Override + public void taskAdded(TaskInfo taskInfo) { + tableViewer.add(taskInfo); + parent.update(); + } + + @Override + public void taskRemoved(TaskInfo taskInfo) { + tableViewer.remove(taskInfo); + parent.update(); + // hide the task related actionset as no task is selected + // site.getPage().hideActionSet(IActionConstants.ACTION_SET_TASK); + } + + @Override + public void taskUpdated(TaskInfo taskInfo) { + tableViewer.update(taskInfo, null); + parent.update(); + // fire selection event so that toolbar gets updated + // (the action class listens to selection and enables/disables automatically) + tableViewer.setSelection(new StructuredSelection(taskInfo)); + } + }; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#getColumnNames() + */ + @Override + protected String[] getColumnNames() { + return TASK_TABLE_COLUMN_NAMES; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#setColumnProperties(org.eclipse.swt.widgets.Table) + */ + @Override + protected void setColumnProperties(Table table) { + guiHelper.setColumnProperties(table, TASK_TABLE_COLUMN_INDICES.TASK.ordinal(), SWT.LEFT, 50); + guiHelper.setColumnProperties(table, TASK_TABLE_COLUMN_INDICES.STATUS.ordinal(), SWT.LEFT, 50); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#getLabelProvider() + */ + @Override + protected IBaseLabelProvider getLabelProvider() { + return new TasksTableLabelProvider(); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#getContentProvider() + */ + @Override + protected IContentProvider getContentProvider() { + return new ArrayContentProvider(); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#getAllEntities() + */ + @Override + protected List getAllEntities() { + return taskInfoList; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.console.views.pages.AbstractTableViewerPage#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (selection instanceof StructuredSelection) { + Entity selectedEntity = (Entity) ((StructuredSelection) selection).getFirstElement(); + if (selectedEntity != null && selectedEntity instanceof TaskInfo && selectedEntity != selectedTask) { + selectedTask = (TaskInfo)selectedEntity; + new GlusterToolbarManager(part.getSite().getWorkbenchWindow()).updateToolbar(selectedTask); + } + } + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeLogsPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeLogsPage.java new file mode 100644 index 00000000..87c319ef --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeLogsPage.java @@ -0,0 +1,426 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.DateTime; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.console.VolumeLogTableLabelProvider; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.constants.GlusterConstants.VOLUME_LOG_LEVELS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.VolumeLogMessage; + +public class VolumeLogsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Text filterText; + private Text lineCountText; + private Volume volume; + + public enum LOG_TABLE_COLUMN_INDICES { + DATE, TIME, BRICK, SEVERITY, MESSAGE + }; + + private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Brick", "Severity", "Message" }; + private TableViewer tableViewer; + private Combo bricksCombo; + private Combo severityCombo; + private DateTime fromDate; + private DateTime fromTime; + private DateTime toDate; + private DateTime toTime; + private Button fromCheckbox; + private Button toCheckbox; + + /** + * Create the volume logs page + * + * @param parent + * @param style + * @param volume + * Volume for which the logs page is to be created + */ + public VolumeLogsPage(Composite parent, int style, Volume volume) { + super(parent, style); + this.volume = volume; + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + configureLayout(); + + Composite composite = toolkit.createComposite(this, SWT.NONE); + toolkit.paintBordersFor(composite); + + createLineCountLabel(composite); + createLineCountText(composite); + + createBricksLabel(composite); + createBricksCombo(composite); + + createSeverityLabel(composite); + createSeverityCombo(composite); + + createFromDateLabel(composite); + createFromDateField(composite); + createFromTimeField(composite); + createFromCheckbox(composite); + + createToDateLabel(composite); + createToDateField(composite); + createToTimeField(composite); + createToCheckbox(composite); + + createSearchButton(composite); + + createSeparator(composite); + + createFilterLabel(composite); + createFilterText(composite); + + createLogTableViewer(); + } + + private void createLogTableViewer() { + Composite tableViewerComposite = createTableViewerComposite(); + + tableViewer = new TableViewer(tableViewerComposite, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeLogTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupLogsTable(tableViewerComposite, tableViewer.getTable()); + guiHelper.createFilter(tableViewer, filterText, false); + } + + private void createFilterText(Composite composite) { + filterText = guiHelper.createFilterText(toolkit, composite); + filterText.setBounds(90, 105, 250, 20); + } + + private void createFilterLabel(Composite composite) { + Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT); + lblFilterString.setBounds(0, 105, 85, 20); + } + + private void createSeparator(Composite composite) { + Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL); + separator.setBounds(0, 95, 680, 2); + } + + private void createSearchButton(Composite composite) { + Button btnGo = toolkit.createButton(composite, "&Go", SWT.NONE); + btnGo.setBounds(615, 55, 50, 30); + btnGo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + VolumesClient client = new VolumesClient(); + + Date fromTimestamp = null; + Date toTimestamp = null; + + if (fromCheckbox.getSelection()) { + fromTimestamp = extractTimestamp(fromDate, fromTime); + } + + if (toCheckbox.getSelection()) { + toTimestamp = extractTimestamp(toDate, toTime); + } + + if (!validateTimeRange(fromTimestamp, toTimestamp)) { + return; + } + + try { + List logMessages = client.getLogs(volume.getName(), bricksCombo.getText(), + severityCombo.getText(), fromTimestamp, toTimestamp, + Integer.parseInt(lineCountText.getText())); + tableViewer.setInput(logMessages.toArray(new VolumeLogMessage[0])); + tableViewer.refresh(); + } catch (Exception ex) { + MessageDialog.openError(getShell(), "Volume Logs", + "Error while fetching volume logs: [" + ex.getMessage() + "]"); + } + } + }); + } + + protected boolean validateTimeRange(Date fromTimestamp, Date toTimestamp) { + if (fromTimestamp == null && toTimestamp == null) { + // no time range selected. nothing to validate. + return true; + } + + Calendar calendar = Calendar.getInstance(); + Date now = calendar.getTime(); + if (fromTimestamp != null && fromTimestamp.after(now)) { + MessageDialog.openError(getShell(), "Volume Logs", "From time can't be greater than current time!"); + return false; + } + + if (toTimestamp != null) { + if (toTimestamp.after(now)) { + MessageDialog.openError(getShell(), "Volume Logs", "To time can't be greater than current time!"); + return false; + } + + if (fromTimestamp.after(toTimestamp)) { + MessageDialog.openError(getShell(), "Volume Logs", "From time can't be greater than To time!"); + return false; + } + } + + return true; + } + + private void createToCheckbox(Composite composite) { + toCheckbox = toolkit.createButton(composite, null, SWT.CHECK); + toCheckbox.setBounds(320, 60, 15, 20); + toCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (toCheckbox.getSelection()) { + toDate.setEnabled(true); + toTime.setEnabled(true); + } else { + toDate.setEnabled(false); + toTime.setEnabled(false); + } + } + }); + } + + private void createToTimeField(Composite composite) { + toTime = new DateTime(composite, SWT.BORDER | SWT.TIME); + toTime.setBounds(490, 60, 120, 20); + toTime.setEnabled(false); + toolkit.adapt(toTime); + toolkit.paintBordersFor(toTime); + } + + private void createToDateField(Composite composite) { + toDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + toDate.setBounds(365, 60, 120, 20); + toDate.setEnabled(false); + toolkit.adapt(toDate); + toolkit.paintBordersFor(toDate); + } + + private void createToDateLabel(Composite composite) { + Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE); + lblTo.setBounds(340, 60, 25, 20); + } + + private void createFromCheckbox(Composite composite) { + fromCheckbox = toolkit.createButton(composite, null, SWT.CHECK); + fromCheckbox.setBounds(0, 60, 15, 20); + fromCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (fromCheckbox.getSelection()) { + fromDate.setEnabled(true); + fromTime.setEnabled(true); + } else { + fromDate.setEnabled(false); + fromTime.setEnabled(false); + } + } + }); + } + + private void createFromTimeField(Composite composite) { + fromTime = new DateTime(composite, SWT.BORDER | SWT.TIME); + fromTime.setBounds(190, 60, 120, 20); + fromTime.setEnabled(false); + toolkit.adapt(fromTime); + toolkit.paintBordersFor(fromTime); + } + + private void createFromDateField(Composite composite) { + fromDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + fromDate.setBounds(60, 60, 120, 20); + fromDate.setEnabled(false); + toolkit.adapt(fromDate); + toolkit.paintBordersFor(fromDate); + } + + private void createFromDateLabel(Composite composite) { + Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE); + lblFrom.setBounds(20, 60, 40, 20); + } + + private void createSeverityCombo(Composite composite) { + severityCombo = new Combo(composite, SWT.READ_ONLY); + severityCombo.setBounds(555, 15, 110, 20); + + severityCombo.setItems(GlusterConstants.VOLUME_LOG_LEVELS_ARR.toArray(new String[0])); + severityCombo.select(VOLUME_LOG_LEVELS.ERROR.ordinal()); + severityCombo.add(CoreConstants.ALL, 0); + + toolkit.adapt(severityCombo); + toolkit.paintBordersFor(severityCombo); + } + + private void createSeverityLabel(Composite composite) { + Label lblSeverity = toolkit.createLabel(composite, "Severity", SWT.NONE); + lblSeverity.setBounds(480, 15, 70, 20); + } + + private void createBricksCombo(Composite composite) { + bricksCombo = new Combo(composite, SWT.READ_ONLY); + bricksCombo.setBounds(365, 15, 100, 20); + bricksCombo.setItems( volume.getBrickDirectories().toArray(new String[0])); + bricksCombo.add(CoreConstants.ALL, 0); + toolkit.adapt(bricksCombo); + toolkit.paintBordersFor(bricksCombo); + bricksCombo.select(0); + } + + private void createBricksLabel(Composite composite) { + Label lblMessagesAndFilter = toolkit.createLabel(composite, "messages, and filter on bricks", SWT.NONE); + lblMessagesAndFilter.setBounds(160, 15, 200, 20); + } + + private void createLineCountText(Composite composite) { + lineCountText = toolkit.createText(composite, "100", SWT.NONE); + lineCountText.setBounds(85, 15, 60, 20); + lineCountText.setTextLimit(4); + lineCountText.addVerifyListener(new VerifyListener() { + + @Override + public void verifyText(VerifyEvent event) { + // Assume we allow it + event.doit = true; + + String text = event.text; + char[] chars = text.toCharArray(); + + // Don't allow if text contains non-digit characters + for (int i = 0; i < chars.length; i++) { + if (!Character.isDigit(chars[i])) { + event.doit = false; + break; + } + } + } + }); + } + + private void createLineCountLabel(Composite composite) { + Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE); + lblScanLast.setBounds(0, 15, 80, 20); + } + + private void configureLayout() { + setLayout(new GridLayout(1, false)); + GridData layoutData = new GridData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + // layoutData.verticalIndent = 10; + setLayoutData(layoutData); + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.verticalIndent = 10; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; + } + + private void setupLogsTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, LOG_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.DATE, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.TIME, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.BRICK, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.SEVERITY, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.MESSAGE, SWT.LEFT, 100); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + private void setColumnProperties(Table table, LOG_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + private Date extractTimestamp(DateTime date, DateTime time) { + Calendar calendar = Calendar.getInstance(); + calendar.setLenient(false); + calendar.set(Calendar.DAY_OF_MONTH, date.getDay()); + // in Calendar class, month starts with zero i.e. Jan = 0 + calendar.set(Calendar.MONTH, date.getMonth()); + calendar.set(Calendar.YEAR, date.getYear()); + calendar.set(Calendar.HOUR_OF_DAY, time.getHours()); + calendar.set(Calendar.MINUTE, time.getMinutes()); + calendar.set(Calendar.SECOND, time.getSeconds()); + return calendar.getTime(); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeOptionsPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeOptionsPage.java new file mode 100644 index 00000000..57ecb615 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumeOptionsPage.java @@ -0,0 +1,360 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.apache.commons.lang.WordUtils; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnLayoutData; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.console.GlusterDataModelManager; +import com.gluster.storage.management.console.VolumeOptionsContentProvider; +import com.gluster.storage.management.console.VolumeOptionsTableLabelProvider; +import com.gluster.storage.management.console.utils.GUIHelper; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.VolumeOption; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +public class VolumeOptionsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + private Volume volume; + private DefaultClusterListener clusterListener; + private Text filterText; + private List defaultVolumeOptions = GlusterDataModelManager.getInstance() + .getVolumeOptionsDefaults(); + + public enum OPTIONS_TABLE_COLUMN_INDICES { + OPTION_KEY, OPTION_VALUE + }; + + private static final String[] OPTIONS_TABLE_COLUMN_NAMES = new String[] { "Option Key", "Option Value" }; + private Button addTopButton; + private Button addBottomButton; + private TableViewerColumn keyColumn; + private OptionKeyEditingSupport keyEditingSupport; + + public VolumeOptionsPage(final Composite parent, int style, Volume volume) { + super(parent, style); + + this.volume = volume; + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + addTopButton = createAddButton(); + filterText = guiHelper.createFilterText(toolkit, this); + + setupOptionsTableViewer(filterText); + + addBottomButton = createAddButton(); + + if (defaultVolumeOptions.size() == volume.getOptions().size()) { + setAddButtonsEnabled(false); + } + + tableViewer.setInput(volume.getOptions()); + + parent.layout(); // Important - this actually paints the table + registerListeners(parent); + } + + private void setAddButtonsEnabled(boolean enable) { + addTopButton.setEnabled(enable); + addBottomButton.setEnabled(enable); + } + + private Button createAddButton() { + return toolkit.createButton(this, "&Add", SWT.FLAT); + } + + private void registerListeners(final Composite parent) { + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + + clusterListener = new DefaultClusterListener() { + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + + switch (event.getEventType()) { + case VOLUME_OPTIONS_RESET: + if (!tableViewer.getControl().isDisposed()) { + //While reseting the options, clear the filter text before refreshing the tree + filterText.setText(""); + tableViewer.refresh(); + setAddButtonsEnabled(true); + } + break; + + case VOLUME_OPTION_SET: + String key = (String)event.getEventData(); + if (isNewOption(volume, key)) { + // option has been set successfully by the user. re-enable the add button and search filter + // textbox + setAddButtonsEnabled(true); + filterText.setEnabled(true); + } + + if (defaultVolumeOptions.size() == volume.getOptions().size()) { + setAddButtonsEnabled(false); + } + + tableViewer.refresh(); + break; + case VOLUME_CHANGED: + tableViewer.refresh(); + if(volume.getOptions().size() == defaultVolumeOptions.size()) { + setAddButtonsEnabled(false); + } else { + setAddButtonsEnabled(true); + } + default: + break; + } + } + + private boolean isNewOption(Volume volume, String optionKey) { + if (filterText.getText().length() > 0) { + // user has been filtering the contents. adding new option is allowed only when contents are NOT + // filtered. Thus it's impossible that this is a newly added option + return false; + } + + // if this is the last option in the volume options, it must be the new option + return optionKey.equals(volume.getOptions().getOptions().get(volume.getOptions().size() - 1).getKey()); + } + }; + + SelectionListener addButtonSelectionListener = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + // add an empty option to be filled up by user + volume.setOption("", ""); + + tableViewer.refresh(); + tableViewer.setSelection(new StructuredSelection(getEntry(""))); + keyColumn.getViewer().editElement(getEntry(""), 0); // edit newly created entry + + // disable the add button AND search filter textbox till user fills up the new option + setAddButtonsEnabled(false); + filterText.setEnabled(false); + } + + private VolumeOption getEntry(String key) { + for (VolumeOption entry : volume.getOptions().getOptions()) { + if (entry.getKey().equals(key)) { + return entry; + } + } + return null; + } + }; + addTopButton.addSelectionListener(addButtonSelectionListener); + addBottomButton.addSelectionListener(addButtonSelectionListener); + + // Make sure that add button is enabled only when search filter textbox is empty + filterText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + if (filterText.getText().length() > 0) { + setAddButtonsEnabled(false); + } else { + if (defaultVolumeOptions.size() == volume.getOptions().size()) { + setAddButtonsEnabled(false); + } else { + setAddButtonsEnabled(true); + } + } + } + }); + + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + + addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + + if (!(addTopButton.isEnabled() || addBottomButton.isEnabled())) { + // user has selected key, but not added value. Since this is not a valid entry, + // remove the last option (without value) from the volume + volume.getOptions().remove(keyEditingSupport.getEntryBeingAdded().getKey()); + } + + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + }); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupOptionsTable(Composite parent) { + Table table = tableViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + TableColumnLayout tableColumnLayout = createTableColumnLayout(); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY, SWT.CENTER, 100); + setColumnProperties(table, OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE, SWT.CENTER, 100); + } + + private TableColumnLayout createTableColumnLayout() { + TableColumnLayout tableColumnLayout = new TableColumnLayout(); + ColumnLayoutData defaultColumnLayoutData = new ColumnWeightData(100); + + tableColumnLayout.setColumnData(createKeyColumn(), defaultColumnLayoutData); + tableColumnLayout.setColumnData(createValueColumn(), defaultColumnLayoutData); + + return tableColumnLayout; + } + + private TableColumn createValueColumn() { + TableViewerColumn valueColumn = new TableViewerColumn(tableViewer, SWT.NONE); + valueColumn.getColumn() + .setText(OPTIONS_TABLE_COLUMN_NAMES[OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE.ordinal()]); + valueColumn.setLabelProvider(new ColumnLabelProvider() { + @Override + public String getText(Object element) { + return ((VolumeOption) element).getValue(); + } + }); + + // User can edit value of a volume option + valueColumn.setEditingSupport(new OptionValueEditingSupport(valueColumn.getViewer(), volume)); + + return valueColumn.getColumn(); + } + + private TableColumn createKeyColumn() { + keyColumn = new TableViewerColumn(tableViewer, SWT.NONE); + keyColumn.getColumn().setText(OPTIONS_TABLE_COLUMN_NAMES[OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal()]); + keyColumn.setLabelProvider(new ColumnLabelProvider() { + @Override + public String getText(Object element) { + return ((VolumeOption) element).getKey(); + } + + @Override + public String getToolTipText(Object element) { + String key = ((VolumeOption) element).getKey(); + if (key.isEmpty()) { + return "Click to select a volume option key"; + } + + VolumeOptionInfo optionInfo = GlusterDataModelManager.getInstance().getVolumeOptionInfo(key); + // Wrap the description before adding to tooltip so that long descriptions are displayed properly + return WordUtils.wrap(optionInfo.getDescription(), 60) + CoreConstants.NEWLINE + "Default value: " + + optionInfo.getDefaultValue(); + } + }); + + // Editing support required when adding new key + keyEditingSupport = new OptionKeyEditingSupport(keyColumn.getViewer(), volume); + keyColumn.setEditingSupport(keyEditingSupport); + + return keyColumn.getColumn(); + } + + private void createOptionsTableViewer(Composite parent) { + tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.SINGLE); + tableViewer.setLabelProvider(new VolumeOptionsTableLabelProvider()); + tableViewer.setContentProvider(new VolumeOptionsContentProvider()); + tableViewer.getTable().setLinesVisible(true); + + setupOptionsTable(parent); + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.horizontalSpan = 2; + tableViewerComposite.setLayoutData(layoutData); + + return tableViewerComposite; + } + + private void setupOptionsTableViewer(final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + createOptionsTableViewer(tableViewerComposite); + ColumnViewerToolTipSupport.enableFor(tableViewer); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + private void setColumnProperties(Table table, OPTIONS_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumesPage.java b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumesPage.java new file mode 100644 index 00000000..985c05dd --- /dev/null +++ b/src/com.gluster.storage.management.console/src/com/gluster/storage/management/console/views/pages/VolumesPage.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.console.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.console.EntityGroupContentProvider; +import com.gluster.storage.management.console.VolumeTableLabelProvider; +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Volume; + +public class VolumesPage extends AbstractTableViewerPage { + private List volumes; + + public enum VOLUME_TABLE_COLUMN_INDICES { + NAME, VOLUME_TYPE, NUM_OF_BRICKS, TRANSPORT_TYPE, VOLUME_STATUS + }; + + private static final String[] VOLUME_TABLE_COLUMN_NAMES = new String[] { "Name", "Volume Type", + "Number of" + CoreConstants.NEWLINE + "Bricks", "Transport Type", "Status" }; + + public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup volumes) { + super(site, parent, SWT.NONE, true, true, volumes); + this.volumes = volumes.getEntities(); + } + + @Override + protected String[] getColumnNames() { + return VOLUME_TABLE_COLUMN_NAMES; + } + + @Override + protected void setColumnProperties(Table table) { + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.NUM_OF_BRICKS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.TRANSPORT_TYPE, SWT.CENTER, 70); + } + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new VolumeTableLabelProvider(); + } + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider(); + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @Override + public void volumeCreated(Volume volume) { + tableViewer.add(volume); + parent.update(); + } + + @Override + public void volumeDeleted(Volume volume) { + tableViewer.remove(volume); + parent.update(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + tableViewer.update(volume, null); + parent.update(); + } + }; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, VOLUME_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + @Override + protected List getAllEntities() { + return volumes; + } +} diff --git a/src/com.gluster.storage.management.console/src/test.xml b/src/com.gluster.storage.management.console/src/test.xml new file mode 100644 index 00000000..12bbf745 --- /dev/null +++ b/src/com.gluster.storage.management.console/src/test.xml @@ -0,0 +1 @@ + -- cgit