From bf531d097bc99db08bda4d1a1dec541c57c7933c Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Mon, 28 Mar 2011 06:58:51 -0700 Subject: Preparing src for migration to github --- .../.classpath | 10 + src/com.gluster.storage.management.client/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../META-INF/MANIFEST.MF | 14 + .../build.properties | 8 + .../lib/jersey-1.5/jersey-client-1.5.jar | Bin 0 -> 128096 bytes .../lib/jersey-1.5/jersey-core-1.5.jar | Bin 0 -> 455665 bytes .../storage/management/client/AbstractClient.java | 159 +++ .../management/client/DiscoveredServersClient.java | 79 ++ .../management/client/GlusterDataModelManager.java | 344 ++++++ .../management/client/GlusterServersClient.java | 83 ++ .../storage/management/client/RESTClientTest.java | 42 + .../management/client/RunningTaskClient.java | 31 + .../storage/management/client/UsersClient.java | 97 ++ .../storage/management/client/VolumesClient.java | 90 ++ .../client/constants/ClientConstants.java | 32 + .../management/client/utils/ClientUtil.java | 20 + src/com.gluster.storage.management.core/.classpath | 9 + src/com.gluster.storage.management.core/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../META-INF/MANIFEST.MF | 12 + .../build.properties | 4 + .../management/core/utils/TestFileUtil.java | 84 ++ .../junit/core.junit.launch | 15 + .../junit/test/test.txt | 1 + .../management/core/constants/CoreConstants.java | 29 + .../management/core/constants/RESTConstants.java | 37 + .../core/exceptions/GlusterRuntimeException.java | 31 + .../management/core/model/AbstractResponse.java | 32 + .../storage/management/core/model/Cluster.java | 100 ++ .../management/core/model/ClusterListener.java | 43 + .../management/core/model/ConnectionDetails.java | 44 + .../core/model/DefaultClusterListener.java | 80 ++ .../storage/management/core/model/Disk.java | 107 ++ .../storage/management/core/model/Entity.java | 83 ++ .../storage/management/core/model/EntityGroup.java | 46 + .../storage/management/core/model/Event.java | 53 + .../storage/management/core/model/Filterable.java | 37 + .../management/core/model/GenericResponse.java | 56 + .../management/core/model/GlusterDataModel.java | 42 + .../management/core/model/GlusterDummyModel.java | 283 +++++ .../management/core/model/GlusterServer.java | 106 ++ .../core/model/GlusterServerListResponse.java | 71 ++ .../core/model/GlusterServerResponse.java | 32 + .../storage/management/core/model/LogMessage.java | 75 ++ .../management/core/model/NetworkInterface.java | 73 ++ .../storage/management/core/model/Response.java | 37 + .../storage/management/core/model/RunningTask.java | 75 ++ .../core/model/RunningTaskListResponse.java | 43 + .../management/core/model/RunningTaskStatus.java | 41 + .../storage/management/core/model/Server.java | 174 +++ .../management/core/model/ServerListResponse.java | 65 ++ .../storage/management/core/model/Status.java | 77 ++ .../management/core/model/StringListResponse.java | 45 + .../storage/management/core/model/User.java | 40 + .../storage/management/core/model/Volume.java | 252 +++++ .../management/core/model/VolumeOptionInfo.java | 66 ++ .../storage/management/core/utils/DateUtil.java | 35 + .../storage/management/core/utils/FileUtil.java | 45 + .../storage/management/core/utils/GlusterUtil.java | 218 ++++ .../gluster/storage/management/core/utils/MD5.java | 504 +++++++++ .../storage/management/core/utils/MD5Crypt.java | 339 ++++++ .../storage/management/core/utils/NumberUtil.java | 30 + .../management/core/utils/ProcessResult.java | 63 ++ .../storage/management/core/utils/ProcessUtil.java | 97 ++ .../storage/management/core/utils/StringUtil.java | 28 + .../.project | 17 + .../buckminster.cspex | 41 + .../build.properties | 2 + .../build/gluster.keystore | Bin 0 -> 2738 bytes .../build/glustermc.ant | 30 + .../feature.xml | 229 ++++ .../rootfiles/gluster-management-console.jnlp | 38 + .../rootfiles/index.html | 8 + .../rootfiles/splash.bmp | Bin 0 -> 377610 bytes .../.project | 17 + .../build.properties | 1 + .../feature.xml | 775 +++++++++++++ src/com.gluster.storage.management.gui/.classpath | 7 + src/com.gluster.storage.management.gui/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../META-INF/MANIFEST.MF | 27 + .../build.properties | 15 + .../icons/arrow-down.png | Bin 0 -> 703 bytes .../icons/arrow-up.png | Bin 0 -> 712 bytes .../icons/cluster.png | Bin 0 -> 622 bytes .../icons/disk-migrate.png | Bin 0 -> 781 bytes .../icons/disk-uninitialized.png | Bin 0 -> 708 bytes .../icons/disk.png | Bin 0 -> 620 bytes .../icons/disks.png | Bin 0 -> 691 bytes .../icons/folder.png | Bin 0 -> 537 bytes .../icons/gluster_icon.png | Bin 0 -> 3131 bytes .../icons/group.png | Bin 0 -> 753 bytes .../icons/gsn.png | Bin 0 -> 923 bytes .../icons/logs.png | Bin 0 -> 900 bytes .../icons/mail.ico | Bin 0 -> 26694 bytes .../icons/minus-white.png | Bin 0 -> 682 bytes .../icons/network-interface.png | Bin 0 -> 577 bytes .../icons/network-interfaces.png | Bin 0 -> 413 bytes .../icons/network-interfaces1.png | Bin 0 -> 563 bytes .../icons/plus-white.png | Bin 0 -> 703 bytes .../icons/preferences.png | Bin 0 -> 916 bytes .../icons/progress-bar.png | Bin 0 -> 261 bytes .../icons/question.png | Bin 0 -> 766 bytes .../icons/sample.gif | Bin 0 -> 983 bytes .../icons/sample.icns | Bin 0 -> 35301 bytes .../icons/sample2.gif | Bin 0 -> 318 bytes .../icons/sample3.gif | Bin 0 -> 173 bytes .../icons/search.png | Bin 0 -> 736 bytes .../icons/server-add-big.png | Bin 0 -> 2057 bytes .../icons/server-add.png | Bin 0 -> 781 bytes .../icons/server-remove.png | Bin 0 -> 775 bytes .../icons/server.png | Bin 0 -> 667 bytes .../icons/servers.png | Bin 0 -> 654 bytes .../icons/star-small.png | Bin 0 -> 447 bytes .../icons/status-offline-circle.png | Bin 0 -> 729 bytes .../icons/status-offline-small.png | Bin 0 -> 322 bytes .../icons/status-offline.png | Bin 0 -> 544 bytes .../icons/status-online-circle.png | Bin 0 -> 724 bytes .../icons/status-online-small.png | Bin 0 -> 361 bytes .../icons/status-online.png | Bin 0 -> 634 bytes .../icons/stop.png | Bin 0 -> 700 bytes .../icons/ui-check-box-mix.png | Bin 0 -> 414 bytes .../icons/ui-check-box-uncheck.png | Bin 0 -> 355 bytes .../icons/ui-check-box.png | Bin 0 -> 435 bytes .../icons/volume-create-big.png | Bin 0 -> 2442 bytes .../icons/volume-create.png | Bin 0 -> 899 bytes .../icons/volume-delete.png | Bin 0 -> 891 bytes .../icons/volume-edit.png | Bin 0 -> 731 bytes .../icons/volume-rebalance.png | Bin 0 -> 753 bytes .../icons/volume-start.png | Bin 0 -> 898 bytes .../icons/volume-stop-1.png | Bin 0 -> 700 bytes .../icons/volume-stop.png | Bin 0 -> 752 bytes .../icons/volume.png | Bin 0 -> 633 bytes .../icons/volume1.png | Bin 0 -> 436 bytes .../icons/volumes.png | Bin 0 -> 504 bytes .../icons/volumes1.png | Bin 0 -> 755 bytes .../icons/volumes2.png | Bin 0 -> 825 bytes .../icons/volumes3.png | Bin 0 -> 613 bytes .../icons/world.png | Bin 0 -> 923 bytes .../images/gauge.png | Bin 0 -> 45242 bytes .../images/gauge_small.png | Bin 0 -> 13875 bytes .../images/progress_image_empty.png | Bin 0 -> 185 bytes .../images/progress_image_filled_danger.png | Bin 0 -> 185 bytes .../images/progress_image_filled_safe.png | Bin 0 -> 201 bytes .../images/progress_image_left.png | Bin 0 -> 185 bytes .../images/progress_image_right.png | Bin 0 -> 185 bytes src/com.gluster.storage.management.gui/plugin.xml | 1175 ++++++++++++++++++++ .../preferences.ini | 1 + src/com.gluster.storage.management.gui/splash.bmp | Bin 0 -> 377610 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 .../gluster/storage/management/gui/Activator.java | 83 ++ .../storage/management/gui/Application.java | 116 ++ .../gui/ApplicationActionBarAdvisor.java | 94 ++ .../gui/ApplicationWorkbenchAdvisor.java | 45 + .../gui/ApplicationWorkbenchWindowAdvisor.java | 60 + .../management/gui/DiskTableLabelProvider.java | 88 ++ .../management/gui/EntityGroupContentProvider.java | 45 + .../gui/GlusterServerTableLabelProvider.java | 75 ++ .../storage/management/gui/ICommandIds.java | 33 + .../storage/management/gui/IEntityListener.java | 37 + .../gluster/storage/management/gui/IImageKeys.java | 62 ++ .../gui/NetworkInterfaceTableLabelProvider.java | 40 + .../storage/management/gui/Perspective.java | 39 + .../gui/ServerDiskTableLabelProvider.java | 90 ++ .../management/gui/ServerTableLabelProvider.java | 48 + .../management/gui/TableLabelProviderAdapter.java | 58 + .../gui/VolumeLogTableLabelProvider.java | 48 + .../gui/VolumeOptionsTableLabelProvider.java | 42 + .../management/gui/VolumeTableLabelProvider.java | 82 ++ .../gui/actions/AbstractActionDelegate.java | 59 + .../management/gui/actions/AddServerAction.java | 70 ++ .../management/gui/actions/CreateVolumeAction.java | 63 ++ .../management/gui/actions/DeleteVolumeAction.java | 33 + .../management/gui/actions/EditVolumeAction.java | 33 + .../management/gui/actions/IActionSetIDs.java | 33 + .../management/gui/actions/MigrateDiskAction.java | 67 ++ .../gui/actions/MigrateVolumeAction.java | 33 + .../management/gui/actions/PreferencesAction.java | 36 + .../gui/actions/RebalanceVolumeAction.java | 33 + .../management/gui/actions/RemoveServerAction.java | 36 + .../management/gui/actions/StartVolumeAction.java | 85 ++ .../management/gui/actions/StopVolumeAction.java | 81 ++ .../gui/actions/TestPopupMenuAction.java | 62 ++ .../gui/dialogs/CreateVolumeDisksPage.java | 306 +++++ .../management/gui/dialogs/CreateVolumePage1.java | 288 +++++ .../management/gui/dialogs/CreateVolumeWizard.java | 72 ++ .../management/gui/dialogs/MigrateDiskPage1.java | 203 ++++ .../management/gui/dialogs/MigrateDiskWizard.java | 48 + .../management/gui/dialogs/SelectDisksDialog.java | 113 ++ .../management/gui/jobs/InitializeDiskJob.java | 84 ++ .../storage/management/gui/login/LoginDialog.java | 200 ++++ .../gui/preferences/ClusterPreferencePage.java | 83 ++ .../gui/preferences/ConsolePreferencePage.java | 83 ++ .../gui/preferences/GlusterPreferencePage.java | 83 ++ .../gui/preferences/PreferenceConstants.java | 34 + .../gui/preferences/PreferenceInitializer.java | 44 + .../gui/toolbar/GlusterToolbarManager.java | 102 ++ .../management/gui/toolbar/ToolbarManager.java | 35 + .../management/gui/utils/EntityViewerFilter.java | 78 ++ .../storage/management/gui/utils/GUIHelper.java | 363 ++++++ .../storage/management/gui/utils/ImageUtil.java | 51 + .../storage/management/gui/utils/LRUCache.java | 55 + .../gui/validators/StringRequiredValidator.java | 59 + .../management/gui/views/ClusterSummaryView.java | 155 +++ .../storage/management/gui/views/DetailsView.java | 110 ++ .../management/gui/views/DiscoveredServerView.java | 90 ++ .../gui/views/DiscoveredServersView.java | 109 ++ .../storage/management/gui/views/DisksView.java | 44 + .../gui/views/GlusterServerDisksView.java | 57 + .../gui/views/GlusterServerLogsView.java | 59 + .../gui/views/GlusterServerSummaryView.java | 246 ++++ .../gui/views/GlusterServersSummaryView.java | 123 ++ .../management/gui/views/GlusterServersView.java | 77 ++ .../management/gui/views/GlusterViewsManager.java | 130 +++ .../management/gui/views/NavigationView.java | 139 +++ .../storage/management/gui/views/ViewsManager.java | 38 + .../management/gui/views/VolumeDisksView.java | 39 + .../management/gui/views/VolumeLogsView.java | 35 + .../management/gui/views/VolumeOptionsView.java | 36 + .../management/gui/views/VolumeSummaryView.java | 270 +++++ .../storage/management/gui/views/VolumeView.java | 90 ++ .../management/gui/views/VolumesSummaryView.java | 145 +++ .../storage/management/gui/views/VolumesView.java | 108 ++ .../gui/views/details/AbstractDisksPage.java | 315 ++++++ .../management/gui/views/details/DisksPage.java | 69 ++ .../gui/views/details/GlusterServersPage.java | 164 +++ .../gui/views/details/ServerDisksPage.java | 68 ++ .../gui/views/details/ServerLogsPage.java | 179 +++ .../management/gui/views/details/TabCreator.java | 49 + .../gui/views/details/TabCreatorFactory.java | 32 + .../gui/views/details/TabCreatorFactoryImpl.java | 72 ++ .../gui/views/details/VolumeLogsPage.java | 196 ++++ .../gui/views/details/VolumeOptionsPage.java | 152 +++ .../details/tabcreators/ClusterTabCreator.java | 146 +++ .../EntityGroupGlusterServerTabCreator.java | 136 +++ .../tabcreators/EntityGroupServerTabCreator.java | 60 + .../tabcreators/EntityGroupVolumeTabCreator.java | 117 ++ .../tabcreators/GlusterServerTabCreator.java | 261 +++++ .../tabcreators/PieChartViewerComposite.java | 254 +++++ .../details/tabcreators/ServerTabCreator.java | 73 ++ .../details/tabcreators/VolumeTabCreator.java | 269 +++++ .../gui/views/navigator/ClusterAdapterFactory.java | 101 ++ .../navigator/NavigationTreeLabelDecorator.java | 87 ++ .../management/gui/views/pages/ServersPage.java | 177 +++ .../management/gui/views/pages/VolumesPage.java | 163 +++ src/com.gluster.storage.management.releng/.project | 17 + .../build.properties | 1 + .../com.gluster.storage.management.client.cquery | 4 + .../com.gluster.storage.management.core.cquery | 4 + ....storage.management.gui.feature.webstart.cquery | 4 + .../com.gluster.storage.management.server.cquery | 4 + .../feature.xml | 20 + .../gluster-management-console.target | 12 + .../glustermc.rmap | 12 + .../glustermc_build.properties | 10 + .../.project | 17 + .../.pydevproject | 10 + .../src/common/Commands.py | 78 ++ .../src/common/Common.py | 34 + .../src/common/Globals.py | 119 ++ .../src/common/NetworkUtils.py | 422 +++++++ .../src/common/Protocol.py | 438 ++++++++ .../src/common/Utils.py | 704 ++++++++++++ ...m-config-network-tui-1.3.99.18-1.el5.noarch.rpm | Bin 0 -> 1915520 bytes .../src/nodes/Agent.py | 118 ++ .../src/nodes/GetServerNetworkConfig.py | 96 ++ .../src/nodes/ServerAgent.py | 179 +++ .../src/nodes/ServerRequestHandler.py | 76 ++ .../src/nodes/ServerUtils.py | 308 +++++ .../src/nodes/Socket.py | 47 + .../src/nodes/XmlHandler.py | 346 ++++++ .../src/nodes/multicast_response.py | 45 + .../src/server/RemoteExecute.py | 287 +++++ .../src/server/RequestHandler.py | 58 + .../src/server/TransportAgent.py | 26 + .../src/server/transport.py | 94 ++ .../src/server/vmware-discover-servers.py | 83 ++ .../.classpath | 14 + src/com.gluster.storage.management.server/.project | 42 + .../.pydevproject | 7 + .../.settings/.jsdtscope | 12 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../org.eclipse.ltk.core.refactoring.prefs | 3 + .../.settings/org.eclipse.wst.common.component | 9 + .../org.eclipse.wst.common.project.facet.core.xml | 20 + .../org.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + .../org.eclipse.wst.ws.service.policy.prefs | 3 + .../WebContent/META-INF/MANIFEST.MF | 3 + .../WebContent/WEB-INF/lib/aopalliance-1.0.jar | Bin 0 -> 4467 bytes .../WebContent/WEB-INF/lib/asm-3.1.jar | Bin 0 -> 43033 bytes .../WEB-INF/lib/commons-logging-1.1.1.jar | Bin 0 -> 60841 bytes .../WebContent/WEB-INF/lib/derby.jar | Bin 0 -> 2512189 bytes .../WebContent/WEB-INF/lib/derbytools.jar | Bin 0 -> 165188 bytes .../WEB-INF/lib/jackson-core-asl-1.5.5.jar | Bin 0 -> 171958 bytes .../WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar | Bin 0 -> 17065 bytes .../WEB-INF/lib/jackson-mapper-asl-1.5.5.jar | Bin 0 -> 485699 bytes .../WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar | Bin 0 -> 24745 bytes .../WebContent/WEB-INF/lib/jersey-client-1.5.jar | Bin 0 -> 128096 bytes .../WebContent/WEB-INF/lib/jersey-core-1.5.jar | Bin 0 -> 455665 bytes .../WebContent/WEB-INF/lib/jersey-json-1.5.jar | Bin 0 -> 144810 bytes .../WebContent/WEB-INF/lib/jersey-server-1.5.jar | Bin 0 -> 681117 bytes .../WebContent/WEB-INF/lib/jersey-spring-1.5.jar | Bin 0 -> 17079 bytes .../WebContent/WEB-INF/lib/jettison-1.1.jar | Bin 0 -> 67758 bytes .../WebContent/WEB-INF/lib/jnlp-servlet.jar | Bin 0 -> 61712 bytes .../WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar | Bin 0 -> 46367 bytes .../org.eclipse.equinox.common_3.6.0.v20100503.jar | Bin 0 -> 101958 bytes .../lib/org.springframework.aop-3.0.5.RELEASE.jar | Bin 0 -> 321190 bytes .../lib/org.springframework.asm-3.0.5.RELEASE.jar | Bin 0 -> 53082 bytes .../org.springframework.aspects-3.0.5.RELEASE.jar | Bin 0 -> 35548 bytes .../org.springframework.beans-3.0.5.RELEASE.jar | Bin 0 -> 555410 bytes .../org.springframework.context-3.0.5.RELEASE.jar | Bin 0 -> 668861 bytes ...ringframework.context.support-3.0.5.RELEASE.jar | Bin 0 -> 100870 bytes .../lib/org.springframework.core-3.0.5.RELEASE.jar | Bin 0 -> 382442 bytes ...rg.springframework.expression-3.0.5.RELEASE.jar | Bin 0 -> 169752 bytes ...rg.springframework.instrument-3.0.5.RELEASE.jar | Bin 0 -> 1810 bytes ...ngframework.instrument.tomcat-3.0.5.RELEASE.jar | Bin 0 -> 5728 bytes .../lib/org.springframework.jdbc-3.0.5.RELEASE.jar | Bin 0 -> 385712 bytes .../lib/org.springframework.jms-3.0.5.RELEASE.jar | Bin 0 -> 185312 bytes .../lib/org.springframework.orm-3.0.5.RELEASE.jar | Bin 0 -> 334327 bytes .../lib/org.springframework.oxm-3.0.5.RELEASE.jar | Bin 0 -> 61379 bytes ...ringframework.spring-library-3.0.5.RELEASE.libd | 21 + .../lib/org.springframework.test-3.0.5.RELEASE.jar | Bin 0 -> 205278 bytes ...g.springframework.transaction-3.0.5.RELEASE.jar | Bin 0 -> 231922 bytes .../lib/org.springframework.web-3.0.5.RELEASE.jar | Bin 0 -> 395587 bytes ...g.springframework.web.portlet-3.0.5.RELEASE.jar | Bin 0 -> 175412 bytes ...g.springframework.web.servlet-3.0.5.RELEASE.jar | Bin 0 -> 418977 bytes ...rg.springframework.web.struts-3.0.5.RELEASE.jar | Bin 0 -> 31404 bytes ...com.gluster.storage.management.client_1.0.0.jar | Bin 0 -> 513103 bytes .../com.gluster.storage.management.core_1.0.0.jar | Bin 0 -> 50608 bytes .../WebContent/WEB-INF/lib/servlet-api.jar | Bin 0 -> 176386 bytes .../lib/spring-security-config-3.0.5.RELEASE.jar | Bin 0 -> 185716 bytes .../lib/spring-security-core-3.0.5.RELEASE.jar | Bin 0 -> 311038 bytes .../lib/spring-security-web-3.0.5.RELEASE.jar | Bin 0 -> 242833 bytes .../WebContent/WEB-INF/web.xml | 72 ++ .../WebContent/scripts/Common.py | 34 + .../WebContent/scripts/Globals.py | 3 + .../WebContent/scripts/vmware-discover-servers.py | 83 ++ .../buckminster.cspex | 37 + .../build/glusterserver.ant | 64 ++ .../server/constants/VolumeOptionsDefaults.java | 120 ++ .../management/server/data/GlusterDataSource.java | 48 + .../server/resources/AbstractServersResource.java | 79 ++ .../resources/DiscoveredServersResource.java | 89 ++ .../server/resources/GlusterServersResource.java | 115 ++ .../storage/management/server/resources/Hello.java | 50 + .../server/resources/RunningTaskResource.java | 128 +++ .../server/resources/ServerResource.java | 72 ++ .../management/server/resources/UsersResource.java | 91 ++ .../server/resources/VolumesResource.java | 93 ++ .../runningtasks/managers/FormatDiskManager.java | 71 ++ .../runningtasks/managers/MigrateDiskManager.java | 50 + .../runningtasks/managers/RunningTaskManager.java | 44 + .../managers/VolumeRebalanceManager.java | 50 + .../server/security/GlusterUserDetailsService.java | 31 + .../management/server/security/UserAuthDao.java | 42 + .../management/server/tasks/InitServerTask.java | 99 ++ .../server/tasks/ServerDiscoveryTask.java | 75 ++ .../management/server/utils/ServerUtil.java | 58 + .../src/data/scripts/security-schema.sql | 26 + .../src/data/scripts/users-authorities-groups.sql | 21 + .../src/spring/gluster-server-base.xml | 50 + .../src/spring/gluster-server-security.xml | 46 + src/com.sun.jersey/.project | 28 + 367 files changed, 22578 insertions(+) create mode 100644 src/com.gluster.storage.management.client/.classpath create mode 100644 src/com.gluster.storage.management.client/.project create mode 100644 src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.client/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.client/build.properties create mode 100644 src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar create mode 100644 src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java create mode 100644 src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java create mode 100644 src/com.gluster.storage.management.core/.classpath create mode 100644 src/com.gluster.storage.management.core/.project create mode 100644 src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.core/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.core/build.properties create mode 100644 src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java create mode 100644 src/com.gluster.storage.management.core/junit/core.junit.launch create mode 100644 src/com.gluster.storage.management.core/junit/test/test.txt create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java create mode 100644 src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/.project create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/build.properties create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/feature.xml create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html create mode 100644 src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp create mode 100644 src/com.gluster.storage.management.gui.feature/.project create mode 100644 src/com.gluster.storage.management.gui.feature/build.properties create mode 100644 src/com.gluster.storage.management.gui.feature/feature.xml create mode 100644 src/com.gluster.storage.management.gui/.classpath create mode 100644 src/com.gluster.storage.management.gui/.project create mode 100644 src/com.gluster.storage.management.gui/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.gui/build.properties create mode 100644 src/com.gluster.storage.management.gui/icons/arrow-down.png create mode 100644 src/com.gluster.storage.management.gui/icons/arrow-up.png create mode 100644 src/com.gluster.storage.management.gui/icons/cluster.png create mode 100644 src/com.gluster.storage.management.gui/icons/disk-migrate.png create mode 100644 src/com.gluster.storage.management.gui/icons/disk-uninitialized.png create mode 100644 src/com.gluster.storage.management.gui/icons/disk.png create mode 100644 src/com.gluster.storage.management.gui/icons/disks.png create mode 100644 src/com.gluster.storage.management.gui/icons/folder.png create mode 100644 src/com.gluster.storage.management.gui/icons/gluster_icon.png create mode 100644 src/com.gluster.storage.management.gui/icons/group.png create mode 100644 src/com.gluster.storage.management.gui/icons/gsn.png create mode 100644 src/com.gluster.storage.management.gui/icons/logs.png create mode 100644 src/com.gluster.storage.management.gui/icons/mail.ico create mode 100644 src/com.gluster.storage.management.gui/icons/minus-white.png create mode 100644 src/com.gluster.storage.management.gui/icons/network-interface.png create mode 100644 src/com.gluster.storage.management.gui/icons/network-interfaces.png create mode 100644 src/com.gluster.storage.management.gui/icons/network-interfaces1.png create mode 100644 src/com.gluster.storage.management.gui/icons/plus-white.png create mode 100644 src/com.gluster.storage.management.gui/icons/preferences.png create mode 100644 src/com.gluster.storage.management.gui/icons/progress-bar.png create mode 100644 src/com.gluster.storage.management.gui/icons/question.png create mode 100644 src/com.gluster.storage.management.gui/icons/sample.gif create mode 100644 src/com.gluster.storage.management.gui/icons/sample.icns create mode 100644 src/com.gluster.storage.management.gui/icons/sample2.gif create mode 100644 src/com.gluster.storage.management.gui/icons/sample3.gif create mode 100644 src/com.gluster.storage.management.gui/icons/search.png create mode 100644 src/com.gluster.storage.management.gui/icons/server-add-big.png create mode 100644 src/com.gluster.storage.management.gui/icons/server-add.png create mode 100644 src/com.gluster.storage.management.gui/icons/server-remove.png create mode 100644 src/com.gluster.storage.management.gui/icons/server.png create mode 100644 src/com.gluster.storage.management.gui/icons/servers.png create mode 100644 src/com.gluster.storage.management.gui/icons/star-small.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-offline-circle.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-offline-small.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-offline.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-online-circle.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-online-small.png create mode 100644 src/com.gluster.storage.management.gui/icons/status-online.png create mode 100644 src/com.gluster.storage.management.gui/icons/stop.png create mode 100644 src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png create mode 100644 src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png create mode 100644 src/com.gluster.storage.management.gui/icons/ui-check-box.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-create-big.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-create.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-delete.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-edit.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-rebalance.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-start.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-stop-1.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume-stop.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume.png create mode 100644 src/com.gluster.storage.management.gui/icons/volume1.png create mode 100644 src/com.gluster.storage.management.gui/icons/volumes.png create mode 100644 src/com.gluster.storage.management.gui/icons/volumes1.png create mode 100644 src/com.gluster.storage.management.gui/icons/volumes2.png create mode 100644 src/com.gluster.storage.management.gui/icons/volumes3.png create mode 100644 src/com.gluster.storage.management.gui/icons/world.png create mode 100644 src/com.gluster.storage.management.gui/images/gauge.png create mode 100644 src/com.gluster.storage.management.gui/images/gauge_small.png create mode 100644 src/com.gluster.storage.management.gui/images/progress_image_empty.png create mode 100644 src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png create mode 100644 src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png create mode 100644 src/com.gluster.storage.management.gui/images/progress_image_left.png create mode 100644 src/com.gluster.storage.management.gui/images/progress_image_right.png create mode 100644 src/com.gluster.storage.management.gui/plugin.xml create mode 100644 src/com.gluster.storage.management.gui/preferences.ini create mode 100644 src/com.gluster.storage.management.gui/splash.bmp create mode 100644 src/com.gluster.storage.management.gui/splash/gluster_about.jpg create mode 100644 src/com.gluster.storage.management.gui/splash/splash-dialog.bmp create mode 100644 src/com.gluster.storage.management.gui/splash/splash-dialog.png create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java create mode 100644 src/com.gluster.storage.management.releng/.project create mode 100644 src/com.gluster.storage.management.releng/build.properties create mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery create mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery create mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery create mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery create mode 100644 src/com.gluster.storage.management.releng/feature.xml create mode 100644 src/com.gluster.storage.management.releng/gluster-management-console.target create mode 100644 src/com.gluster.storage.management.releng/glustermc.rmap create mode 100644 src/com.gluster.storage.management.releng/glustermc_build.properties create mode 100644 src/com.gluster.storage.management.server.scripts/.project create mode 100644 src/com.gluster.storage.management.server.scripts/.pydevproject create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/Commands.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/Common.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/Globals.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/Protocol.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/Utils.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py create mode 100755 src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py create mode 100644 src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py create mode 100755 src/com.gluster.storage.management.server.scripts/src/server/transport.py create mode 100755 src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py create mode 100644 src/com.gluster.storage.management.server/.classpath create mode 100644 src/com.gluster.storage.management.server/.project create mode 100644 src/com.gluster.storage.management.server/.pydevproject create mode 100644 src/com.gluster.storage.management.server/.settings/.jsdtscope create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name create mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs create mode 100644 src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml create mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/Common.py create mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/Globals.py create mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py create mode 100644 src/com.gluster.storage.management.server/buckminster.cspex create mode 100644 src/com.gluster.storage.management.server/build/glusterserver.ant create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java create mode 100755 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java create mode 100644 src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql create mode 100644 src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql create mode 100644 src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml create mode 100644 src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml create mode 100644 src/com.sun.jersey/.project (limited to 'src') diff --git a/src/com.gluster.storage.management.client/.classpath b/src/com.gluster.storage.management.client/.classpath new file mode 100644 index 00000000..b8f71a37 --- /dev/null +++ b/src/com.gluster.storage.management.client/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/com.gluster.storage.management.client/.project b/src/com.gluster.storage.management.client/.project new file mode 100644 index 00000000..647c8a91 --- /dev/null +++ b/src/com.gluster.storage.management.client/.project @@ -0,0 +1,28 @@ + + + com.gluster.storage.management.client + + + + + + 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.client/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f8b5cc38 --- /dev/null +++ b/src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 29 15:47:13 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.client/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.client/META-INF/MANIFEST.MF new file mode 100644 index 00000000..43ae7c3e --- /dev/null +++ b/src/com.gluster.storage.management.client/META-INF/MANIFEST.MF @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gluster Storage Platform Client +Bundle-SymbolicName: com.gluster.storage.management.client +Bundle-Version: 1.0.0 +Bundle-Vendor: GLUSTER +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: com.gluster.storage.management.core;bundle-version="1.0.0", + org.eclipse.equinox.common;bundle-version="3.6.0" +Export-Package: com.gluster.storage.management.client, + com.gluster.storage.management.client.constants +Bundle-ClassPath: ., + lib/jersey-1.5/jersey-client-1.5.jar, + lib/jersey-1.5/jersey-core-1.5.jar diff --git a/src/com.gluster.storage.management.client/build.properties b/src/com.gluster.storage.management.client/build.properties new file mode 100644 index 00000000..271ce382 --- /dev/null +++ b/src/com.gluster.storage.management.client/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = .,\ + META-INF/,\ + lib/jersey-1.5/jersey-client-1.5.jar,\ + lib/jersey-1.5/jersey-core-1.5.jar +src.includes = lib/jersey-1.4/jersey-client-1.4.jar,\ + lib/jersey-1.4/jersey-core-1.4.jar diff --git a/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar new file mode 100644 index 00000000..62f790fa Binary files /dev/null and b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar differ diff --git a/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar new file mode 100644 index 00000000..92b38466 Binary files /dev/null and b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar differ diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java new file mode 100644 index 00000000..12fbd354 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java @@ -0,0 +1,159 @@ +package com.gluster.storage.management.client; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + +import com.gluster.storage.management.client.utils.ClientUtil; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.representation.Form; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public abstract class AbstractClient { + private static final String HTTP_HEADER_AUTH = "Authorization"; + protected static final MultivaluedMap NO_PARAMS = new MultivaluedMapImpl(); + + protected WebResource resource; + private String securityToken; + private String authHeader; + + public AbstractClient() { + URI baseURI = new ClientUtil().getServerBaseURI(); + resource = Client.create(new DefaultClientConfig()).resource(baseURI).path(getResourceName()); + } + + public AbstractClient(String securityToken) { + this(); + setSecurityToken(securityToken); + } + + /** + * Fetches the given resource by dispatching a GET request + * + * @param res + * Resource to be fetched + * @param queryParams + * Query parameters to be sent for the GET request + * @param responseClass + * Expected class of the response + * @return Object of responseClass received as a result of the GET request + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private Object fetchResource(WebResource res, MultivaluedMap queryParams, Class responseClass) { + return res.queryParams(queryParams).header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.TEXT_XML) + .get(responseClass); + } + + /** + * Fetches the default resource (the one returned by {@link AbstractClient#getResourceName()}) by dispatching a GET + * request on the resource + * + * @param queryParams + * Query parameters to be sent for the GET request + * @param responseClass + * Expected class of the response + * @return Object of responseClass received as a result of the GET request + */ + @SuppressWarnings("rawtypes") + protected Object fetchResource(MultivaluedMap queryParams, Class responseClass) { + return fetchResource(resource, queryParams, responseClass); + } + + /** + * Fetches the default resource (the one returned by {@link AbstractClient#getResourceName()}) by dispatching a GET + * request on the resource + * + * @param responseClass + * Expected class of the response + * @return Object of responseClass received as a result of the GET request + */ + @SuppressWarnings("rawtypes") + protected Object fetchResource(Class responseClass) { + Object response = fetchResource(resource, NO_PARAMS, responseClass); + return response; + } + + /** + * Fetches the resource whose name is arrived at by appending the "subResourceName" parameter to the default + * resource (the one returned by {@link AbstractClient#getResourceName()}) + * + * @param subResourceName + * Name of the sub-resource + * @param responseClass + * Expected class of the response + * @return Object of responseClass received as a result of the GET request on the sub-resource + */ + @SuppressWarnings("rawtypes") + protected Object fetchSubResource(String subResourceName, Class responseClass) { + return fetchResource(resource.path(subResourceName), NO_PARAMS, responseClass); + } + + /** + * Submits given Form using POST method to the resource and returns the object received as response + * @param responseClass Class of the object expected as response + * @param form Form to be submitted + * @return Object of given class received as response + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Object postRequest(Class responseClass, Form form) { + return resource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).header("Authorization", authHeader) + .accept(MediaType.TEXT_XML).post(responseClass, form); + } + + /** + * Submits given Form using POST method to the given sub-resource and returns the object received as response + * @param subResourceName Name of the sub-resource to which the request is to be posted + * @param responseClass Class of the object expected as response + * @param form Form to be submitted + * @return Object of given class received as response + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Object postRequest(String subResourceName, Class responseClass, Form form) { + return resource.path(subResourceName).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE) + .header("Authorization", authHeader).accept(MediaType.TEXT_XML).post(responseClass, form); + } + + /** + * Submits given Form using PUT method to the given sub-resource and returns the object received as response + * @param subResourceName Name of the sub-resource to which the request is to be posted + * @param responseClass Class of the object expected as response + * @param form Form to be submitted + * @return Object of given class received as response + */ + protected Object putRequest(String subResourceName, Class responseClass, Form form) { + return resource.path(subResourceName).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE) + .header("Authorization", authHeader).accept(MediaType.TEXT_XML).put(responseClass, form); + } + + /** + * Submits given object to the resource and returns the object received as response + * @param responseClass Class of the object expected as response + * @param requestObject the Object to be submitted + * @return Object of given class received as response + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Object postObject(Class responseClass, Object requestObject) { + return resource.type(MediaType.TEXT_XML).header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.TEXT_XML) + .post(responseClass, requestObject); + } + + public abstract String getResourceName(); + + /** + * @return the securityToken + */ + protected String getSecurityToken() { + return securityToken; + } + + /** + * @param securityToken the securityToken to set + */ + protected void setSecurityToken(String securityToken) { + this.securityToken = securityToken; + authHeader = "Basic " + securityToken; + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java new file mode 100644 index 00000000..0cc18037 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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.client; + +import java.util.List; + +import javax.ws.rs.core.MultivaluedMap; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerListResponse; +import com.gluster.storage.management.core.model.StringListResponse; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class DiscoveredServersClient extends AbstractClient { + private static final String RESOURCE_NAME = "discoveredservers"; + + public DiscoveredServersClient(String serverName, String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + private Object getDiscoveredServers(Boolean getDetails, Class responseClass) { + MultivaluedMap queryParams = new MultivaluedMapImpl(); + queryParams.putSingle("details", getDetails.toString()); + + return ((Response) fetchResource(queryParams, responseClass)).getData(); + } + + public List getDiscoveredServerNames() { + return (List) getDiscoveredServers(Boolean.FALSE, StringListResponse.class); + } + + public List getDiscoveredServerDetails() { + return (List) getDiscoveredServers(Boolean.TRUE, ServerListResponse.class); + } + + @SuppressWarnings("unchecked") + public Server getServer(String serverName) { + GenericResponse response = (GenericResponse) fetchSubResource(serverName, GenericResponse.class); + return response.getData(); + } + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + DiscoveredServersClient serverResource = new DiscoveredServersClient("localhost", + usersClient.getSecurityToken()); + List discoveredServerNames = serverResource.getDiscoveredServerNames(); + System.out.println(discoveredServerNames); + List discoveredServers = serverResource.getDiscoveredServerDetails(); + System.out.println(discoveredServers); + + // Server serverDetails = ServerResource.getServer("localhost"); + // System.out.println(serverDetails.getName()); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java new file mode 100644 index 00000000..de0112db --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -0,0 +1,344 @@ +/******************************************************************************* + * 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.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +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.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.LogMessage; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; +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; + +public class GlusterDataModelManager { + // private Server discoveredServer1, discoveredServer2, discoveredServer3, discoveredServer4, discoveredServer5; + private GlusterServer server1, server2, server3, server4, server5; + private Volume volume1, volume2, volume3, volume4, volume5; + private Disk s1da, s1db, s2da, s2db, s2dc, s2dd, s3da, s4da, s5da, s5db; + private static List logMessages = new ArrayList(); + private static GlusterDataModelManager instance = new GlusterDataModelManager(); + private GlusterDataModel model; + private String securityToken; + private String serverName; + private List listeners = new ArrayList(); + + private GlusterDataModelManager() { + } + + public String getSecurityToken() { + return securityToken; + } + + public void setSecurityToken(String securityToken) { + this.securityToken = securityToken; + } + + public GlusterDataModel getModel() { + return model; + } + + public static GlusterDataModelManager getInstance() { + return instance; + } + + // Renamed preferredInterfaceName to interfaceName + private GlusterServer addGlusterServer(List servers, Entity parent, String name, + SERVER_STATUS status, String interfaceName, int numOfCPUs, double cpuUsage, double totalMemory, + double memoryInUse) { + GlusterServer glusterServer = new GlusterServer(name, parent, status, numOfCPUs, cpuUsage, totalMemory, + memoryInUse); + NetworkInterface networkInterface = addNetworkInterface(glusterServer, interfaceName); // Renamed preferredInterfaceName to interfaceName + // glusterServer.setPreferredNetworkInterface(networkInterface); + + servers.add(glusterServer); + return glusterServer; + } + + private NetworkInterface addNetworkInterface(Server server, String interfaceName) { + NetworkInterface networkInterface = new NetworkInterface(interfaceName, server, "192.168.1." + + Math.round(Math.random() * 255), "255.255.255.0", "192.168.1.1"); + server.setNetworkInterfaces(Arrays.asList(new NetworkInterface[] { networkInterface })); + return networkInterface; + } + + private void addDiscoveredServer(List servers, Entity parent, String name, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, double totalDiskSpace, double diskSpaceInUse) { + Server server = new Server(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + server.addDisk(new Disk(server, "sda", totalDiskSpace, diskSpaceInUse, DISK_STATUS.READY)); + addNetworkInterface(server, "eth0"); + + servers.add(server); + } + + public void initializeModel(String securityToken) { + setSecurityToken(securityToken); + + // Create the dummy data model for demo + model = new GlusterDataModel("Clusters"); + Cluster cluster = new Cluster("Home", model); + + initializeGlusterServers(cluster); + initializeVolumes(cluster); + initializeAutoDiscoveredServers(cluster); + initializeDisks(); + addDisksToVolumes(); + addVolumeOptions(); + + createDummyLogMessages(); + + initializeRunningTasks(cluster); + + model.addCluster(cluster); + } + + private void addVolumeOptions() { + for (Volume vol : new Volume[] { volume1, volume2, volume3, volume4, volume5 }) { + for (int i = 1; i <= 5; i++) { + String key = vol.getName() + "key" + i; + String value = vol.getName() + "value" + i; + vol.setOption(key, value); + } + } + } + + 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 void initializeVolumes(Cluster cluster) { + List volumes = new ArrayList(); + + volume1 = addVolume(volumes, "Volume1", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume2 = addVolume(volumes, "Volume2", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume3 = addVolume(volumes, "Volume3", cluster, VOLUME_TYPE.DISTRIBUTED_MIRROR, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.OFFLINE); + volume3.setReplicaCount(2); + + volume4 = addVolume(volumes, "Volume4", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume5 = addVolume(volumes, "Volume5", cluster, VOLUME_TYPE.DISTRIBUTED_STRIPE, TRANSPORT_TYPE.INFINIBAND, + VOLUME_STATUS.OFFLINE); + volume5.setStripeCount(3); + + cluster.setVolumes(volumes); + } + + private void initializeDisks() { + s1da = new Disk(server1, "sda", 100d, 80d, DISK_STATUS.READY); + s1db = new Disk(server1, "sdb", 100d, 67.83, DISK_STATUS.READY); + + s2da = new Disk(server2, "sda", 200d, 157.12, DISK_STATUS.READY); + s2db = new Disk(server2, "sdb", 200d, 182.27, DISK_STATUS.READY); + s2dc = new Disk(server2, "sdc", 200d, -1d, DISK_STATUS.UNINITIALIZED); + s2dd = new Disk(server2, "sdd", 200d, 124.89, DISK_STATUS.READY); + + s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE); // disk name unavailable since server is offline + + s4da = new Disk(server4, "sda", 100d, 85.39, DISK_STATUS.READY); + + s5da = new Disk(server5, "sda", 100d, 92.83, DISK_STATUS.READY); + s5db = new Disk(server5, "sdb", 200d, 185.69, DISK_STATUS.READY); + } + + private void addDisksToServers() { + server1.addDisk(s1da); + server1.addDisk(s1db); + + server2.addDisk(s2da); + server2.addDisk(s2db); + server2.addDisk(s2dc); + server2.addDisk(s2dd); + + // server3.addDisk(s3da); + + server4.addDisk(s4da); + + server5.addDisk(s5da); + server5.addDisk(s5db); + } + + private void addDisksToVolumes() { + volume1.addDisk(s1da); + + volume2.addDisk(s2da); + volume2.addDisk(s1db); + volume2.addDisk(s3da); + volume2.addDisk(s4da); + + volume3.addDisk(s2db); + volume3.addDisk(s4da); + volume3.addDisk(s5da); + + volume4.addDisk(s1da); + volume4.addDisk(s3da); + volume4.addDisk(s4da); + volume4.addDisk(s5db); + + volume5.addDisk(s2da); + volume5.addDisk(s5db); + } + + private void initializeGlusterServers(Cluster cluster) { + cluster.setServers(new GlusterServersClient(securityToken).getServers()); + } + + private void initializeAutoDiscoveredServers(Cluster cluster) { + cluster.setAutoDiscoveredServers(new DiscoveredServersClient(serverName, securityToken) + .getDiscoveredServerDetails()); + } + + private void addMessages(List messages, Disk disk, String severity, int count) { + for (int i = 1; i <= count; i++) { + String message = severity + "message" + i; + messages.add(new LogMessage(new Date(), disk, severity, message)); + } + } + + private void addMessagesForDisk(List logMessages, Disk disk) { + addMessages(logMessages, disk, "SEVERE", 5); + addMessages(logMessages, disk, "WARNING", 5); + addMessages(logMessages, disk, "DEBUG", 5); + addMessages(logMessages, disk, "INFO", 5); + } + + public void initializeRunningTasks(Cluster cluster) { + cluster.setRunningTasks(new RunningTaskClient(securityToken).getRunningTasks()); + } + + public List createDummyLogMessages() { + addMessagesForDisk(logMessages, s1da); + addMessagesForDisk(logMessages, s1db); + addMessagesForDisk(logMessages, s2da); + addMessagesForDisk(logMessages, s2db); + addMessagesForDisk(logMessages, s2dc); + addMessagesForDisk(logMessages, s2dd); + addMessagesForDisk(logMessages, s4da); + addMessagesForDisk(logMessages, s5da); + addMessagesForDisk(logMessages, s5db); + return logMessages; + } + + public static List getDummyLogMessages() { + return logMessages; + } + + public List getReadyDisksOfVolume(Volume volume) { + List disks = new ArrayList(); + for (Disk disk : volume.getDisks()) { + if (disk.isReady()) { + disks.add(disk); + } + } + return disks; + } + + public List getReadyDisksOfAllVolumes() { + List disks = new ArrayList(); + for (Volume volume : ((Cluster) model.getChildren().get(0)).getVolumes()) { + disks.addAll(getReadyDisksOfVolume(volume)); + } + return disks; + } + + public List getReadyDisksOfAllServers() { + return getReadyDisksOfAllServersExcluding(new ArrayList()); + } + + public List getReadyDisksOfAllServersExcluding(List excludeDisks) { + List disks = new ArrayList(); + + for (Server server : ((Cluster) model.getChildren().get(0)).getServers()) { + for (Disk disk : server.getDisks()) { + if (disk.isReady() && !excludeDisks.contains(disk)) { + disks.add(disk); + } + } + } + return disks; + } + + public void addClusterListener(ClusterListener listener) { + listeners.add(listener); + } + + public void removeClusterListener(ClusterListener listener) { + listeners.remove(listener); + } + + public void addGlusterServer(GlusterServer server) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.addServer(server); + + for(ClusterListener listener : listeners) { + listener.serverAdded(server); + } + } + + public void removeDiscoveredServer(Server server) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.removeDiscoveredServer(server); + + for(ClusterListener listener : listeners) { + listener.discoveredServerRemoved(server); + } + } + + public void updateVolumeStatus(Volume volume, VOLUME_STATUS newStatus) { + volume.setStatus(newStatus); + for(ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_STATUS_CHANGED, newStatus)); + } + } + + public void addVolume(Volume volume) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.addVolume(volume); + + for(ClusterListener listener : listeners) { + listener.volumeCreated(volume); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java new file mode 100644 index 00000000..25fe3bbc --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.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.client; + +import java.util.List; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServerListResponse; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.sun.jersey.api.representation.Form; + +public class GlusterServersClient extends AbstractClient { + private static final String RESOURCE_NAME = "/cluster/servers"; + + public GlusterServersClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + public List getServers() { + GlusterServerListResponse response = (GlusterServerListResponse) fetchResource(GlusterServerListResponse.class); + return response.getServers(); + } + + @SuppressWarnings("unchecked") + public Server getServer(String serverName) { + GenericResponse response = (GenericResponse) fetchSubResource(serverName, GenericResponse.class); + return response.getData(); + } + + public String getServerXML(String serverName) { + return ((String) fetchSubResource(serverName, String.class)); + } + + public GlusterServerResponse addServer(Server discoveredServer) { + Form form = new Form(); + form.add("serverName", discoveredServer.getName()); + return (GlusterServerResponse)postRequest(GlusterServerResponse.class, form); + } + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + + GlusterServersClient serverResource = new GlusterServersClient(usersClient.getSecurityToken()); + List glusterServers = serverResource.getServers(); + for (GlusterServer server : glusterServers) { + System.out.println(server.getName()); + } + + // Add server + Server srv = new Server(); + srv.setName("server3"); + GlusterServerResponse response = serverResource.addServer(srv); + System.out.println(response.getGlusterServer().getName()); + System.out.println(response.getStatus().isSuccess()); + + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java new file mode 100644 index 00000000..05e1e094 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.client; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.DefaultClientConfig; + +public class RESTClientTest { + public static void main(String args[]) { + WebResource service = Client.create(new DefaultClientConfig()).resource(getBaseURI()); + String name = service.path("services").path("name").accept(MediaType.TEXT_PLAIN).get(String.class); + System.out.println(name); + name = service.path("services").path("name/xml").accept(MediaType.TEXT_XML).get(String.class); + System.out.println(name); + } + + private static URI getBaseURI() { + return UriBuilder.fromUri("http://localhost:8080/glustermc").build(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java new file mode 100644 index 00000000..9309cdc8 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java @@ -0,0 +1,31 @@ +package com.gluster.storage.management.client; + +import java.util.List; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.RunningTaskListResponse; + +public class RunningTaskClient extends AbstractClient { + private static final String RESOURCE_NAME = RESTConstants.RESOURCE_PATH_RUNNING_TASKS; + + public RunningTaskClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + @SuppressWarnings("rawtypes") + private Object fetchRunningTasks(Class responseClass) { + return fetchResource( responseClass ); + } + + public List getRunningTasks() { + RunningTaskListResponse response = (RunningTaskListResponse) fetchRunningTasks( RunningTaskListResponse.class ); + return response.getRunningTasks(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java new file mode 100644 index 00000000..8d7a52fc --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * 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.client; + +import com.gluster.storage.management.core.model.Status; +import com.sun.jersey.api.representation.Form; +import com.sun.jersey.core.util.Base64; + +public class UsersClient extends AbstractClient { + private static final String RESOURCE_NAME = "users"; + private static final String FORM_PARAM_OLD_PASSWORD = "oldpassword"; + private static final String FORM_PARAM_NEW_PASSWORD = "newpassword"; + + private String generateSecurityToken(String user, String password) { + return new String(Base64.encode(user + ":" + password)); + } + + public UsersClient() { + super(); + } + + public boolean authenticate(String user, String password) { + setSecurityToken(generateSecurityToken(user, password)); + try { + Status authStatus = (Status) fetchSubResource(user, Status.class); + if (authStatus.isSuccess()) { + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + + // If we reach here, it means authentication failed. Clear security token and return false. + setSecurityToken(null); + return false; + } + + public boolean changePassword(String user, String oldPassword, String newPassword) { + setSecurityToken(generateSecurityToken(user, oldPassword)); + + Form form = new Form(); + form.add(FORM_PARAM_OLD_PASSWORD, oldPassword); + form.add(FORM_PARAM_NEW_PASSWORD, newPassword); + Status status = (Status) putRequest(user, Status.class, form); + + return status.isSuccess(); + } + + public static void main(String[] args) { + UsersClient authClient = new UsersClient(); + + // authenticate user + System.out.println(authClient.authenticate("gluster", "gluster")); + + // change password to gluster1 + System.out.println(authClient.changePassword("gluster", "gluster", "gluster1")); + + // change it back to gluster + System.out.println(authClient.changePassword("gluster", "gluster1", "gluster")); + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.client.AbstractClient#getResourceName() + */ + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.client.AbstractClient#getSecurityToken() + */ + @Override + public String getSecurityToken() { + return super.getSecurityToken(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java new file mode 100644 index 00000000..03e83a31 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java @@ -0,0 +1,90 @@ +/** + * VolumesClient.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.client; + +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.sun.jersey.api.representation.Form; + +public class VolumesClient extends AbstractClient { + + public VolumesClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESTConstants.RESOURCE_PATH_VOLUMES; + } + + @SuppressWarnings("unchecked") + public Status createVolume(Volume volume) { + GenericResponse createVolumeResponse = (GenericResponse) postObject(GenericResponse.class, volume); + + if (!createVolumeResponse.getStatus().isSuccess()) { + return (Status) createVolumeResponse.getStatus(); + } + return (Status) createVolumeResponse.getStatus(); + } + + private Status performOperation(String volumeName, String operation) { + Form form = new Form(); + form.add(RESTConstants.FORM_PARAM_OPERATION, operation); + + return (Status)putRequest(volumeName, Status.class, form); + } + + public Status startVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_START); + } + + public Status stopVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_STOP); + } + + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + VolumesClient VC = new VolumesClient(usersClient.getSecurityToken()); + List disks = new ArrayList(); + Disk diskElement = new Disk(); + diskElement.setName("sda1"); + diskElement.setStatus(DISK_STATUS.READY); + disks.add(diskElement); + diskElement.setName("sda2"); + diskElement.setStatus(DISK_STATUS.READY); + disks.add(diskElement); + + Volume vol = new Volume("vol1", null, Volume.VOLUME_TYPE.PLAIN_DISTRIBUTE, Volume.TRANSPORT_TYPE.ETHERNET, + Volume.VOLUME_STATUS.ONLINE); + // vol.setDisks(disks); + System.out.println(VC.createVolume(vol)); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java new file mode 100644 index 00000000..853cfe96 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java @@ -0,0 +1,32 @@ +/** + * ClientConstants.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.client.constants; + +/** + * + */ +public class ClientConstants { + public static final String SYS_PROP_SERVER_URL = "gluster.server.url"; + public static final String DEFAULT_SERVER_URL = "http://localhost:8080/glustermc/linux.gtk.x86_64"; + public static final String WEB_CONTEXT = "glustermc"; + public static final String WEB_RESOURCE_BASE_PATH = "resources"; +} + diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java new file mode 100644 index 00000000..23d2f9fd --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java @@ -0,0 +1,20 @@ +package com.gluster.storage.management.client.utils; + +import java.net.URI; + +import javax.ws.rs.core.UriBuilder; + +import com.gluster.storage.management.client.constants.ClientConstants; + +public class ClientUtil { + + public URI getServerBaseURI() { + return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.WEB_RESOURCE_BASE_PATH).build(); + } + + private String getBaseURL() { + // remove the platform path (e.g. /linux.gtk.x86_64) from the URL + return System.getProperty(ClientConstants.SYS_PROP_SERVER_URL, ClientConstants.DEFAULT_SERVER_URL) + .replaceAll("glustermc\\/.*", "glustermc\\/"); + } +} diff --git a/src/com.gluster.storage.management.core/.classpath b/src/com.gluster.storage.management.core/.classpath new file mode 100644 index 00000000..b41cbcdb --- /dev/null +++ b/src/com.gluster.storage.management.core/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/com.gluster.storage.management.core/.project b/src/com.gluster.storage.management.core/.project new file mode 100644 index 00000000..6c8fbb5c --- /dev/null +++ b/src/com.gluster.storage.management.core/.project @@ -0,0 +1,28 @@ + + + com.gluster.storage.management.core + + + + + + 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.core/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f22cedf1 --- /dev/null +++ b/src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 22 11:18:01 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.core/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF new file mode 100644 index 00000000..b5a2a830 --- /dev/null +++ b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gluster Storage Platform Core +Bundle-SymbolicName: com.gluster.storage.management.core +Bundle-Version: 1.0.0 +Bundle-Vendor: GLUSTER +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Export-Package: com.gluster.storage.management.core.constants, + com.gluster.storage.management.core.exceptions, + com.gluster.storage.management.core.model, + com.gluster.storage.management.core.utils +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0" diff --git a/src/com.gluster.storage.management.core/build.properties b/src/com.gluster.storage.management.core/build.properties new file mode 100644 index 00000000..34d2e4d2 --- /dev/null +++ b/src/com.gluster.storage.management.core/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java b/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java new file mode 100644 index 00000000..8902ae8f --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java @@ -0,0 +1,84 @@ +/** + * TestFileUtil.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.core.utils; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStreamWriter; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestFileUtil { + private String testFileName; + private String fileContent; + private FileUtil fileUtil; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + testFileName = "testFileUtil.txt"; + fileContent = "Testing FileUtil class."; + fileUtil = new FileUtil(); + + BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(testFileName)); + OutputStreamWriter writer = new OutputStreamWriter(outStream); + writer.write(fileContent); + writer.close(); + outStream.close(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + File testFile = new File(testFileName); + testFile.delete(); + } + + /** + * Test method for {@link com.gluster.storage.management.core.utils.FileUtil#readFileAsString(java.io.File)}. + */ + @Test + public final void testReadFileAsString() { + String readContent = fileUtil.readFileAsString(new File(testFileName)); + assertTrue("File contents expected [" + fileContent + "], actual [" + readContent + "]", + readContent.equals(fileContent)); + } + + /** + * Test method for {@link com.gluster.storage.management.core.utils.FileUtil#loadResource(java.lang.String)}. + */ + @Test + public final void testLoadResource() { + InputStream inputStream = fileUtil.loadResource("test/test.txt"); + Assert.assertNotNull(inputStream); + } +} diff --git a/src/com.gluster.storage.management.core/junit/core.junit.launch b/src/com.gluster.storage.management.core/junit/core.junit.launch new file mode 100644 index 00000000..0bf6dc30 --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/core.junit.launch @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.core/junit/test/test.txt b/src/com.gluster.storage.management.core/junit/test/test.txt new file mode 100644 index 00000000..267ce144 --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/test/test.txt @@ -0,0 +1 @@ +Test Resource \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java new file mode 100644 index 00000000..177334bd --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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.core.constants; + + +/** + * + */ +public class CoreConstants { + public static final String NEWLINE = System.getProperty("line.separator"); + public static final String FILE_SEPARATOR = System.getProperty("file.separator"); + public static final String ENCODING_UTF8 = "UTF-8"; +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java new file mode 100644 index 00000000..fb40be8a --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -0,0 +1,37 @@ +/** + * RESTConstants.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.core.constants; + +/** + * All constants related to the Gluster REST server and client + */ +public class RESTConstants { + // Volumes Resource + public static final String RESOURCE_PATH_VOLUMES = "/cluster/volumes"; + public static final String FORM_PARAM_OPERATION = "operation"; + public static final String FORM_PARAM_VALUE_START = "start"; + public static final String FORM_PARAM_VALUE_STOP = "stop"; + public static final String PATH_PARAM_VOLUME_NAME = "volumeName"; + public static final String SUBRESOURCE_DEFAULT_OPTIONS = "defaultoptions"; + + // Running tasks resource + public static final String RESOURCE_PATH_RUNNING_TASKS = "/cluster/runningtasks"; +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java new file mode 100644 index 00000000..e7e604fc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.core.exceptions; + +public class GlusterRuntimeException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public GlusterRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public GlusterRuntimeException(String message) { + super(message); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java new file mode 100644 index 00000000..be552bdc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.core.model; + +public abstract class AbstractResponse implements Response { + private Status status; + + @Override + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java new file mode 100644 index 00000000..65d5ebea --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="cluster") +public class Cluster extends Entity { + List servers = new ArrayList(); + List discoveredServers = new ArrayList(); + List volumes = new ArrayList(); + List runningTasks = new ArrayList(); + + public Cluster() { + } + + public List getServers() { + return servers; + } + + public void addServer(GlusterServer server) { + servers.add(server); + } + + public void removeServer(GlusterServer server) { + servers.remove(server); + } + + public void addDiscoveredServer(Server server) { + discoveredServers.add(server); + } + + public void removeDiscoveredServer(Server server) { + discoveredServers.remove(server); + } + + public void setServers(List servers) { + this.servers = servers; + children.add(new EntityGroup("Servers", GlusterServer.class, this, servers)); + } + + public List getAutoDiscoveredServers() { + return discoveredServers; + } + + public void setAutoDiscoveredServers(List autoDiscoveredServers) { + this.discoveredServers = autoDiscoveredServers; + children.add(new EntityGroup("Discovered Servers", Server.class, this, autoDiscoveredServers)); + } + + public List getVolumes() { + return volumes; + } + + public void setVolumes(List volumes) { + this.volumes = volumes; + children.add(new EntityGroup("Volumes", Volume.class, this, volumes)); + } + + public void addVolume(Volume volume) { + this.volumes.add(volume); + } + + public Cluster(String name, Entity parent) { + super(name, parent); + } + + public Cluster(String name, Entity parent, List servers, List volumes) { + super(name, parent); + setServers(servers); + setVolumes(volumes); + } + + public List getRunningTasks() { + return runningTasks; + } + + public void setRunningTasks(List runningTasks) { + this.runningTasks = runningTasks; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java new file mode 100644 index 00000000..ce2752a4 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.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.core.model; + +/** + * Interface for a cluster listener. Every registered listener will be notified + * on various events happening on the cluster. + */ +public interface ClusterListener { + public void discoveredServerAdded(Server server); + + public void discoveredServerRemoved(Server server); + + public void serverAdded(GlusterServer server); + + public void serverRemoved(GlusterServer server); + + public void serverChanged(GlusterServer server, Event event); + + public void volumeAdded(Volume volume); + + public void volumeRemoved(Volume volume); + + public void volumeChanged(Volume volume, Event event); + + public void volumeCreated(Volume volume); +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java new file mode 100644 index 00000000..ccf8fecf --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.core.model; + +public class ConnectionDetails { + private String userId, password; + + public ConnectionDetails() { + + } + + public ConnectionDetails(String userId, String password) { + this.userId = userId; + this.password = password; + } + + public String getUserId() { + return userId; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java new file mode 100644 index 00000000..1a39a014 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * 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.core.model; + +/** + * Default listener - doesn't do anything. Sub-class and override the method for + * the event you want to handle. + */ +public class DefaultClusterListener implements ClusterListener { + + @Override + public void serverAdded(GlusterServer server) { + clusterChanged(); + } + + @Override + public void serverRemoved(GlusterServer server) { + clusterChanged(); + } + + @Override + public void serverChanged(GlusterServer server, Event event) { + clusterChanged(); + } + + @Override + public void volumeAdded(Volume volume) { + clusterChanged(); + } + + @Override + public void volumeRemoved(Volume volume) { + clusterChanged(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + clusterChanged(); + } + + @Override + public void discoveredServerAdded(Server server) { + clusterChanged(); + } + + @Override + public void discoveredServerRemoved(Server server) { + clusterChanged(); + } + + @Override + public void volumeCreated(Volume volume) { + clusterChanged(); + } + + /** + * This method is called by every other event method. Thus, if a view/listener is interested in performing the same + * task on any change happening in the cluster data model, it can simply override this method and implement the + * logic. e.g. A view may simply refresh its tree/table viewer whenever the cluster data model changes. + */ + public void clusterChanged() { + + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java new file mode 100644 index 00000000..9924d596 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name="Disk") +public class Disk extends Entity { + public enum DISK_STATUS { + READY, UNINITIALIZED, INITIALIZING, OFFLINE + }; + + private String[] DISK_STATUS_STR = { "Ready", "Uninitialized", "Initializing", "Offline" }; + + private String serverName; + private Double space; + private Double spaceInUse; + private DISK_STATUS status; + + public Disk() { + + } + + public Double getSpace() { + return space; + } + + public void setSpace(Double space) { + this.space = space; + } + + public boolean isUninitialized() { + return getStatus() == DISK_STATUS.UNINITIALIZED; + } + + public boolean isOffline() { + return getStatus() == DISK_STATUS.OFFLINE; + } + + public boolean isReady() { + return getStatus() == DISK_STATUS.READY; + } + + public DISK_STATUS getStatus() { + return status; + } + + public String getStatusStr() { + return DISK_STATUS_STR[getStatus().ordinal()]; + } + + public void setStatus(DISK_STATUS status) { + this.status = status; + } + + public Double getSpaceInUse() { + return spaceInUse; + } + + public void setSpaceInUse(Double spaceInUse) { + this.spaceInUse = spaceInUse; + } + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public Disk(Server server, String name, Double space, Double spaceInUse, DISK_STATUS status) { + super(name, server); + setServerName(server != null ? server.getName() : ""); + setSpace(space); + setSpaceInUse(spaceInUse); + setStatus(status); + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getServerName() + getName() + getStatusStr(), filterString, caseSensitive); + } + + public String getQualifiedName() { + return getServerName() + ":" + getName(); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java new file mode 100644 index 00000000..e721d052 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import org.eclipse.core.runtime.PlatformObject; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement +public class Entity extends PlatformObject implements Filterable { + private static final long serialVersionUID = 1L; + + protected String name; + protected List children = new ArrayList(); + private Entity parent; + + public Entity() { + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @XmlTransient + public Entity getParent() { + return parent; + } + + public void setParent(Entity parent) { + this.parent = parent; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public Entity(String name, Entity parent) { + this.name = name; + this.parent = parent; + } + + public Entity(String name, Entity parent, List children) { + this.name = name; + this.parent = parent; + this.children = children; + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java new file mode 100644 index 00000000..0fc0f507 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.List; + +public class EntityGroup extends Entity { + private Class type; + + public EntityGroup(String name, Class type, Cluster cluster) { + this(name, type, cluster, null); + } + + public EntityGroup(String name, Class type, Cluster cluster, List entities) { + super(name, cluster, (List)entities); + this.type = type; + } + + public List getEntities() { + return children; + } + + public void setEntities(List entities) { + children = (List)entities; + } + + public Class getEntityType() { + return type; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java new file mode 100644 index 00000000..65501a2b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.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.core.model; + +public class Event { + public enum EVENT_TYPE { + DISK_ADDED, + DISK_REMOVED, + NETWORK_INTERFACE_ADDED, + NETWORK_INTERFACE_REMOVED, + VOLUME_STATUS_CHANGED + } + + private EVENT_TYPE eventType; + private Object eventData; + + public Event(EVENT_TYPE eventType, Object eventData) { + this.eventType = eventType; + this.eventData = eventData; + } + + public EVENT_TYPE getEventType() { + return eventType; + } + + public void setEventType(EVENT_TYPE eventType) { + this.eventType = eventType; + } + + public Object getEventData() { + return eventData; + } + + public void setEventData(Object eventData) { + this.eventData = eventData; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java new file mode 100644 index 00000000..9a2ed405 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.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.core.model; + +/** + * By default, the {@link EntityViewerFilter} filters the objects by parsing the + * output of {@link Object#toString()} with the filter string. Classes that need + * specific filtering logic can implement this interface. The default logic will + * then be overridden by the method {@link Filterable#filter(String)}. + */ +public interface Filterable { + /** + * @param filterString + * String to be used for filtering + * @param caseSensitive + * Flag indicating whether the filtering should be case sensitive + * @return true if the object can be selected using the filter string, else + * false + */ + public boolean filter(String filterString, boolean caseSensitive); +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java new file mode 100644 index 00000000..efeed34b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java @@ -0,0 +1,56 @@ +/** + * GenericServerResponse.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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class GenericResponse extends AbstractResponse { + private T data; + private Status status; + + @Override + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public GenericResponse(Status status, T data) { + setStatus(status); + this.data = data; + } + + public GenericResponse() { + } + + @Override + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java new file mode 100644 index 00000000..612cae31 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.ArrayList; +import java.util.List; + +public class GlusterDataModel extends Entity { + public GlusterDataModel(String name, List clusters) { + super(name, null); + children.addAll(clusters); + } + + public GlusterDataModel(String name) { + this(name, new ArrayList()); + } + + public void setClusters(List clusters) { + children.clear(); + children.addAll(clusters); + } + + public void addCluster(Cluster cluster) { + children.add(cluster); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java new file mode 100644 index 00000000..11d31553 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +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; + +public class GlusterDummyModel { + // private Server discoveredServer1, discoveredServer2, discoveredServer3, discoveredServer4, discoveredServer5; + private GlusterServer server1, server2, server3, server4, server5; + private Volume volume1, volume2, volume3, volume4, volume5; + private Disk s1da, s1db, s2da, s2db, s2dc, s2dd, s3da, s4da, s5da, s5db; + private static List logMessages = new ArrayList(); + private static GlusterDummyModel instance = new GlusterDummyModel(); + private GlusterDataModel model; + + private GlusterDummyModel() { + model = initializeModel(); + } + + public GlusterDataModel getModel() { + return model; + } + + public static GlusterDummyModel getInstance() { + return instance; + } + + // Renamed preferredInterfaceName to interfaceName + private GlusterServer addGlusterServer(List servers, Entity parent, String name, + SERVER_STATUS status, String interfaceName, int numOfCPUs, double cpuUsage, double totalMemory, + double memoryInUse) { + GlusterServer glusterServer = new GlusterServer(name, parent, status, numOfCPUs, cpuUsage, totalMemory, + memoryInUse); + NetworkInterface networkInterface = addNetworkInterface(glusterServer, interfaceName); // Renamed preferredInterfaceName to interfaceName + // glusterServer.setPreferredNetworkInterface(networkInterface); + + servers.add(glusterServer); + return glusterServer; + } + + private NetworkInterface addNetworkInterface(Server server, String interfaceName) { + NetworkInterface networkInterface = new NetworkInterface(interfaceName, server, "192.168.1." + + Math.round(Math.random() * 255), "255.255.255.0", "192.168.1.1"); + server.setNetworkInterfaces(Arrays.asList(new NetworkInterface[] { networkInterface })); + return networkInterface; + } + + private void addDiscoveredServer(List servers, Entity parent, String name, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, double totalDiskSpace, double diskSpaceInUse) { + Server server = new Server(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + server.addDisk(new Disk(server, "sda", totalDiskSpace, diskSpaceInUse, DISK_STATUS.READY)); + addNetworkInterface(server, "eth0"); + + servers.add(server); + } + + private GlusterDataModel initializeModel() { + // Create the dummy data model for demo + GlusterDataModel model = new GlusterDataModel("Clusters"); + Cluster cluster = new Cluster("Home", model); + + initializeGlusterServers(cluster); + initializeVolumes(cluster); + initializeAutoDiscoveredServers(cluster); + initializeDisks(); + addDisksToServers(); + addDisksToVolumes(); + addVolumeOptions(); + + createDummyLogMessages(); + + model.addCluster(cluster); + return model; + } + + private void addVolumeOptions() { + for (Volume vol : new Volume[] { volume1, volume2, volume3, volume4, volume5 }) { + for (int i = 1; i <= 5; i++) { + String key = vol.getName() + "key" + i; + String value = vol.getName() + "value" + i; + vol.setOption(key, value); + } + } + } + + private 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 void initializeVolumes(Cluster cluster) { + List volumes = new ArrayList(); + + volume1 = addVolume(volumes, "Volume1", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume2 = addVolume(volumes, "Volume2", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume3 = addVolume(volumes, "Volume3", cluster, VOLUME_TYPE.DISTRIBUTED_MIRROR, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.OFFLINE); + volume3.setReplicaCount(2); + + volume4 = addVolume(volumes, "Volume4", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume5 = addVolume(volumes, "Volume5", cluster, VOLUME_TYPE.DISTRIBUTED_STRIPE, TRANSPORT_TYPE.INFINIBAND, + VOLUME_STATUS.OFFLINE); + volume5.setStripeCount(3); + + cluster.setVolumes(volumes); + } + + private void initializeDisks() { + s1da = new Disk(server1, "sda", 100d, 80d, DISK_STATUS.READY); + s1db = new Disk(server1, "sdb", 100d, 67.83, DISK_STATUS.READY); + + s2da = new Disk(server2, "sda", 200d, 157.12, DISK_STATUS.READY); + s2db = new Disk(server2, "sdb", 200d, 182.27, DISK_STATUS.READY); + s2dc = new Disk(server2, "sdc", 200d, -1d, DISK_STATUS.UNINITIALIZED); + s2dd = new Disk(server2, "sdd", 200d, 124.89, DISK_STATUS.READY); + + s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE); // disk name unavailable since server is offline + + s4da = new Disk(server4, "sda", 100d, 85.39, DISK_STATUS.READY); + + s5da = new Disk(server5, "sda", 100d, 92.83, DISK_STATUS.READY); + s5db = new Disk(server5, "sdb", 200d, 185.69, DISK_STATUS.READY); + } + + private void addDisksToServers() { + server1.addDisk(s1da); + server1.addDisk(s1db); + + server2.addDisk(s2da); + server2.addDisk(s2db); + server2.addDisk(s2dc); + server2.addDisk(s2dd); + + // server3.addDisk(s3da); + + server4.addDisk(s4da); + + server5.addDisk(s5da); + server5.addDisk(s5db); + } + + private void addDisksToVolumes() { + volume1.addDisk(s1da); + + volume2.addDisk(s2da); + volume2.addDisk(s1db); + volume2.addDisk(s3da); + volume2.addDisk(s4da); + + volume3.addDisk(s2db); + volume3.addDisk(s4da); + volume3.addDisk(s5da); + + volume4.addDisk(s1da); + volume4.addDisk(s3da); + volume4.addDisk(s4da); + volume4.addDisk(s5db); + + volume5.addDisk(s2da); + volume5.addDisk(s5db); + } + + private void initializeGlusterServers(Cluster cluster) { + List servers = new ArrayList(); + server1 = addGlusterServer(servers, cluster, "Server1", SERVER_STATUS.ONLINE, "eth0", 4, 56.3, 16, 8.4); + server2 = addGlusterServer(servers, cluster, "Server2", SERVER_STATUS.ONLINE, "eth1", 8, 41.92, 32, 18.76); + server3 = addGlusterServer(servers, cluster, "Server3", SERVER_STATUS.OFFLINE, "eth0", -1, -1, -1, -1); + server4 = addGlusterServer(servers, cluster, "Server4", SERVER_STATUS.ONLINE, "eth0", 1, 92.83, 4, 3.18); + server5 = addGlusterServer(servers, cluster, "Server5", SERVER_STATUS.ONLINE, "inf0", 2, 87.24, 8, 7.23); + + cluster.setServers(servers); + } + + private void initializeAutoDiscoveredServers(Cluster cluster) { + List servers = new ArrayList(); + addDiscoveredServer(servers, cluster, "ADServer1", 4, 56.3, 16, 8.4, 200, 147.83); + addDiscoveredServer(servers, cluster, "ADServer2", 8, 41.92, 32, 18.76, 800, 464.28); + addDiscoveredServer(servers, cluster, "ADServer3", 2, 84.28, 2, 1.41, 120, 69.93); + addDiscoveredServer(servers, cluster, "ADServer4", 1, 92.83, 4, 3.18, 100, 85.39); + addDiscoveredServer(servers, cluster, "ADServer5", 2, 87.24, 8, 7.23, 250, 238.52); + cluster.setAutoDiscoveredServers(servers); + } + + private void addMessages(List messages, Disk disk, String severity, int count) { + for (int i = 1; i <= count; i++) { + String message = severity + "message" + i; + messages.add(new LogMessage(new Date(), disk, severity, message)); + } + } + + private void addMessagesForDisk(List logMessages, Disk disk) { + addMessages(logMessages, disk, "SEVERE", 5); + addMessages(logMessages, disk, "WARNING", 5); + addMessages(logMessages, disk, "DEBUG", 5); + addMessages(logMessages, disk, "INFO", 5); + } + + public List createDummyLogMessages() { + addMessagesForDisk(logMessages, s1da); + addMessagesForDisk(logMessages, s1db); + addMessagesForDisk(logMessages, s2da); + addMessagesForDisk(logMessages, s2db); + addMessagesForDisk(logMessages, s2dc); + addMessagesForDisk(logMessages, s2dd); + addMessagesForDisk(logMessages, s4da); + addMessagesForDisk(logMessages, s5da); + addMessagesForDisk(logMessages, s5db); + return logMessages; + } + + public static List getDummyLogMessages() { + return logMessages; + } + + public List getReadyDisksOfVolume(Volume volume) { + List disks = new ArrayList(); + for (Disk disk : volume.getDisks()) { + if (disk.isReady()) { + disks.add(disk); + } + } + return disks; + } + + public List getReadyDisksOfAllVolumes() { + List disks = new ArrayList(); + for (Volume volume : ((Cluster) model.getChildren().get(0)).getVolumes()) { + disks.addAll(getReadyDisksOfVolume(volume)); + } + return disks; + } + + public List getReadyDisksOfAllServers() { + return getReadyDisksOfAllServersExcluding(new ArrayList()); + } + + public List getReadyDisksOfAllServersExcluding(List excludeDisks) { + List disks = new ArrayList(); + + for (Server server : ((Cluster) model.getChildren().get(0)).getServers()) { + for (Disk disk : server.getDisks()) { + if (disk.isReady() && !excludeDisks.contains(disk)) { + disks.add(disk); + } + } + } + return disks; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java new file mode 100644 index 00000000..fd4e58c9 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * 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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name = "glusterServer") +public class GlusterServer extends Server { + public enum SERVER_STATUS { + ONLINE, OFFLINE + }; + + private static final String[] STATUS_STR = new String[] { "Online", "Offline" }; + + private String uuid; + private SERVER_STATUS status; + // private NetworkInterface preferredNetworkInterface; + private Cluster cluster; + + public GlusterServer() { + } + + public GlusterServer(String name) { + super(name); + } + + public GlusterServer(String name, Entity parent, SERVER_STATUS status, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse) { + super(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + setStatus(status); + } + + public GlusterServer(String name, Entity parent, SERVER_STATUS status, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, Cluster cluster) { + this(name, parent, status, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + setCluster(cluster); + } + + public String getStatusStr() { + return STATUS_STR[getStatus().ordinal()]; + } + + public SERVER_STATUS getStatus() { + return status; + } + + public void setStatus(SERVER_STATUS status) { + this.status = status; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + +// public NetworkInterface getPreferredNetworkInterface() { +// return preferredNetworkInterface; +// } +// +// public void setPreferredNetworkInterface(NetworkInterface preferredNetworkInterface) { +// this.preferredNetworkInterface = preferredNetworkInterface; +// preferredNetworkInterface.setPreferred(true); +// } + + + @XmlTransient + public Cluster getCluster() { + return cluster; + } + + public void setCluster(Cluster cluster) { + this.cluster = cluster; + } + + /** + * Filter matches if any of the properties name, status and primary/secondary/third + * DNS contains the filter string + */ + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getStatusStr(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java new file mode 100644 index 00000000..479dcc09 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java @@ -0,0 +1,71 @@ +/** + * GlusterServerListResponse.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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * + */ +@XmlRootElement(name = "response") +public class GlusterServerListResponse extends AbstractResponse { + private List servers = new ArrayList(); + + public GlusterServerListResponse() { + } + + public GlusterServerListResponse(Status status, List servers) { + setStatus(status); + setServers(servers); + } + + @XmlElementWrapper(name = "servers") + @XmlElement(name = "server", type=GlusterServer.class) + public List getServers() { + return servers; + } + + /** + * @param servers + * the servers to set + */ + public void setServers(List servers) { + this.servers = servers; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.core.model.Response#getData() + */ + @Override + @XmlTransient + public List getData() { + return getServers(); + } +} + diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java new file mode 100644 index 00000000..e00b8288 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java @@ -0,0 +1,32 @@ +package com.gluster.storage.management.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +@XmlRootElement(name = "response") +public class GlusterServerResponse extends AbstractResponse { + private GlusterServer glusterServer; + + public GlusterServerResponse() { + } + + public GlusterServerResponse(Status status, GlusterServer server) { + setStatus(status); + setGlusterServer(server); + } + + public GlusterServer getGlusterServer() { + return glusterServer; + } + + public void setGlusterServer(GlusterServer glusterServer) { + this.glusterServer = glusterServer; + } + + @XmlTransient + @Override + public GlusterServer getData() { + return getGlusterServer(); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java new file mode 100644 index 00000000..cc3aa043 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.Date; + +import com.gluster.storage.management.core.utils.StringUtil; + +public class LogMessage implements Filterable { + private Date timestamp; + private Disk disk; + private String severity; + private String message; + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } + + public Disk getDisk() { + return disk; + } + + public void setDisk(Disk disk) { + this.disk = disk; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public LogMessage(Date timestamp, Disk disk, String severity, String message) { + setTimestamp(timestamp); + setDisk(disk); + setSeverity(severity); + setMessage(message); + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getSeverity() + getTimestamp() + getDisk().getServerName() + + getDisk().getQualifiedName() + getMessage(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java new file mode 100644 index 00000000..882dfe09 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="networkInterface") +public class NetworkInterface extends Entity { + private String ipAddress; + private String netMask; + private String defaultGateway; +// private boolean isPreferred; + + public NetworkInterface() { + + } + +// public boolean isPreferred() { +// return isPreferred; +// } +// +// public void setPreferred(boolean isPreferred) { +// this.isPreferred = isPreferred; +// } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getNetMask() { + return netMask; + } + + public void setNetMask(String netMask) { + this.netMask = netMask; + } + + public String getDefaultGateway() { + return defaultGateway; + } + + public void setDefaultGateway(String defaultGateway) { + this.defaultGateway = defaultGateway; + } + + public NetworkInterface(String name, Entity parent, String ipAddress, String netMask, String defaultGateway) { + super(name, parent); + setIpAddress(ipAddress); + setNetMask(netMask); + setDefaultGateway(defaultGateway); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java new file mode 100644 index 00000000..96ea8497 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.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.core.model; + +/** + * Interface for server response. Any request handled by the Gluster Management + * Server will result in a response that must be an instance of a class + * implementing this interface. + */ +public interface Response { + /** + * @return Status of request processing + */ + public Status getStatus(); + + /** + * @return Data associated with the response. e.g. A "discover servers" + * request will return the list of discovered servers. + */ + public T getData(); +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java new file mode 100644 index 00000000..1a9d63f6 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class RunningTask { + + protected String id; + protected String type; // FormatDisk, MigrateDisk, VolumeRebalance + protected Object reference; + protected String description; + protected RunningTaskStatus status; // TODO redefine + + public RunningTask() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Object getReference() { + return reference; + } + + public void setReference(Object reference) { + this.reference = reference; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public RunningTaskStatus getStatus() { + return status; + } + + public void setStatus(RunningTaskStatus status) { + this.status = status; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java new file mode 100644 index 00000000..79949c90 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java @@ -0,0 +1,43 @@ +package com.gluster.storage.management.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class RunningTaskListResponse extends AbstractResponse { + private List runningTasks = new ArrayList(); + + public RunningTaskListResponse() { + + } + + + public RunningTaskListResponse(Status status, List runningTasks) { + setStatus(status); + setRunningTasks(runningTasks); + } + + @XmlElementWrapper(name = "runningTasks") + @XmlElement(name = "runningTask", type=RunningTask.class) + public List getRunningTasks() { + return runningTasks; + } + + /** + * @param runningTasks + * the runningTasks to set + */ + public void setRunningTasks(List runningTasks) { + this.runningTasks = runningTasks; + } + + @Override + public Object getData() { + return getRunningTasks(); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java new file mode 100644 index 00000000..7ffeb4b8 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java @@ -0,0 +1,41 @@ +package com.gluster.storage.management.core.model; + +public class RunningTaskStatus extends Status { + + private String status; + private boolean isPercentageSupported; + private float percentCompleted; + private String description; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public boolean isPercentageSupported() { + return isPercentageSupported; + } + + public void setPercentageSupported(boolean isPercentageSupported) { + this.isPercentageSupported = isPercentageSupported; + } + + public float getPercentCompleted() { + return percentCompleted; + } + + public void getPercentCompleted(float percentCompleted) { + this.percentCompleted = percentCompleted; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java new file mode 100644 index 00000000..bc0c42bc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name = "server") +public class Server extends Entity { + private List networkInterfaces = new ArrayList(); + private int numOfCPUs; + private double cpuUsage; + private double totalMemory; + private double memoryInUse; + private double totalDiskSpace = 0; + private double diskSpaceInUse = 0; + private List disks = new ArrayList(); + + public Server() { + + } + + public Server(String name) { + super(name, null); + } + + public Server(String name, Entity parent, int numOfCPUs, double cpuUsage, double totalMemory, double memoryInUse) { + super(name, parent); + setNumOfCPUs(numOfCPUs); + setCpuUsage(cpuUsage); + setTotalMemory(totalMemory); + setMemoryInUse(memoryInUse); + } + + public int getNumOfCPUs() { + return numOfCPUs; + } + + public void setNumOfCPUs(int numOfCPUs) { + this.numOfCPUs = numOfCPUs; + } + + public double getCpuUsage() { + return cpuUsage; + } + + public void setCpuUsage(double cpuUsage) { + this.cpuUsage = cpuUsage; + } + + public double getTotalMemory() { + return totalMemory; + } + + public void setTotalMemory(double totalMemory) { + this.totalMemory = totalMemory; + } + + public double getMemoryInUse() { + return memoryInUse; + } + + public void setMemoryInUse(double memoryInUse) { + this.memoryInUse = memoryInUse; + } + + public double getTotalDiskSpace() { + return totalDiskSpace; + } + + /** + * Total disk space is automatically calculated, and hence this method should never be called. It is required only + * to make sure that the element "totalDiskSpace" gets added to the XML tag when jersey converts the server object + * to XML for sending to client. + */ + public void setTotalDiskSpace(double totalDiskSpace) { + this.totalDiskSpace = totalDiskSpace; + } + + public double getDiskSpaceInUse() { + return diskSpaceInUse; + } + + @XmlElementWrapper(name = "networkInterfaces") + @XmlElement(name = "networkInterface", type = NetworkInterface.class) + public List getNetworkInterfaces() { + return networkInterfaces; + } + + public void setNetworkInterfaces(List networkInterfaces) { + this.networkInterfaces = networkInterfaces; + } + + @XmlElementWrapper(name = "disks") + @XmlElement(name = "disk", type = Disk.class) + public List getDisks() { + return disks; + } + + public void addNetworkInterface(NetworkInterface networkInterface) { + networkInterfaces.add(networkInterface); + } + + public void addDisk(Disk disk) { + if (disks.add(disk)) { + totalDiskSpace += disk.getSpace(); + diskSpaceInUse += disk.getSpaceInUse(); + } + } + + public void addDisks(List disks) { + for (Disk disk : disks) { + addDisk(disk); + } + } + + public void removeDisk(Disk disk) { + if (disks.remove(disk)) { + totalDiskSpace -= disk.getSpace(); + diskSpaceInUse -= disk.getSpaceInUse(); + } + } + + public void removeAllDisks() { + disks.clear(); + totalDiskSpace = 0; + diskSpaceInUse = 0; + } + + public void setDisks(List disks) { + removeAllDisks(); + addDisks(disks); + } + + public int getNumOfDisks() { + return disks.size(); + } + + public String getIpAddressesAsString() { + String ipAddresses = ""; + for (NetworkInterface networkInterface : getNetworkInterfaces()) { + String ipAddr = networkInterface.getIpAddress(); + ipAddresses += (ipAddresses.isEmpty() ? ipAddr : ", " + ipAddr); + } + return ipAddresses; + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getIpAddressesAsString(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java new file mode 100644 index 00000000..56f33992 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +@XmlRootElement(name = "response") +public class ServerListResponse extends AbstractResponse { + private List servers = new ArrayList(); + + public ServerListResponse() { + } + + public ServerListResponse(Status status, List servers) { + setStatus(status); + setServers(servers); + } + + @XmlElementWrapper(name = "servers") + @XmlElement(name = "server", type=Server.class) + public List getServers() { + return servers; + } + + /** + * @param servers + * the servers to set + */ + public void setServers(List servers) { + this.servers = servers; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.core.model.Response#getData() + */ + @Override + @XmlTransient + public List getData() { + return getServers(); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java new file mode 100644 index 00000000..06d6efe1 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.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.core.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import com.gluster.storage.management.core.utils.ProcessResult; + +@XmlRootElement(name = "status") +public class Status { + public static final int STATUS_CODE_SUCCESS = 0; + public static final int STATUS_CODE_FAILURE = 1; + public static final int STATUS_CODE_RUNNING = 2; + public static final Status STATUS_SUCCESS = new Status(STATUS_CODE_SUCCESS, "Success"); + public static final Status STATUS_FAILURE = new Status(STATUS_CODE_FAILURE, "Failure"); + + // public static final Status + + private Integer code; + private String message; + + public Status() { + } + + public boolean isSuccess() { + return code == STATUS_CODE_SUCCESS; + } + + public Status(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Status(ProcessResult result) { + this.code = result.getExitValue(); + this.message = result.getOutput(); + } + + @XmlElement(name = "code", type = Integer.class) + public Integer getCode() { + return code; + } + + public void setCode(Integer executionStatus) { + this.code = executionStatus; + } + + @XmlElement + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return (isSuccess() ? "Success" : "Failure [" + getCode() + "]") + ": " + getMessage(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java new file mode 100644 index 00000000..3304692d --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class StringListResponse extends AbstractResponse { + private List data = new ArrayList(); + + public StringListResponse() { + } + + public StringListResponse(List data) { + this.data = data; + } + + @Override + @XmlElementWrapper(name = "list") + @XmlElement(name = "value", type = String.class) + public List getData() { + return data; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java new file mode 100644 index 00000000..da92ca14 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class User { + private String userId; + private String password; + + public String getUserId() { + return userId; + } + public void setUserId(String userId) { + this.userId = userId; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java new file mode 100644 index 00000000..a7e498c4 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java @@ -0,0 +1,252 @@ +/******************************************************************************* + * 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.core.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement +public class Volume extends Entity { + public enum VOLUME_STATUS { + ONLINE, OFFLINE + }; + + public enum VOLUME_TYPE { + PLAIN_DISTRIBUTE, DISTRIBUTED_MIRROR, DISTRIBUTED_STRIPE + }; + + public enum TRANSPORT_TYPE { + ETHERNET, INFINIBAND + }; + + public enum NAS_PROTOCOL { + GLUSTERFS, NFS + }; + + private static final String[] VOLUME_TYPE_STR = new String[] { "Plain Distribute", "Distributed Mirror", + "Distributed Stripe" }; + private static final String[] TRANSPORT_TYPE_STR = new String[] { "Ethernet", "Infiniband" }; + private static final String[] STATUS_STR = new String[] { "Online", "Offline" }; + private static final String[] NAS_PROTOCOL_STR = new String[] { "Gluster", "NFS" }; + + private Cluster cluster; + private VOLUME_TYPE volumeType; + private TRANSPORT_TYPE transportType; + private VOLUME_STATUS status; + private int replicaCount; + private int stripeCount; + private Map options = new LinkedHashMap(); + + private double totalDiskSpace = 0; + private List disks = new ArrayList(); + + public Volume() { + } + + // GlusterFS export is always enabled + private Set nasProtocols = new LinkedHashSet( + Arrays.asList(new NAS_PROTOCOL[] { NAS_PROTOCOL.GLUSTERFS })); + + private String accessControlList = "*"; + + public String getVolumeTypeStr() { + return getVolumeTypeStr(getVolumeType()); + } + + public static String getVolumeTypeStr(VOLUME_TYPE volumeType) { + return VOLUME_TYPE_STR[volumeType.ordinal()]; + } + + public String getTransportTypeStr() { + return TRANSPORT_TYPE_STR[getTransportType().ordinal()]; + } + + public String getStatusStr() { + return STATUS_STR[getStatus().ordinal()]; + } + + public int getNumOfDisks() { + return disks.size(); + } + + public VOLUME_TYPE getVolumeType() { + return volumeType; + } + + public void setVolumeType(VOLUME_TYPE volumeType) { + this.volumeType = volumeType; + } + + public TRANSPORT_TYPE getTransportType() { + return transportType; + } + + public void setTransportType(TRANSPORT_TYPE transportType) { + this.transportType = transportType; + } + + public VOLUME_STATUS getStatus() { + return status; + } + + public int getReplicaCount() { + return replicaCount; + } + + public void setReplicaCount(int replicaCount) { + this.replicaCount = replicaCount; + } + + public int getStripeCount() { + return stripeCount; + } + + public void setStripeCount(int stripeCount) { + this.stripeCount = stripeCount; + } + + public void setStatus(VOLUME_STATUS status) { + this.status = status; + } + + @XmlTransient + public Cluster getCluster() { + return cluster; + } + + public void setCluster(Cluster cluster) { + this.cluster = cluster; + } + + public Set getNASProtocols() { + return nasProtocols; + } + + public void setNASProtocols(Set nasProtocols) { + this.nasProtocols = nasProtocols; + } + + public String getNASProtocolsStr() { + String protocolsStr = ""; + for (NAS_PROTOCOL protocol : nasProtocols) { + String protocolStr = NAS_PROTOCOL_STR[protocol.ordinal()]; + protocolsStr += (protocolsStr.isEmpty() ? protocolStr : ", " + protocolStr); + } + return protocolsStr; + } + + public String getAccessControlList() { + return accessControlList; + } + + public void setAccessControlList(String accessControlList) { + this.accessControlList = accessControlList; + } + + public Map getOptions() { + return options; + } + + public void setOption(String key, String value) { + options.put(key, value); + } + + public void setOptions(Map options) { + this.options = options; + } + + public double getTotalDiskSpace() { + return totalDiskSpace; + } + + public List getDisks() { + return disks; + } + + public void addDisk(Disk disk) { + if (disks.add(disk) && disk.getStatus() != DISK_STATUS.OFFLINE) { + totalDiskSpace += disk.getSpace(); + } + } + + public void addDisks(List disks) { + for (Disk disk : disks) { + addDisk(disk); + } + } + + public void removeDisk(Disk disk) { + if (disks.remove(disk)) { + totalDiskSpace -= disk.getSpace(); + } + } + + public void removeAllDisks() { + disks.clear(); + totalDiskSpace = 0; + } + + public void setDisks(List disks) { + removeAllDisks(); + addDisks(disks); + } + + public void enableNFS() { + nasProtocols.add(NAS_PROTOCOL.NFS); + } + + public void disableNFS() { + nasProtocols.remove(NAS_PROTOCOL.NFS); + } + + public Volume(String name, Entity parent, VOLUME_TYPE volumeType, TRANSPORT_TYPE transportType, VOLUME_STATUS status) { + super(name, parent); + setVolumeType(volumeType); + setTransportType(transportType); + setStatus(status); + } + + public Volume(String name, Entity parent, Cluster cluster, VOLUME_TYPE volumeType, TRANSPORT_TYPE transportType, + VOLUME_STATUS status) { + this(name, parent, volumeType, transportType, status); + + setCluster(cluster); + } + + /** + * Filter matches if any of the properties name, volume type, transport type, status and number of disks contains + * the filter string + */ + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getVolumeTypeStr() + getTransportTypeStr() + getStatusStr() + + getNumOfDisks(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java new file mode 100644 index 00000000..44e45df5 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java @@ -0,0 +1,66 @@ +/** + * VolumeOptionInfo.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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Class to hold information about a volume option + */ +@XmlRootElement(name = "volumeOption") +public class VolumeOptionInfo { + private String name; + private String description; + private String defaultValue; + + public VolumeOptionInfo() { + } + + public VolumeOptionInfo(String name, String description, String defaultValue) { + setName(name); + setDescription(description); + setDefaultValue(defaultValue); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java new file mode 100644 index 00000000..1b284cb8 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.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.core.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateUtil { + public static final String formatDate(Date inputDate) { + DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + return formatter.format(inputDate); + } + + public static final String formatTime(Date inputDate) { + DateFormat formatter = new SimpleDateFormat("HH:mm:ss z"); + return formatter.format(inputDate); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java new file mode 100644 index 00000000..c650d632 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.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.core.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; + +public class FileUtil { + public String readFileAsString(File file) { + try { + FileInputStream fileInputStream = new FileInputStream(file); + byte[] data = new byte[fileInputStream.available()]; + fileInputStream.read(data); + fileInputStream.close(); + + return new String(data); + } catch (Exception e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Could not read file [" + file + "]", e); + } + } + + public InputStream loadResource(String resourcePath) { + return this.getClass().getClassLoader().getResourceAsStream(resourcePath); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java new file mode 100644 index 00000000..ad5b4c2b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java @@ -0,0 +1,218 @@ +/** + * GlusterUtil.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.core.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +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_TYPE; + +/** + * + */ +public class GlusterUtil { + private static final String HOSTNAME_PFX = "Hostname:"; + private static final String UUID_PFX = "Uuid:"; + private static final String STATE_PFX = "State:"; + private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; + private static final ProcessUtil processUtil = new ProcessUtil(); + + /** + * Extract value of given token from given line. It is assumed that the token, if present, will be of the following + * form: token: value + * + * @param line + * Line to be analyzed + * @param token + * Token whose value is to be extracted + * @return Value of the token, if present in the line + */ + private final String extractToken(String line, String token) { + if (line.contains(token)) { + return line.split(token)[1].trim(); + } + return null; + } + + public List getGlusterServers() { + String output = getPeerStatus(); + if (output == null) { + return null; + } + + List glusterServers = new ArrayList(); + GlusterServer server = null; + boolean foundHost = false; + boolean foundUuid = false; + for (String line : output.split(CoreConstants.NEWLINE)) { + if (foundHost && foundUuid) { + // Host and UUID is found, we should look for state + String state = extractToken(line, STATE_PFX); + if (state != null) { + server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE + : SERVER_STATUS.OFFLINE); + // Completed populating current server. Add it to the list and reset all related variables. + glusterServers.add(server); + + foundHost = false; + foundUuid = false; + server = null; + } + } else if (foundHost) { + // Host is found, look for UUID + String uuid = extractToken(line, UUID_PFX); + if (uuid != null) { + server.setUuid(uuid); + foundUuid = true; + } + } else { + // Look for the next host + if (server == null) { + server = new GlusterServer(); + } + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + server.setName(hostName); + foundHost = true; + } + } + + } + return glusterServers; + } + + public List getGlusterServerNames() { + String output = getPeerStatus(); + if(output == null) { + return null; + } + + List glusterServerNames = new ArrayList(); + for (String line : output.split(CoreConstants.NEWLINE)) { + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + glusterServerNames.add(hostName); + } + } + return glusterServerNames; + } + + private String getPeerStatus() { + String output; + ProcessResult result = processUtil.executeCommand("gluster", "peer", "status"); + if (!result.isSuccess()) { + output = null; + } + output = result.getOutput(); + return output; + } + + public ProcessResult addServer(String serverName) { + return processUtil.executeCommand("gluster", "peer", "probe", serverName); + } + + + public ProcessResult startVolume(String volumeName) { + return processUtil.executeCommand("gluster", "volume", "start", volumeName); + } + + public ProcessResult stopVolume(String volumeName) { + return processUtil.executeCommand("gluster", "--mode=script", "volume", "stop", volumeName); + } + + public ProcessResult createVolume(Volume volume) { + int count=1; // replica or stripe count + String volumeType = null; + VOLUME_TYPE volType = volume.getVolumeType(); + if(volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volumeType = "replica"; + count = 2; + } else if(volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volumeType = "stripe"; + count = 4; + } + + String transportTypeStr = null; + TRANSPORT_TYPE transportType = volume.getTransportType(); + transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + + List command = new ArrayList(); + command.add("gluster"); + command.add("volume"); + command.add("create"); + command.add(volume.getName()); + if(volumeType != null) { + command.add(volumeType); + command.add("" + count); + } + command.add("transport"); + command.add(transportTypeStr); + for(Disk disk : volume.getDisks()) { + command.add(getBrickNotation(volume, disk)); + } + return processUtil.executeCommand(command); + } + + public ProcessResult setOption(List command) { + return processUtil.executeCommand(command); + } + + public ProcessResult setVolumeAccessControl(Volume volume) { + List command = new ArrayList(); + command.add("gluster"); + command.add("volume"); + command.add("set"); + command.add(volume.getName()); + command.add("auth.allow"); + command.add(volume.getAccessControlList()); + return setOption(command); + } + + /** + * @param disk + * @return + */ + private String getBrickNotation(Volume vol, Disk disk) { + // TODO: Figure out an appropriate directory INSIDE the DISK having given NAME (e.g. sda, sdb, etc) + // String dirName = "/export/" + vol.getName() + "/" + disk.getName(); + + // if /export directory is not exist then create the directory + boolean exists = (new File("/export")).exists(); + + if (!exists) { + processUtil.executeCommand("mkdir", "/export"); + } + String dirName = "/export/" + vol.getName() ; + return disk.getServerName() + ":" + dirName; + } + + public static void main(String args[]) { + List names = new GlusterUtil().getGlusterServerNames(); + System.out.println(names); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java new file mode 100644 index 00000000..e0daaf81 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java @@ -0,0 +1,504 @@ +/* + * MD5 in Java JDK Beta-2 + * written Santeri Paavolainen, Helsinki Finland 1996 + * (c) Santeri Paavolainen, Helsinki Finland 1996 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * See http://www.cs.hut.fi/~santtu/java/ for more information on this + * class. + * + * This is rather straight re-implementation of the reference implementation + * given in RFC1321 by RSA. + * + * Passes MD5 test suite as defined in RFC1321. + * + * + * This Java class has been derivedfrom the RSA Data Security, Inc. MD5 + * Message-Digest Algorithm and its reference implementation. + * + * + * $Log: MD5.java,v $ + * Revision 1.1 2004/07/12 13:35:20 aubryp + * initial commit + * + * Revision 1.3 2002/03/16 01:46:39 broccol + * Moved the MD5 classes into the md5 package to make 1.4 javac happy + * + * Revision 1.2 1999/11/04 21:38:00 broccol + * Got MD5Crypt calculating the same hash as the OpenBSD md5crypt.c routine. + * + * Revision 1.1 1999/08/05 22:07:03 broccol + * Added support for the MD5 classes. + * + * Revision 1.3 1996/04/15 07:28:09 santtu + * Added GPL statements, and RSA derivate statements. + * + * Revision 1.2 1996/03/04 08:05:48 santtu + * Added offsets to Update method + * + * Revision 1.1 1996/01/07 20:51:59 santtu + * Initial revision + * + */ +package com.gluster.storage.management.core.utils; + +/** + * Contains internal state of the MD5 class + * + * @author Santeri Paavolainen + */ + +class MD5State { + /** + * 128-byte state + */ + int state[]; + + /** + * 64-bit character count (could be true Java long?) + */ + int count[]; + + /** + * 64-byte buffer (512 bits) for storing to-be-hashed characters + */ + byte buffer[]; + + public MD5State() { + buffer = new byte[64]; + count = new int[2]; + state = new int[4]; + + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + count[0] = count[1] = 0; + } + + /** Create this State as a copy of another state */ + public MD5State(MD5State from) { + this (); + + int i; + + for (i = 0; i < buffer.length; i++) + this .buffer[i] = from.buffer[i]; + + for (i = 0; i < state.length; i++) + this .state[i] = from.state[i]; + + for (i = 0; i < count.length; i++) + this .count[i] = from.count[i]; + } +}; + +/** + * Implementation of RSA's MD5 hash generator + * + * @version $Revision: 1.1 $ + * @author Santeri Paavolainen + */ + +public class MD5 { + /** + * MD5 state + */ + MD5State state; + + /** + * If Final() has been called, finals is set to the current finals + * state. Any Update() causes this to be set to null. + */ + MD5State finals; + + /** + * Padding for Final() + */ + static byte padding[] = { (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + /** + * Initialize MD5 internal state (object can be reused just by + * calling Init() after every Final() + */ + public synchronized void Init() { + state = new MD5State(); + finals = null; + } + + /** + * Class constructor + */ + public MD5() { + this .Init(); + } + + /** + * Initialize class, and update hash with ob.toString() + * + * @param ob Object, ob.toString() is used to update hash + * after initialization + */ + public MD5(Object ob) { + this (); + Update(ob.toString()); + } + + public String debugDump() { + return asHex(); + } + + private int rotate_left(int x, int n) { + return (x << n) | (x >>> (32 - n)); + } + + /* I wonder how many loops and hoops you'll have to go through to + get unsigned add for longs in java */ + + private int uadd(int a, int b) { + long aa, bb; + aa = ((long) a) & 0xffffffffL; + bb = ((long) b) & 0xffffffffL; + + aa += bb; + + return (int) (aa & 0xffffffffL); + } + + private int uadd(int a, int b, int c) { + return uadd(uadd(a, b), c); + } + + private int uadd(int a, int b, int c, int d) { + return uadd(uadd(a, b, c), d); + } + + private int FF(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & c) | (~b & d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int GG(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & d) | (c & ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int HH(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (b ^ c ^ d), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int II(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (c ^ (b | ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int[] Decode(byte buffer[], int len, int shift) { + int out[]; + int i, j; + + out = new int[16]; + + for (i = j = 0; j < len; i++, j += 4) { + out[i] = ((int) (buffer[j + shift] & 0xff)) + | (((int) (buffer[j + 1 + shift] & 0xff)) << 8) + | (((int) (buffer[j + 2 + shift] & 0xff)) << 16) + | (((int) (buffer[j + 3 + shift] & 0xff)) << 24); + } + + return out; + } + + private void Transform(MD5State state, byte buffer[], int shift) { + int a = state.state[0], b = state.state[1], c = state.state[2], d = state.state[3], x[]; + + x = Decode(buffer, 64, shift); + + /* Round 1 */ + a = FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */ + d = FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */ + c = FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */ + b = FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */ + a = FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */ + d = FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */ + c = FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */ + b = FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */ + a = FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */ + d = FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */ + c = FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + b = FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + a = FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + d = FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + c = FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + b = FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */ + d = GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */ + c = GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + b = GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */ + a = GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */ + d = GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ + c = GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + b = GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */ + a = GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */ + d = GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + c = GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */ + b = GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */ + a = GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + d = GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */ + c = GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */ + b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */ + d = HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */ + c = HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + b = HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + a = HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */ + d = HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */ + c = HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */ + b = HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + a = HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + d = HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */ + c = HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */ + b = HH(b, c, d, a, x[6], 23, 0x4881d05); /* 44 */ + a = HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */ + d = HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + b = HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */ + d = II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */ + c = II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + b = II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */ + a = II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + d = II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */ + c = II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + b = II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */ + a = II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */ + d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + c = II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */ + b = II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + a = II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */ + d = II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + c = II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */ + b = II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */ + + state.state[0] += a; + state.state[1] += b; + state.state[2] += c; + state.state[3] += d; + } + + /** + * Updates hash with the bytebuffer given (using at maximum length bytes from + * that buffer) + * + * @param stat Which state is updated + * @param buffer Array of bytes to be hashed + * @param offset Offset to buffer array + * @param length Use at maximum `length' bytes (absolute + * maximum is buffer.length) + */ + public void Update(MD5State stat, byte buffer[], int offset, + int length) { + int index, partlen, i, start; + + finals = null; + + /* Length can be told to be shorter, but not inter */ + if ((length - offset) > buffer.length) + length = buffer.length - offset; + + /* compute number of bytes mod 64 */ + index = (int) (stat.count[0] >>> 3) & 0x3f; + + if ((stat.count[0] += (length << 3)) < (length << 3)) + stat.count[1]++; + + stat.count[1] += length >>> 29; + + partlen = 64 - index; + + if (length >= partlen) { + for (i = 0; i < partlen; i++) + stat.buffer[i + index] = buffer[i + offset]; + + Transform(stat, stat.buffer, 0); + + for (i = partlen; (i + 63) < length; i += 64) + Transform(stat, buffer, i); + + index = 0; + } else + i = 0; + + /* buffer remaining input */ + if (i < length) { + start = i; + for (; i < length; i++) + stat.buffer[index + i - start] = buffer[i + offset]; + } + } + + /* + * Update()s for other datatypes than byte[] also. Update(byte[], int) + * is only the main driver. + */ + + /** + * Plain update, updates this object + */ + + public void Update(byte buffer[], int offset, int length) { + Update(this .state, buffer, offset, length); + } + + public void Update(byte buffer[], int length) { + Update(this .state, buffer, 0, length); + } + + /** + * Updates hash with given array of bytes + * + * @param buffer Array of bytes to use for updating the hash + */ + public void Update(byte buffer[]) { + Update(buffer, 0, buffer.length); + } + + /** + * Updates hash with a single byte + * + * @param b Single byte to update the hash + */ + public void Update(byte b) { + byte buffer[] = new byte[1]; + buffer[0] = b; + + Update(buffer, 1); + } + + /** + * Update buffer with given string. + * + * @param s String to be update to hash (is used as + * s.getBytes()) + */ + public void Update(String s) { + byte chars[]; + + chars = s.getBytes(); + + Update(chars, chars.length); + } + + private byte[] Encode(int input[], int len) { + int i, j; + byte out[]; + + out = new byte[len]; + + for (i = j = 0; j < len; i++, j += 4) { + out[j] = (byte) (input[i] & 0xff); + out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); + out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); + out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); + } + + return out; + } + + /** + * Returns array of bytes (16 bytes) representing hash as of the + * current state of this object. Note: getting a hash does not + * invalidate the hash object, it only creates a copy of the real + * state which is finalized. + * + * @return Array of 16 bytes, the hash of all updated bytes + */ + public synchronized byte[] Final() { + byte bits[]; + int index, padlen; + MD5State fin; + + if (finals == null) { + fin = new MD5State(state); + + bits = Encode(fin.count, 8); + + index = (int) ((fin.count[0] >>> 3) & 0x3f); + padlen = (index < 56) ? (56 - index) : (120 - index); + + Update(fin, padding, 0, padlen); + /**/ + Update(fin, bits, 0, 8); + + /* Update() sets finalds to null */ + finals = fin; + } + + return Encode(finals.state, 16); + } + + /** + * Turns array of bytes into string representing each byte as + * unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + */ + public static String asHex(byte hash[]) { + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) { + if (((int) hash[i] & 0xff) < 0x10) + buf.append("0"); + + buf.append(Long.toString((int) hash[i] & 0xff, 16)); + } + + return buf.toString(); + } + + /** + * Returns 32-character hex representation of this objects hash + * + * @return String of this object's hash + */ + public String asHex() { + return asHex(this .Final()); + } + + /** + * One-stop md5 string encrypting. + */ + + public static String md5crypt(String input) { + MD5 md5 = new MD5(); + md5.Init(); + md5.Update(input); + return md5.asHex(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java new file mode 100644 index 00000000..25c757a2 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java @@ -0,0 +1,339 @@ +/*------------------------------------------------------------------------------ + class + MD5Crypt + ------------------------------------------------------------------------------*/ + +package com.gluster.storage.management.core.utils; + + +/** + *

This class defines a method, + * {@link MD5Crypt#crypt(java.lang.String, java.lang.String) crypt()}, which + * takes a password and a salt string and generates an OpenBSD/FreeBSD/Linux-compatible + * md5-encoded password entry.

+ * + *

Created: 3 November 1999

+ *

Release: $Name: $

+ *

Version: $Revision: 1.1 $

+ *

Last Mod Date: $Date: 2004/07/12 13:35:20 $

+ *

Java Code By: Jonathan Abbey, jonabbey@arlut.utexas.edu

+ *

Original C Version:

+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ *  wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ * 

+ * + * @author Jonathan Abbey + */ +public final class MD5Crypt { + + /** + * + * Command line test rig. + * + */ + + static public void main(String argv[]) { + if ((argv.length < 1) || (argv.length > 3)) { + System.err + .println("Usage: MD5Crypt [-apache] password salt"); + System.exit(1); + } + + if (argv.length == 3) { + System.err.println(MD5Crypt.apacheCrypt(argv[1], argv[2])); + } else if (argv.length == 2) { + System.err.println(MD5Crypt.crypt(argv[0], argv[1])); + } else { + System.err.println(MD5Crypt.crypt(argv[0])); + } + + System.exit(0); + } + + static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + + static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + static private final String to64(long v, int size) { + StringBuffer result = new StringBuffer(); + + while (--size >= 0) { + result.append(itoa64.charAt((int) (v & 0x3f))); + v >>>= 6; + } + + return result.toString(); + } + + static private final void clearbits(byte bits[]) { + for (int i = 0; i < bits.length; i++) { + bits[i] = 0; + } + } + + /** + * convert an encoded unsigned byte value into a int + * with the unsigned value. + */ + + static private final int bytes2u(byte inp) { + return (int) inp & 0xff; + } + + /** + *

This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible + * md5-encoded password hash from a plaintext password and a + * salt.

+ * + *

The resulting string will be in the form '$1$<salt>$<hashed mess>

+ * + * @param password Plaintext password + * + * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. + */ + + static public final String crypt(String password) { + StringBuffer salt = new StringBuffer(); + java.util.Random randgen = new java.util.Random(); + + /* -- */ + + while (salt.length() < 8) { + int index = (int) (randgen.nextFloat() * SALTCHARS.length()); + salt.append(SALTCHARS.substring(index, index + 1)); + } + + return MD5Crypt.crypt(password, salt.toString()); + } + + /** + *

This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible + * md5-encoded password hash from a plaintext password and a + * salt.

+ * + *

The resulting string will be in the form '$1$<salt>$<hashed mess>

+ * + * @param password Plaintext password + * @param salt A short string to use to randomize md5. May start with $1$, which + * will be ignored. It is explicitly permitted to pass a pre-existing + * MD5Crypt'ed password entry as the salt. crypt() will strip the salt + * chars out properly. + * + * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. + */ + + static public final String crypt(String password, String salt) { + return MD5Crypt.crypt(password, salt, "$1$"); + } + + /** + *

This method generates an Apache MD5 compatible + * md5-encoded password hash from a plaintext password and a + * salt.

+ * + *

The resulting string will be in the form '$apr1$<salt>$<hashed mess>

+ * + * @param password Plaintext password + * + * @return An Apache-compatible md5-hashed password string. + */ + + static public final String apacheCrypt(String password) { + StringBuffer salt = new StringBuffer(); + java.util.Random randgen = new java.util.Random(); + + /* -- */ + + while (salt.length() < 8) { + int index = (int) (randgen.nextFloat() * SALTCHARS.length()); + salt.append(SALTCHARS.substring(index, index + 1)); + } + + return MD5Crypt.apacheCrypt(password, salt.toString()); + } + + /** + *

This method actually generates an Apache MD5 compatible + * md5-encoded password hash from a plaintext password and a + * salt.

+ * + *

The resulting string will be in the form '$apr1$<salt>$<hashed mess>

+ * + * @param password Plaintext password + * @param salt A short string to use to randomize md5. May start with $apr1$, which + * will be ignored. It is explicitly permitted to pass a pre-existing + * MD5Crypt'ed password entry as the salt. crypt() will strip the salt + * chars out properly. + * + * @return An Apache-compatible md5-hashed password string. + */ + + static public final String apacheCrypt(String password, String salt) { + return MD5Crypt.crypt(password, salt, "$apr1$"); + } + + /** + *

This method actually generates md5-encoded password hash from + * a plaintext password, a salt, and a magic string.

+ * + *

There are two magic strings that make sense to use here.. '$1$' is the + * magic string used by the FreeBSD/Linux/OpenBSD MD5Crypt algorithm, and + * '$apr1$' is the magic string used by the Apache MD5Crypt algorithm.

+ * + *

The resulting string will be in the form '<magic><salt>$<hashed mess>

+ * + * @param password Plaintext password @param salt A short string to + * use to randomize md5. May start with the magic string, which + * will be ignored. It is explicitly permitted to pass a + * pre-existing MD5Crypt'ed password entry as the salt. crypt() + * will strip the salt chars out properly. + * + * @return An md5-hashed password string. + */ + + static public final String crypt(String password, String salt, + String magic) { + /* This string is magic for this algorithm. Having it this way, + * we can get get better later on */ + + byte finalState[]; + MD5 ctx, ctx1; + long l; + + /* -- */ + + /* Refine the Salt first */ + + /* If it starts with the magic string, then skip that */ + + if (salt.startsWith(magic)) { + salt = salt.substring(magic.length()); + } + + /* It stops at the first '$', max 8 chars */ + + if (salt.indexOf('$') != -1) { + salt = salt.substring(0, salt.indexOf('$')); + } + + if (salt.length() > 8) { + salt = salt.substring(0, 8); + } + + ctx = new MD5(); + + ctx.Update(password); // The password first, since that is what is most unknown + ctx.Update(magic); // Then our magic string + ctx.Update(salt); // Then the raw salt + + /* Then just as many characters of the MD5(pw,salt,pw) */ + + ctx1 = new MD5(); + ctx1.Update(password); + ctx1.Update(salt); + ctx1.Update(password); + finalState = ctx1.Final(); + + for (int pl = password.length(); pl > 0; pl -= 16) { + ctx.Update(finalState, pl > 16 ? 16 : pl); + } + + /* the original code claimed that finalState was being cleared + to keep dangerous bits out of memory, but doing this is also + required in order to get the right output. */ + + clearbits(finalState); + + /* Then something really weird... */ + + for (int i = password.length(); i != 0; i >>>= 1) { + if ((i & 1) != 0) { + ctx.Update(finalState, 1); + } else { + ctx.Update(password.getBytes(), 1); + } + } + + finalState = ctx.Final(); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + * + * (The above timings from the C version) + */ + + for (int i = 0; i < 1000; i++) { + ctx1 = new MD5(); + + if ((i & 1) != 0) { + ctx1.Update(password); + } else { + ctx1.Update(finalState, 16); + } + + if ((i % 3) != 0) { + ctx1.Update(salt); + } + + if ((i % 7) != 0) { + ctx1.Update(password); + } + + if ((i & 1) != 0) { + ctx1.Update(finalState, 16); + } else { + ctx1.Update(password); + } + + finalState = ctx1.Final(); + } + + /* Now make the output string */ + + StringBuffer result = new StringBuffer(); + + result.append(magic); + result.append(salt); + result.append("$"); + + l = (bytes2u(finalState[0]) << 16) + | (bytes2u(finalState[6]) << 8) + | bytes2u(finalState[12]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[1]) << 16) + | (bytes2u(finalState[7]) << 8) + | bytes2u(finalState[13]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[2]) << 16) + | (bytes2u(finalState[8]) << 8) + | bytes2u(finalState[14]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[3]) << 16) + | (bytes2u(finalState[9]) << 8) + | bytes2u(finalState[15]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[4]) << 16) + | (bytes2u(finalState[10]) << 8) + | bytes2u(finalState[5]); + result.append(to64(l, 4)); + + l = bytes2u(finalState[11]); + result.append(to64(l, 2)); + + /* Don't leave anything around in vm they could use. */ + clearbits(finalState); + + return result.toString(); + } +} + diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java new file mode 100644 index 00000000..9b1cd5e2 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * 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.core.utils; + +import java.text.NumberFormat; + +public class NumberUtil { + public static final String formatNumber(double num) { + NumberFormat formatter = NumberFormat.getNumberInstance(); + formatter.setMinimumFractionDigits(2); + formatter.setMaximumFractionDigits(2); + return formatter.format(num); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java new file mode 100644 index 00000000..6c8b857d --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.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.core.utils; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the result of a command execution in a separate process. Consists of the "exit status" of the process and + * output from the process. The output includes stdout as well as stderr streams + */ +@XmlRootElement +public class ProcessResult { + + public static final int SUCCESS = 0; + private int exitValue; + private String output; + + // Required for JAXB de-serialization + public ProcessResult() { + + } + + public ProcessResult(int exitValue, String output) { + this.exitValue = exitValue; + this.output = output; + } + + public int getExitValue() { + return exitValue; + } + + public void setExitValue(int exitValue) { + this.exitValue = exitValue; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + public boolean isSuccess() { + return exitValue == SUCCESS; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java new file mode 100644 index 00000000..507c6d95 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * 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.core.utils; + +import static com.gluster.storage.management.core.constants.CoreConstants.NEWLINE; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; + +/** + * Utility class for creating processes (foreground/background) with given + * command and checking the output/exit status + */ +public class ProcessUtil { + + private static final ProcessUtil instance = new ProcessUtil(); + + public ProcessResult executeCommand(List command) { + return executeCommand(true, command); + } + + /** + * Executes given command in a separate process in FOREGROUND + * @param command + * @return {@link ProcessResult} object + */ + public ProcessResult executeCommand(String... command) { + ArrayList commandList = new ArrayList(); + for (String part : command) { + commandList.add(part); + } + return executeCommand(commandList); + } + + /** + * Executes given command in foreground/background + * @param runInForeground Boolean flag indicating whether the command should + * be executed in foreground + * @param command + * @return {@link ProcessResult} object + */ + public ProcessResult executeCommand(boolean runInForeground, List command) { + StringBuilder output = new StringBuilder(); + try { + Process process = new ProcessBuilder(command).redirectErrorStream(true).start(); + + if (runInForeground) { + process.waitFor(); // Wait for process to finish + + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + + while ((line = br.readLine()) != null) { + output.append(line); + output.append(NEWLINE); + } + } else { + output.append("Command ["); + output.append(command); + output.append("] triggerred in background."); + } + + return new ProcessResult(process.exitValue(), output.toString()); + } catch (Throwable e) { + throw new GlusterRuntimeException("Exception while executing command [" + command + "]", e); + } + } + + public static void main(String args[]) { + ProcessResult result = new ProcessUtil().executeCommand("ls", "-lrt", "/"); + System.out.println(result.getExitValue()); + System.out.println(result.getOutput()); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java new file mode 100644 index 00000000..1c4e6893 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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.core.utils; + +public class StringUtil { + public static boolean filterString(String sourceString, + String filterString, boolean caseSensitive) { + return caseSensitive ? sourceString.contains(filterString) + : sourceString.toLowerCase().contains( + filterString.toLowerCase()); + } +} diff --git a/src/com.gluster.storage.management.gui.feature.webstart/.project b/src/com.gluster.storage.management.gui.feature.webstart/.project new file mode 100644 index 00000000..03adbe4c --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/.project @@ -0,0 +1,17 @@ + + + com.gluster.storage.management.gui.feature.webstart + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex b/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex new file mode 100644 index 00000000..252a5e15 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build.properties b/src/com.gluster.storage.management.gui.feature.webstart/build.properties new file mode 100644 index 00000000..322a3114 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/build.properties @@ -0,0 +1,2 @@ +#bin.includes = feature.xml +root=rootfiles diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore b/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore new file mode 100644 index 00000000..ee3bc3a9 Binary files /dev/null and b/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore differ diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant b/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant new file mode 100644 index 00000000..e7baaa03 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gui.feature.webstart/feature.xml b/src/com.gluster.storage.management.gui.feature.webstart/feature.xml new file mode 100644 index 00000000..0c7142fe --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/feature.xml @@ -0,0 +1,229 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp new file mode 100644 index 00000000..8828736c --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp @@ -0,0 +1,38 @@ + + + + Gluster Management Console + Gluster Inc. + + Gluster Management Console + + + + + + + + + + + + + + + + + + + -nosplash + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html new file mode 100644 index 00000000..70f47279 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html @@ -0,0 +1,8 @@ + + +Gluster Storage Platform + + +Gluster Storage Platform + + diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp new file mode 100644 index 00000000..059c28f9 Binary files /dev/null and b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp differ diff --git a/src/com.gluster.storage.management.gui.feature/.project b/src/com.gluster.storage.management.gui.feature/.project new file mode 100644 index 00000000..c93780b5 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/.project @@ -0,0 +1,17 @@ + + + com.gluster.storage.management.gui.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/src/com.gluster.storage.management.gui.feature/build.properties b/src/com.gluster.storage.management.gui.feature/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/src/com.gluster.storage.management.gui.feature/feature.xml b/src/com.gluster.storage.management.gui.feature/feature.xml new file mode 100644 index 00000000..2448b3cc --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/feature.xml @@ -0,0 +1,775 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gui/.classpath b/src/com.gluster.storage.management.gui/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/src/com.gluster.storage.management.gui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/com.gluster.storage.management.gui/.project b/src/com.gluster.storage.management.gui/.project new file mode 100644 index 00000000..84ab78e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/.project @@ -0,0 +1,28 @@ + + + com.gluster.storage.management.gui + + + + + + 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.gui/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.gui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..abf7cf5a --- /dev/null +++ b/src/com.gluster.storage.management.gui/.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.gui/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..2e59c854 --- /dev/null +++ b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF @@ -0,0 +1,27 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: glustersp-gui +Bundle-SymbolicName: com.gluster.storage.management.gui;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: com.gluster.storage.management.gui.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 +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: . diff --git a/src/com.gluster.storage.management.gui/build.properties b/src/com.gluster.storage.management.gui/build.properties new file mode 100644 index 00000000..47ced62b --- /dev/null +++ b/src/com.gluster.storage.management.gui/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.gui/icons/arrow-down.png b/src/com.gluster.storage.management.gui/icons/arrow-down.png new file mode 100644 index 00000000..7f23e3f4 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/arrow-down.png differ diff --git a/src/com.gluster.storage.management.gui/icons/arrow-up.png b/src/com.gluster.storage.management.gui/icons/arrow-up.png new file mode 100644 index 00000000..b8ad3050 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/arrow-up.png differ diff --git a/src/com.gluster.storage.management.gui/icons/cluster.png b/src/com.gluster.storage.management.gui/icons/cluster.png new file mode 100644 index 00000000..c9348a21 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/cluster.png differ diff --git a/src/com.gluster.storage.management.gui/icons/disk-migrate.png b/src/com.gluster.storage.management.gui/icons/disk-migrate.png new file mode 100644 index 00000000..2de348dc Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/disk-migrate.png differ diff --git a/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png b/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png new file mode 100644 index 00000000..b982d118 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png differ diff --git a/src/com.gluster.storage.management.gui/icons/disk.png b/src/com.gluster.storage.management.gui/icons/disk.png new file mode 100644 index 00000000..99d532e8 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/disk.png differ diff --git a/src/com.gluster.storage.management.gui/icons/disks.png b/src/com.gluster.storage.management.gui/icons/disks.png new file mode 100644 index 00000000..fc5a52f5 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/disks.png differ diff --git a/src/com.gluster.storage.management.gui/icons/folder.png b/src/com.gluster.storage.management.gui/icons/folder.png new file mode 100644 index 00000000..784e8fa4 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/folder.png differ diff --git a/src/com.gluster.storage.management.gui/icons/gluster_icon.png b/src/com.gluster.storage.management.gui/icons/gluster_icon.png new file mode 100644 index 00000000..f92e472d Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/gluster_icon.png differ diff --git a/src/com.gluster.storage.management.gui/icons/group.png b/src/com.gluster.storage.management.gui/icons/group.png new file mode 100644 index 00000000..7fb4e1f1 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/group.png differ diff --git a/src/com.gluster.storage.management.gui/icons/gsn.png b/src/com.gluster.storage.management.gui/icons/gsn.png new file mode 100644 index 00000000..68f21d30 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/gsn.png differ diff --git a/src/com.gluster.storage.management.gui/icons/logs.png b/src/com.gluster.storage.management.gui/icons/logs.png new file mode 100644 index 00000000..c8449f98 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/logs.png differ diff --git a/src/com.gluster.storage.management.gui/icons/mail.ico b/src/com.gluster.storage.management.gui/icons/mail.ico new file mode 100644 index 00000000..b0000611 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/mail.ico differ diff --git a/src/com.gluster.storage.management.gui/icons/minus-white.png b/src/com.gluster.storage.management.gui/icons/minus-white.png new file mode 100644 index 00000000..8efd5d33 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/minus-white.png differ diff --git a/src/com.gluster.storage.management.gui/icons/network-interface.png b/src/com.gluster.storage.management.gui/icons/network-interface.png new file mode 100644 index 00000000..24ca7370 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/network-interface.png differ diff --git a/src/com.gluster.storage.management.gui/icons/network-interfaces.png b/src/com.gluster.storage.management.gui/icons/network-interfaces.png new file mode 100644 index 00000000..752968bb Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/network-interfaces.png differ diff --git a/src/com.gluster.storage.management.gui/icons/network-interfaces1.png b/src/com.gluster.storage.management.gui/icons/network-interfaces1.png new file mode 100644 index 00000000..af438028 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/network-interfaces1.png differ diff --git a/src/com.gluster.storage.management.gui/icons/plus-white.png b/src/com.gluster.storage.management.gui/icons/plus-white.png new file mode 100644 index 00000000..c765946e Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/plus-white.png differ diff --git a/src/com.gluster.storage.management.gui/icons/preferences.png b/src/com.gluster.storage.management.gui/icons/preferences.png new file mode 100644 index 00000000..7b93eb05 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/preferences.png differ diff --git a/src/com.gluster.storage.management.gui/icons/progress-bar.png b/src/com.gluster.storage.management.gui/icons/progress-bar.png new file mode 100644 index 00000000..c7db00ae Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/progress-bar.png differ diff --git a/src/com.gluster.storage.management.gui/icons/question.png b/src/com.gluster.storage.management.gui/icons/question.png new file mode 100644 index 00000000..30a47032 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/question.png differ diff --git a/src/com.gluster.storage.management.gui/icons/sample.gif b/src/com.gluster.storage.management.gui/icons/sample.gif new file mode 100644 index 00000000..34fb3c9d Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/sample.gif differ diff --git a/src/com.gluster.storage.management.gui/icons/sample.icns b/src/com.gluster.storage.management.gui/icons/sample.icns new file mode 100644 index 00000000..1e92ccce Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/sample.icns differ diff --git a/src/com.gluster.storage.management.gui/icons/sample2.gif b/src/com.gluster.storage.management.gui/icons/sample2.gif new file mode 100644 index 00000000..252d7ebc Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/sample2.gif differ diff --git a/src/com.gluster.storage.management.gui/icons/sample3.gif b/src/com.gluster.storage.management.gui/icons/sample3.gif new file mode 100644 index 00000000..b949ac94 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/sample3.gif differ diff --git a/src/com.gluster.storage.management.gui/icons/search.png b/src/com.gluster.storage.management.gui/icons/search.png new file mode 100644 index 00000000..b4b23129 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/search.png differ diff --git a/src/com.gluster.storage.management.gui/icons/server-add-big.png b/src/com.gluster.storage.management.gui/icons/server-add-big.png new file mode 100644 index 00000000..d96b8175 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/server-add-big.png differ diff --git a/src/com.gluster.storage.management.gui/icons/server-add.png b/src/com.gluster.storage.management.gui/icons/server-add.png new file mode 100644 index 00000000..db604ee3 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/server-add.png differ diff --git a/src/com.gluster.storage.management.gui/icons/server-remove.png b/src/com.gluster.storage.management.gui/icons/server-remove.png new file mode 100644 index 00000000..5e9b2683 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/server-remove.png differ diff --git a/src/com.gluster.storage.management.gui/icons/server.png b/src/com.gluster.storage.management.gui/icons/server.png new file mode 100644 index 00000000..9bc37dce Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/server.png differ diff --git a/src/com.gluster.storage.management.gui/icons/servers.png b/src/com.gluster.storage.management.gui/icons/servers.png new file mode 100644 index 00000000..b18a74d9 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/servers.png differ diff --git a/src/com.gluster.storage.management.gui/icons/star-small.png b/src/com.gluster.storage.management.gui/icons/star-small.png new file mode 100644 index 00000000..fef14263 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/star-small.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-offline-circle.png b/src/com.gluster.storage.management.gui/icons/status-offline-circle.png new file mode 100644 index 00000000..20d6f5ea Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-offline-circle.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-offline-small.png b/src/com.gluster.storage.management.gui/icons/status-offline-small.png new file mode 100644 index 00000000..39d47690 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-offline-small.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-offline.png b/src/com.gluster.storage.management.gui/icons/status-offline.png new file mode 100644 index 00000000..6b9fa6dd Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-offline.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-online-circle.png b/src/com.gluster.storage.management.gui/icons/status-online-circle.png new file mode 100644 index 00000000..210b1a6c Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-online-circle.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-online-small.png b/src/com.gluster.storage.management.gui/icons/status-online-small.png new file mode 100644 index 00000000..8e87f2e5 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-online-small.png differ diff --git a/src/com.gluster.storage.management.gui/icons/status-online.png b/src/com.gluster.storage.management.gui/icons/status-online.png new file mode 100644 index 00000000..2414885b Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/status-online.png differ diff --git a/src/com.gluster.storage.management.gui/icons/stop.png b/src/com.gluster.storage.management.gui/icons/stop.png new file mode 100644 index 00000000..0cfd5859 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/stop.png differ diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png b/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png new file mode 100644 index 00000000..3c961711 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png differ diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png b/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png new file mode 100644 index 00000000..ba447358 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png differ diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box.png b/src/com.gluster.storage.management.gui/icons/ui-check-box.png new file mode 100644 index 00000000..07f3522a Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/ui-check-box.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-create-big.png b/src/com.gluster.storage.management.gui/icons/volume-create-big.png new file mode 100644 index 00000000..231bae5b Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-create-big.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-create.png b/src/com.gluster.storage.management.gui/icons/volume-create.png new file mode 100644 index 00000000..9c8a9da4 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-create.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-delete.png b/src/com.gluster.storage.management.gui/icons/volume-delete.png new file mode 100644 index 00000000..86f7fbc2 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-delete.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-edit.png b/src/com.gluster.storage.management.gui/icons/volume-edit.png new file mode 100644 index 00000000..291bfc76 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-edit.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-rebalance.png b/src/com.gluster.storage.management.gui/icons/volume-rebalance.png new file mode 100644 index 00000000..e213cd5b Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-rebalance.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-start.png b/src/com.gluster.storage.management.gui/icons/volume-start.png new file mode 100644 index 00000000..aace63ad Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-start.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-stop-1.png b/src/com.gluster.storage.management.gui/icons/volume-stop-1.png new file mode 100644 index 00000000..0cfd5859 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-stop-1.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume-stop.png b/src/com.gluster.storage.management.gui/icons/volume-stop.png new file mode 100644 index 00000000..7af3a518 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume-stop.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume.png b/src/com.gluster.storage.management.gui/icons/volume.png new file mode 100644 index 00000000..46b7564a Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volume1.png b/src/com.gluster.storage.management.gui/icons/volume1.png new file mode 100644 index 00000000..5e23dbc8 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volume1.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volumes.png b/src/com.gluster.storage.management.gui/icons/volumes.png new file mode 100644 index 00000000..80dfa195 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volumes.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volumes1.png b/src/com.gluster.storage.management.gui/icons/volumes1.png new file mode 100644 index 00000000..448e46fd Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volumes1.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volumes2.png b/src/com.gluster.storage.management.gui/icons/volumes2.png new file mode 100644 index 00000000..0905f933 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volumes2.png differ diff --git a/src/com.gluster.storage.management.gui/icons/volumes3.png b/src/com.gluster.storage.management.gui/icons/volumes3.png new file mode 100644 index 00000000..7e90d397 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/volumes3.png differ diff --git a/src/com.gluster.storage.management.gui/icons/world.png b/src/com.gluster.storage.management.gui/icons/world.png new file mode 100644 index 00000000..68f21d30 Binary files /dev/null and b/src/com.gluster.storage.management.gui/icons/world.png differ diff --git a/src/com.gluster.storage.management.gui/images/gauge.png b/src/com.gluster.storage.management.gui/images/gauge.png new file mode 100644 index 00000000..6f5764ea Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/gauge.png differ diff --git a/src/com.gluster.storage.management.gui/images/gauge_small.png b/src/com.gluster.storage.management.gui/images/gauge_small.png new file mode 100644 index 00000000..71e424fe Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/gauge_small.png differ diff --git a/src/com.gluster.storage.management.gui/images/progress_image_empty.png b/src/com.gluster.storage.management.gui/images/progress_image_empty.png new file mode 100644 index 00000000..590097ad Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/progress_image_empty.png differ diff --git a/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png b/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png new file mode 100644 index 00000000..97704230 Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png differ diff --git a/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png b/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png new file mode 100644 index 00000000..ae4e3c69 Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png differ diff --git a/src/com.gluster.storage.management.gui/images/progress_image_left.png b/src/com.gluster.storage.management.gui/images/progress_image_left.png new file mode 100644 index 00000000..97704230 Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/progress_image_left.png differ diff --git a/src/com.gluster.storage.management.gui/images/progress_image_right.png b/src/com.gluster.storage.management.gui/images/progress_image_right.png new file mode 100644 index 00000000..97704230 Binary files /dev/null and b/src/com.gluster.storage.management.gui/images/progress_image_right.png differ diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml new file mode 100644 index 00000000..f5ab3db7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -0,0 +1,1175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gui/preferences.ini b/src/com.gluster.storage.management.gui/preferences.ini new file mode 100644 index 00000000..91228592 --- /dev/null +++ b/src/com.gluster.storage.management.gui/preferences.ini @@ -0,0 +1 @@ +org.eclipse.ui/KEY_CONFIGURATION_ID = com.gluster.storage.management.gui.KeyConfig \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/splash.bmp b/src/com.gluster.storage.management.gui/splash.bmp new file mode 100644 index 00000000..059c28f9 Binary files /dev/null and b/src/com.gluster.storage.management.gui/splash.bmp differ diff --git a/src/com.gluster.storage.management.gui/splash/gluster_about.jpg b/src/com.gluster.storage.management.gui/splash/gluster_about.jpg new file mode 100644 index 00000000..242fa560 Binary files /dev/null and b/src/com.gluster.storage.management.gui/splash/gluster_about.jpg differ diff --git a/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp b/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp new file mode 100644 index 00000000..2de2897f Binary files /dev/null and b/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp differ diff --git a/src/com.gluster.storage.management.gui/splash/splash-dialog.png b/src/com.gluster.storage.management.gui/splash/splash-dialog.png new file mode 100644 index 00000000..789eafb0 Binary files /dev/null and b/src/com.gluster.storage.management.gui/splash/splash-dialog.png differ diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java new file mode 100644 index 00000000..3fa5bcf0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +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.gui"; //$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.gui/src/com/gluster/storage/management/gui/Application.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.java new file mode 100644 index 00000000..50dbd314 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.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.gui; + +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.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.core.model.Entity; +import com.gluster.storage.management.gui.login.LoginDialog; + +/** + * 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.gui"; + private static Application instance; + private List entityListeners = Collections.synchronizedList(new ArrayList()); + + public Application() { + instance = this; + } + + public static Application getApplication() { + return instance; + } + + 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) { + 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(); + } + } + + /* + * (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.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java new file mode 100644 index 00000000..3f6cb7d5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.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.gui; + +import org.eclipse.jface.action.Action; +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.gui.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 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)); + register(aboutAction); + } + + 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(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.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java new file mode 100644 index 00000000..07e20466 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.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.gui; + +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +/** + * This workbench advisor creates the window advisor, and specifies + * the perspective id for the initial window. + */ +public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { + + 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 + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java new file mode 100644 index 00000000..722821f7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.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.gui; + +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.gui.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()); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java new file mode 100644 index 00000000..92553797 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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.gui; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage.DISK_TABLE_COLUMN_INDICES; + +public class DiskTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + if (columnIndex == DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + DISK_STATUS status = disk.getStatus(); + switch (status) { + case READY: + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + case OFFLINE: + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.WORK_IN_PROGRESS); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + private String getDiskSpaceInUse(Disk disk) { + if (disk.isReady()) { + return NumberUtil.formatNumber(disk.getSpaceInUse()); + } else { + return "NA"; + } + } + + private String getDiskSpace(Disk disk) { + if (disk.isOffline()) { + return "NA"; + } else { + return NumberUtil.formatNumber(disk.getSpace()); + } + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? getDiskSpace(disk) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? getDiskSpaceInUse(disk) + : columnIndex == DISK_TABLE_COLUMN_INDICES.STATUS.ordinal() ? disk.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java new file mode 100644 index 00000000..26848eef --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +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.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java new file mode 100644 index 00000000..3fc2dfa0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.gui; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.GlusterServersPage.GLUSTER_SERVER_TABLE_COLUMN_INDICES; + +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); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + } + } + + 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() ? "" + server.getTotalMemory() + //: columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE.ordinal() ? "" + server.getMemoryInUse() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE.ordinal() ? NumberUtil.formatNumber(server.getTotalDiskSpace()) + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES.ordinal() ? server.getIpAddressesAsString() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java new file mode 100644 index 00000000..d9cb434c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +/** + * 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.gui.open"; + public static final String CMD_OPEN_MESSAGE = "com.gluster.storage.management.gui.openMessage"; + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java new file mode 100644 index 00000000..98dfbe9a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +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.gui/src/com/gluster/storage/management/gui/IImageKeys.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java new file mode 100644 index 00000000..fd5972c5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.gui; + +public interface IImageKeys { + public static final String CLUSTER = "icons/cluster.png"; + public static final String VOLUMES = "icons/volumes.png"; + public static final String SERVERS = "icons/servers.png"; + public static final String VOLUME = "icons/volume.png"; + public static final String SERVER = "icons/server.png"; + public static final String GSN = "icons/gsn.png"; + public static final String SETTINGS = "icons/settings.png"; + public static final String ADD = "icons/plus-white.png"; + public static final String REMOVE = "icons/minus-white.png"; + public static final String CREATE_VOLUME = "icons/volume-create.png"; + public static final String CREATE_VOLUME_BIG = "icons/volume-create-big.png"; + public static final String REMOVE_VOLUME = "icons/volume-delete.png"; + public static final String ADD_SERVER = "icons/server-add.png"; + public static final String ADD_SERVER_BIG = "icons/server-add-big.png"; + public static final String REMOVE_SERVER = "icons/server-remove.png"; + public static final String HELP = "icons/question.png"; + public static final String STATUS_OFFLINE = "icons/status-offline.png"; + public static final String STATUS_ONLINE = "icons/status-online.png"; + public static final String STATUS_CANCELLED = "icons/status-offline.png"; + public static final String STATUS_SUCCESS = "icons/status-online.png"; + public static final String WORK_IN_PROGRESS = "icons/progress-bar.png"; + public static final String CHECKBOX_UNCHECKED = "icons/ui-check-box-uncheck.png"; + public static final String CHECKBOX_CHECKED = "icons/ui-check-box.png"; + public static final String DISK_UNINITIALIZED = "icons/disk-uninitialized.png"; + public static final String SEARCH = "icons/search.png"; + public static final String ARROW_UP = "icons/arrow-up.png"; + public static final String ARROW_DOWN = "icons/arrow-down.png"; + + public static final String OVERLAY_OFFLINE = "icons/status-offline-small.png"; + public static final String OVERLAY_ONLINE = "icons/status-online-small.png"; + public static final String OVERLAY_STAR = "icons/star-small.png"; + + public static final String SPLASH_IMAGE = "splash.bmp"; + public static final String DIALOG_SPLASH_IMAGE = "splash/splash-dialog.bmp"; + + public static final String PROGRESS_BAR_LEFT = "images/progress_image_left.png"; + public static final String PROGRESS_BAR_RIGHT = "images/progress_image_right.png"; + public static final String PROGRESS_BAR_FILLED = "images/progress_image_filled_safe.png"; + public static final String PROGRESS_BAR_EMPTY = "images/progress_image_empty.png"; + public static final String GAUGE_SMALL = "images/gauge_small.png"; +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java new file mode 100644 index 00000000..d7b700d4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.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.gui; + + +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.gui.views.details.tabcreators.GlusterServerTabCreator.NETWORK_INTERFACE_TABLE_COLUMN_INDICES; + +public class NetworkInterfaceTableLabelProvider extends TableLabelProviderAdapter { + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof NetworkInterface)) { + return null; + } + + NetworkInterface networkInterface = (NetworkInterface) element; + return (columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE.ordinal() ? networkInterface.getName() + : 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() + // : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED.ordinal() ? (networkInterface.isPreferred() ? "Yes" : "No") + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java new file mode 100644 index 00000000..3f8702ce --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.gui; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +import com.gluster.storage.management.gui.views.DetailsView; +import com.gluster.storage.management.gui.views.NavigationView; + +public class Perspective implements IPerspectiveFactory { + + /** + * The ID of the perspective as specified in the extension. + */ + public static final String ID = "com.gluster.storage.management.gui.perspective"; + + 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.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java new file mode 100644 index 00000000..cd5fab62 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.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.gui; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage.SERVER_DISK_TABLE_COLUMN_INDICES; + +public class ServerDiskTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + if (columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + DISK_STATUS status = disk.getStatus(); + switch (status) { + case READY: + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + case OFFLINE: + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.WORK_IN_PROGRESS); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + private String getDiskSpaceInUse(Disk disk) { + if(disk.isReady()) { + return NumberUtil.formatNumber(disk.getSpaceInUse()); + } else { + return "NA"; + } + } + + private String getDiskSpace(Disk disk) { + if(disk.isOffline()) { + return "NA"; + } else { + return NumberUtil.formatNumber(disk.getSpace()); + } + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + + Disk disk = (Disk) element; + return (columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? getDiskSpace(disk) + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? getDiskSpaceInUse(disk) + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal() ? disk.getStatusStr() + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java new file mode 100644 index 00000000..6ec446cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.gui; + + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage.SERVER_TABLE_COLUMN_INDICES; + +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()) +// : 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.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java new file mode 100644 index 00000000..95d6fde4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +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.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java new file mode 100644 index 00000000..399cdc65 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.gui; + + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.LogMessage; +import com.gluster.storage.management.core.utils.DateUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage.LOG_TABLE_COLUMN_INDICES; + +public class VolumeLogTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + private String getFormattedDiskName(Disk disk) { + return disk.getServerName() + ":" + disk.getName(); + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof LogMessage)) { + return null; + } + + LogMessage logMessage = (LogMessage) 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.DISK.ordinal() ? getFormattedDiskName(logMessage.getDisk()) + : 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.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java new file mode 100644 index 00000000..cf1ceaf7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.gui; + +import java.util.Map.Entry; + +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage.OPTIONS_TABLE_COLUMN_INDICES; + +public class VolumeOptionsTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Entry)) { + return null; + } + + Entry entry = (Entry) element; + String key = entry.getKey(); + String value = entry.getValue(); + return (columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal() ? key + : columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE.ordinal() ? value + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java new file mode 100644 index 00000000..b0f0c8d0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui; + +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.VolumesPage.VOLUME_TABLE_COLUMN_INDICES; + +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); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + } + } + + 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_DISKS.ordinal() ? "" + volume.getNumOfDisks() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS.ordinal() ? volume.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java new file mode 100644 index 00000000..4aa387bc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +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. + */ +public abstract class AbstractActionDelegate implements IWorkbenchWindowActionDelegate { + protected IWorkbenchWindow window; + protected Entity selectedEntity; + + @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; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java new file mode 100644 index 00000000..7957b6f0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +public class AddServerAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + GlusterServersClient glusterServersClient = new GlusterServersClient(modelManager.getSecurityToken()); + Server server = (Server) selectedEntity; + GlusterServerResponse response = glusterServersClient.addServer(server); + if (response.getStatus().isSuccess()) { + modelManager.removeDiscoveredServer(server); + modelManager.addGlusterServer(response.getGlusterServer()); + new MessageDialog(Display.getDefault().getActiveShell(), "Add Server", null, "Server [" + server.getName() + + "] added successfully!", MessageDialog.INFORMATION, new String[] { "OK" }, 0).open(); + } else { + new MessageDialog(Display.getDefault().getActiveShell(), "Add Server", null, "Server [" + server.getName() + + " could not be added to cluster! Error: [" + response.getStatus().getMessage() + "]", + MessageDialog.ERROR, new String[] { "OK" }, 0).open(); + } + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } + + @SuppressWarnings("rawtypes") + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity != null && selectedEntity instanceof Entity) { + action.setEnabled(true); + if (selectedEntity instanceof EntityGroup && ((EntityGroup) selectedEntity).getEntityType() == Volume.class) { + action.setEnabled(false); + } + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java new file mode 100644 index 00000000..266db0af --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.CreateVolumeWizard; + +public class CreateVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + CreateVolumeWizard wizard = new CreateVolumeWizard(); + + WizardDialog dialog = new WizardDialog(window.getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(500, 550); + dialog.open(); + } + }); + } + + @Override + public void dispose() { + window = null; + } + + @SuppressWarnings("rawtypes") + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + action.setEnabled(true); + if(selectedEntity instanceof EntityGroup && ((EntityGroup)selectedEntity).getEntityType() != Volume.class) { + // selected entity is either "servers" or "discovered servers". + action.setEnabled(false); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java new file mode 100644 index 00000000..b4b92c31 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; + +public class DeleteVolumeAction extends AbstractActionDelegate { + @Override + public void run(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.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java new file mode 100644 index 00000000..6f3fdf24 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.actions; + +import org.eclipse.jface.action.IAction; + +public class EditVolumeAction extends AbstractActionDelegate { + @Override + public void run(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.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java new file mode 100644 index 00000000..6c54bae8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.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.gui.actions; + +public interface IActionSetIDs { + public static final String ACTION_SET_CLUSTER = "com.gluster.storage.management.gui.actionsets.gluster"; + public static final String ACTION_SET_VOLUMES = "com.gluster.storage.management.gui.actionsets.volumes"; + public static final String ACTION_SET_VOLUME = "com.gluster.storage.management.gui.actionsets.volume"; + public static final String ACTION_SET_DISKS = "com.gluster.storage.management.gui.actionsets.disks"; + public static final String ACTION_SET_DISK = "com.gluster.storage.management.gui.actionsets.disk"; + public static final String ACTION_SET_GLUSTER_SERVERS = "com.gluster.storage.management.gui.actionsets.glusterservers"; + public static final String ACTION_SET_GLUSTER_SERVER = "com.gluster.storage.management.gui.actionsets.glusterserver"; + public static final String ACTION_SET_DISCOVERED_SERVERS = "com.gluster.storage.management.gui.actionsets.serversdiscovered"; + public static final String ACTION_SET_DISCOVERED_SERVER = "com.gluster.storage.management.gui.actionsets.serverdiscovered"; + + public static final String ACTION_SET_EDIT = "com.gluster.storage.management.gui.actionsets.edit"; +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java new file mode 100644 index 00000000..75be4e6b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.MigrateDiskWizard; + +public class MigrateDiskAction extends AbstractActionDelegate { + private Volume volume; + private Disk disk; + + @Override + public void run(IAction action) { +// MigrateDiskDialog dialog = new MigrateDiskDialog(window.getShell(), volume, disk); +// dialog.create(); +// dialog.open(); + MigrateDiskWizard wizard = new MigrateDiskWizard(volume, disk); + + 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); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + } + + action.setEnabled(false); + if (selectedEntity instanceof Disk) { + disk = (Disk) selectedEntity; + action.setEnabled(((StructuredSelection) selection).size() == 1); + } + } + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java new file mode 100644 index 00000000..97f1c79b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.actions; + +import org.eclipse.jface.action.IAction; + +public class MigrateVolumeAction extends AbstractActionDelegate { + @Override + public void run(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.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java new file mode 100644 index 00000000..f6fd88e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.actions.ActionFactory; + +public class PreferencesAction extends AbstractActionDelegate { + + @Override + public void dispose() { + + } + + @Override + public void run(IAction action) { + ActionFactory.PREFERENCES.create(window).run(); + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java new file mode 100644 index 00000000..65227b0b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; + +public class RebalanceVolumeAction extends AbstractActionDelegate { + @Override + public void run(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.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java new file mode 100644 index 00000000..d5d42363 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +public class RemoveServerAction extends AbstractActionDelegate { + @Override + public void run(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.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java new file mode 100644 index 00000000..cc0fbe94 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class StartVolumeAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void run(final IAction action) { + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + return; // Volume already online. Don't do anything. + } + + VolumesClient client = new VolumesClient(modelManager.getSecurityToken()); + final Status status = client.startVolume(volume.getName()); + final String actionDesc = action.getDescription(); + final Display display = Display.getDefault(); + display.asyncExec(new Runnable() { + + @Override + public void run() { + if (status.isSuccess()) { + new MessageDialog(display.getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] started successfully!", MessageDialog.INFORMATION, + new String[] { "OK" }, 0).open(); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.ONLINE); + } else { + new MessageDialog(display.getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] could not be started! Error: [" + status + "]", + MessageDialog.ERROR, new String[] { "OK" }, 0).open(); + } + } + }); + } + + @Override + public void dispose() { + + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.gui.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction + * , org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + action.setEnabled(volume.getStatus() == VOLUME_STATUS.OFFLINE); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java new file mode 100644 index 00000000..a89782f9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * 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.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class StopVolumeAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void run(IAction action) { + if(volume.getStatus() == VOLUME_STATUS.OFFLINE) { + return; // Volume already offline. Don't do anything. + } + + VolumesClient client = new VolumesClient(modelManager.getSecurityToken()); + final Status status = client.stopVolume(volume.getName()); + final String actionDesc = action.getDescription(); + final Display display = Display.getDefault(); + + display.asyncExec(new Runnable() { + + @Override + public void run() { + if (status.isSuccess()) { + new MessageDialog(Display.getCurrent().getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] stopped successfully!", MessageDialog.INFORMATION, new String[] { "OK" }, 0) + .open(); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + } else { + new MessageDialog(Display.getCurrent().getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] could not be stopped! Error: [" + status + "]", MessageDialog.ERROR, + new String[] { "OK" }, 0).open(); + } + } + }); + } + + @Override + public void dispose() { + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + action.setEnabled(volume.getStatus() == VOLUME_STATUS.ONLINE); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java new file mode 100644 index 00000000..e1fe0f14 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.gui.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.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.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java new file mode 100644 index 00000000..80811226 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.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.gui.dialogs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +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.core.model.Disk; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; +import com.gluster.storage.management.gui.utils.EntityViewerFilter; +import com.gluster.storage.management.gui.utils.GUIHelper; +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 CreateVolumeDisksPage extends Composite { + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_USED + } + + private static final String[] DISK_TABLE_COLUMNS_NAMES = { "Server", "Disk", "Space (GB)", "Used 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 chosenDisks = new ArrayList(); + + private IRemovableContentProvider chosenDisksContentProvider; + + private Button btnUp; + + private Button btnDown; + + public CreateVolumeDisksPage(final Composite parent, int style, List allDisks, List selectedDisks) { + super(parent, style); + + createPage(allDisks, selectedDisks); + + parent.layout(); + } + + private TableLabelProviderAdapter getDiskLabelProvider() { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? NumberUtil + .formatNumber(disk.getSpace()) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_USED.ordinal() ? NumberUtil + .formatNumber(disk.getSpaceInUse()) : "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 allDisks, List selectedDisks) { + setupPageLayout(); + + filterText = guiHelper.createFilterText(this); + new Label(this, SWT.NONE); + + createDualTableViewer(allDisks, selectedDisks); + 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)); + btnUp.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + chosenDisks = getChosenDisks(); + List selectedDisks = getSelectedChosenDisks(); + + chosenDisksContentProvider.removeElements(chosenDisks); + for(Disk disk : selectedDisks) { + int index = chosenDisks.indexOf(disk); + Disk diskAbove = chosenDisks.get(index - 1); + chosenDisks.set(index - 1, disk); + chosenDisks.set(index, diskAbove); + } + chosenDisksContentProvider.addElements(chosenDisks); + 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)); + btnDown.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + + chosenDisks = getChosenDisks(); + List selectedDisks = getSelectedChosenDisks(); + + chosenDisksContentProvider.removeElements(chosenDisks); + for(Disk disk : selectedDisks) { + int index = chosenDisks.indexOf(disk); + Disk diskBelow = chosenDisks.get(index + 1); + chosenDisks.set(index + 1, disk); + chosenDisks.set(index, diskBelow); + } + chosenDisksContentProvider.addElements(chosenDisks); + dualTableViewer.refreshChosenViewer(); + updateButtons(); + + } + }); + } + + private List getSelectedChosenDisks() { + TableItem[] selectedItems = dualTableViewer.getChosenTable().getSelection(); + List selectedDisks = new ArrayList(); + for (TableItem item : selectedItems) { + selectedDisks.add((Disk)item.getData()); + } + return selectedDisks; + } + + 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 allDisks, List selectedDisks) { + TableColumnData[] columnData = createColumnData(); + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(); + + dualTableViewer = new CustomTableDualListComposite(this, SWT.NONE, columnData, columnData); + + dualTableViewer.setViewerLabels("Available:", "Chosen:"); + + dualTableViewer.setAvailableTableLinesVisible(false); + dualTableViewer.setAvailableTableHeaderVisible(true); + dualTableViewer.setAvailableContentProvider(new RemovableContentProvider(getAvailableDisks(allDisks, + selectedDisks))); + dualTableViewer.setAvailableLabelProvider(diskLabelProvider); + + dualTableViewer.setChosenTableLinesVisible(true); + dualTableViewer.setChosenTableHeaderVisible(true); + + chosenDisksContentProvider = new RemovableContentProvider(selectedDisks); + dualTableViewer.setChosenContentProvider(chosenDisksContentProvider); + 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 selectedChosenDisks = getSelectedChosenDisks(); + List chosenDisks = getChosenDisks(); + for(Disk disk : selectedChosenDisks) { + int index = chosenDisks.indexOf(disk); + if(index == 0) { + btnUp.setEnabled(false); + } + if(index == chosenDisks.size() - 1) { + btnDown.setEnabled(false); + } + } + } + + /** + * @param allDisks + * @param selectedDisks + * @return + */ + private List getAvailableDisks(List allDisks, List selectedDisks) { + List availableDisks = new ArrayList(); + for (Disk disk : allDisks) { + if (!selectedDisks.contains(disk)) { + availableDisks.add(disk); + } + } + return availableDisks; + } + + private TableColumnData[] createColumnData() { + DISK_TABLE_COLUMN_INDICES[] columns = DISK_TABLE_COLUMN_INDICES.values(); + TableColumnData[] columnData = new TableColumnData[columns.length]; + + for (DISK_TABLE_COLUMN_INDICES column : columns) { + int 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 getChosenDisks() { + Object[] disksArr = (Object[]) chosenDisksContentProvider.getElements(dualTableViewer); + if (disksArr != null) { + List disks = new ArrayList(); + for (Object disk : disksArr) { + disks.add((Disk) disk); + } + return disks; + } + return null; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java new file mode 100644 index 00000000..d919fd84 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * 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.gui.dialogs; + +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.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.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.client.GlusterDataModelManager; +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; + +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 Volume volume = new Volume(); + private List allDisks; + private Button btnNfs; + private Button btnStartVolume; + private Link linkCustomize; + private ValidationListener valListener = new ValidationListener(); + + /** + * Create the wizard. + */ + public CreateVolumePage1() { + super(PAGE_NAME); + setTitle("Create Volume"); + setDescription("Create a new Volume by choosing disks from the cluster servers and configuring the volume properties."); + + // by default, we create volume with all available disks + allDisks = GlusterDataModelManager.getInstance().getReadyDisksOfAllServers(); + volume.setDisks(allDisks); + } + + private class ValidationListener implements ModifyListener { + /* (non-Javadoc) + * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) + */ + @Override + public void modifyText(ModifyEvent e) { + String volumeName = txtName.getText().trim(); + String accessControl = txtAccessControl.getText().trim(); + String volumeNameToken = "^[a-zA-Z][a-zA-Z0-9\\-]*"; + + + setErrorMessage(null); + setPageComplete(true); + + if(volumeName.length() == 0) { + setPageComplete(false); + setErrorMessage("Please enter Volume Name"); + } + + if (!volumeName.matches(volumeNameToken)) { + setPageComplete(false); + setErrorMessage("Please enter valid Volume Name"); + } + + if(accessControl.length() == 0) { + setPageComplete(false); + setErrorMessage("Please enter Access Control"); + } + + + // acl validation + String[] aclList = accessControl.split(","); + for (String ip : aclList) { + if (!isValidIP(ip)) { + setPageComplete(false); + setErrorMessage("Please enter valid access control list"); + } + } + + } + + private Boolean isValidIP(String ip) { + // String pattern = "^.[0-9]{1,3}/..[0-9]{1,3}/..[0-9]{1,3}/..[0-9]{1,3}"; + String pattern = "^.[0-9]{1,3}/."; + if (ip == "*") { + return true; + } + String[] ipQuads = ip.split("."); + for (String quad : ipQuads) { + if (!quad.matches(pattern)) { + return false; + } + } + return true; + + } + } + + /** + * Create contents of the wizard. + * @param parent + */ + public void createControl(Composite parent) { + + setPageComplete(false); + 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); + + new Label(container, SWT.NONE); + new Label(container, SWT.NONE); + + Label lblName = new Label(container, SWT.NONE); + lblName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblName.setText("Name: "); + + txtName = new Text(container, SWT.BORDER); + GridData txtNameData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + txtNameData.widthHint = 300; + txtName.setLayoutData(txtNameData); + txtName.addModifyListener(valListener); + + Label lblType = new Label(container, SWT.NONE); + lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblType.setText("Type: "); + + 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); + } + }); + + Label lblTransportType = new Label(container, SWT.NONE); + lblTransportType.setText("Transport Type: "); + + Label lblEthernet = new Label(container, SWT.NONE); + lblEthernet.setText("Ethernet"); + + Label lblDisks = new Label(container, SWT.RIGHT); + lblDisks.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblDisks.setText("Disks: "); + + linkCustomize = new Link(container, SWT.UNDERLINE_LINK); + linkCustomize.setText("All Disk(s) (customize)"); + 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(), allDisks, volume.getDisks()); + + dialog.create(); + if(dialog.open() == Window.OK) { + // user has customized disks. get them from the dialog box. + volume.setDisks(dialog.getSelectedDisks()); + linkCustomize.setText("" + volume.getDisks().size() + " Disk(s) (customize)"); + } + } + }); + } + }); + + Label lblNasProtocol = new Label(container, SWT.RIGHT); + lblNasProtocol.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblNasProtocol.setText("NAS Protocol: "); + + Button btnGluster = new Button(container, SWT.CHECK); + btnGluster.setEnabled(false); + btnGluster.setSelection(true); + btnGluster.setText("Gluster"); + new Label(container, SWT.NONE); + + btnNfs = new Button(container, SWT.CHECK); + btnNfs.setSelection(true); + btnNfs.setText("NFS"); + + Label lblAccessControl = new Label(container, SWT.NONE); + lblAccessControl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblAccessControl.setText("Access Control: "); + + 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(valListener); + + new Label(container, SWT.NONE); + 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)"); + + Label lblStartVolume = new Label(container, SWT.NONE); + lblStartVolume.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblStartVolume.setText("Start Volume: "); + + btnStartVolume = new Button(container, SWT.CHECK); + btnStartVolume.setSelection(true); + } + + public Volume getVolume() { + volume.setName(txtName.getText()); + + IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); + volume.setVolumeType((VOLUME_TYPE)selection.getFirstElement()); + + volume.setTransportType(TRANSPORT_TYPE.ETHERNET); + Set nasProtocols = new HashSet(); + nasProtocols.add(NAS_PROTOCOL.GLUSTERFS); + if(btnNfs.getSelection()) { + nasProtocols.add(NAS_PROTOCOL.NFS); + } + + volume.setAccessControlList(txtAccessControl.getText()); + + return volume; + } + + public Boolean getStartVolumeRequest() { + return btnStartVolume.getSelection(); + } + + public Boolean isValidCreateVolumeForm() { + IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); + if (selection.getFirstElement().equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && ((int)volume.getDisks().size()) % 2 != 0 ) { + setErrorMessage("Mirror type volume requires disk in multiples of two"); + return false; + } else if(selection.getFirstElement().equals(VOLUME_TYPE.DISTRIBUTED_STRIPE) && ((int)volume.getDisks().size()) % 4 != 0) { + setErrorMessage("Stripe type volume requires disk in multiples of four"); + return false; + } + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java new file mode 100644 index 00000000..36755bec --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.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.gui.dialogs; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class CreateVolumeWizard extends Wizard { + + public CreateVolumeWizard() { + setWindowTitle("Gluster Management Console - Create Volume"); + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + addPage(new CreateVolumePage1()); + } + + @Override + public boolean performFinish() { + CreateVolumePage1 page = (CreateVolumePage1) getPage(CreateVolumePage1.PAGE_NAME); + if (!page.isValidCreateVolumeForm()) { + return false; + } + + Volume newVolume = page.getVolume(); + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + VolumesClient volumesClient = new VolumesClient(modelManager.getSecurityToken()); + Status status = volumesClient.createVolume(newVolume); + + if (status.isSuccess()) { + newVolume.setStatus(VOLUME_STATUS.OFFLINE); + if (page.getStartVolumeRequest()) { + Status volumeStartStatus = volumesClient.startVolume(newVolume.getName()); + if (volumeStartStatus.isSuccess()) { + newVolume.setStatus(VOLUME_STATUS.ONLINE); + } + } + //update the model + modelManager.addVolume(newVolume); + MessageDialog.openInformation(getShell(), "Create Volume", "Volume created successfully and configuration added!"); + } else { + MessageDialog.openError(getShell(), "Create Volume", "Volume creation failed! [" + status.getCode() + "][" + + status.getMessage() + "]"); + } + + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java new file mode 100644 index 00000000..7dc0b03d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * 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.gui.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.ITableLabelProvider; +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.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.core.model.Disk; +import com.gluster.storage.management.core.model.GlusterDummyModel; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class MigrateDiskPage1 extends WizardPage { + private static final String PAGE_NAME = "migrate.disk.page.1"; + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_IN_USE + } + private static final String[] DISK_TABLE_COLUMN_NAMES = { "Server", "Disk", "Space (GB)", "Used Space (GB)" }; + + private Volume volume; + private Disk fromDisk; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private ITableLabelProvider getDiskLabelProvider() { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? NumberUtil.formatNumber(disk.getSpace()) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? NumberUtil.formatNumber(disk.getSpaceInUse()) + : "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.DISK, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE, SWT.CENTER, 90); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE, 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 MigrateDiskPage1(Volume volume, Disk disk) { + super(PAGE_NAME); + this.volume = volume; + this.fromDisk = disk; + setTitle("Migrate Disk [" + volume.getName() + "]"); +// setDescription("Migrate data from one disk to another for the chosen Volume. " + +// "This will copy all data present in the \"from disk\" of the volume " + +// "to \"to disk\", remove \"from disk\" from the volume, and " + +// "add \"to disk\" to the volume"); + setDescription("Migrate volume data from \"From Disk\" to \"To Disk\""); + } + + 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; + } + + /** + * 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 Disk:"); + lblFromDisk.setLayoutData(labelLayoutData); + Label lblToDisk = new Label(container, SWT.NONE); + lblToDisk.setText("To Disk:"); + lblToDisk.setLayoutData(labelLayoutData); + + Text txtFilterFrom = guiHelper.createFilterText(container); + Text txtFilterTo = guiHelper.createFilterText(container); + + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(); + + GlusterDummyModel glusterDummyModel = GlusterDummyModel.getInstance(); + List fromDisks = glusterDummyModel.getReadyDisksOfVolume(volume); + List toDisks = glusterDummyModel.getReadyDisksOfAllServersExcluding(volume.getDisks()); + + TableViewer tableViewerFrom = createTableViewer(container, diskLabelProvider, fromDisks, txtFilterFrom); + if(fromDisk != null) { + setFromDisk(tableViewerFrom, fromDisk); + } + + createTableViewer(container, diskLabelProvider, toDisks, txtFilterTo); + } + + private void setFromDisk(TableViewer tableViewer, Disk diskToSelect) { + Table table = tableViewer.getTable(); + for(int i = 0 ; i < table.getItemCount(); i++) { + TableItem item = table.getItem(i); + if(item.getData() == diskToSelect) { + table.select(i); + return; + } + } + } + + private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, List fromDisks, 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(fromDisks.toArray()); + return tableViewer; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java new file mode 100644 index 00000000..464abefa --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.gui.dialogs; + +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; + +public class MigrateDiskWizard extends Wizard { + private Volume volume; + private Disk disk; + + public MigrateDiskWizard(Volume volume, Disk disk) { + setWindowTitle("Gluster Management Console - Migrate Disk [" + volume.getName() + "]"); + this.volume = volume; + this.disk = disk; + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + addPage(new MigrateDiskPage1(volume, disk)); + } + + @Override + public boolean performFinish() { + System.out.println("Triggered Disk Migration!"); + // TODO: Add code to migrate disk + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java new file mode 100644 index 00000000..10a36fb0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.gui.dialogs; + +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.osgi.framework.internal.core.Msg; +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.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; + +public class SelectDisksDialog extends Dialog { + + private CreateVolumeDisksPage disksPage; + private List allDisks; + private List selectedDisks; + + /** + * Create the dialog. + * + * @param parentShell + */ + public SelectDisksDialog(Shell parentShell, List allDisks, List selectedDisks) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + this.allDisks = allDisks; + this.selectedDisks = selectedDisks; + } + + /** + * 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 Disks"); + + disksPage = new CreateVolumeDisksPage(container, SWT.NONE, allDisks, selectedDisks); + + 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.getSelectedDisks().size() == 0 ) { + MessageDialog.openError(getShell(), "Select Disk(s)", "Please select atlease one disk"); + } else { + super.okPressed(); + } + } + + public List getSelectedDisks() { + return disksPage.getChosenDisks(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java new file mode 100644 index 00000000..b5945e61 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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.gui.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.ui.progress.IProgressConstants; +import org.eclipse.ui.progress.IProgressConstants2; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class InitializeDiskJob extends Job { + private Disk disk; + private Application app = Application.getApplication(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + public InitializeDiskJob(Disk disk) { + super("Initialize Disk [" + disk.getQualifiedName() + "]"); + this.disk = disk; + setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.WORK_IN_PROGRESS)); + } + + private void updateStatus(final DISK_STATUS status) { + disk.setStatus(status); + disk.setSpaceInUse(0d); + app.entityChanged(disk, new String[] { "status", "spaceInUse" }); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + monitor.beginTask("Formatting the disk...", 100); + boolean cancelRequested = false; + String msgPrefix = ""; + try { + for (int i = 1; i <= 5; i++) { + if (!cancelRequested && monitor.isCanceled()) { + cancelRequested = true; // come only once here + + msgPrefix = "This task cannot be cancelled! "; + monitor.setTaskName(msgPrefix); +// setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.STATUS_CANCELLED)); +// +// updateStatus(DISK_STATUS.UNINITIALIZED); +// return new Status(Status.CANCEL, Application.PLUGIN_ID, "Cancelled"); + } + Thread.sleep(2000); + monitor.worked(20); + monitor.setTaskName(msgPrefix + "[" + 20 * i + "%] completed"); + } + monitor.done(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + updateStatus(DISK_STATUS.READY); + setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.STATUS_SUCCESS)); + + return new Status(Status.OK, Application.PLUGIN_ID, "Task Completed!"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java new file mode 100644 index 00000000..45b13a19 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * 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.gui.login; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.PojoProperties; +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.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.GlusterDataModelManager; +import com.gluster.storage.management.client.UsersClient; +import com.gluster.storage.management.client.constants.ClientConstants; +import com.gluster.storage.management.core.model.ConnectionDetails; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.validators.StringRequiredValidator; + +/** + * Login dialog, which prompts for the user's account info, and has Login and Cancel buttons. + */ +public class LoginDialog extends Dialog { + + 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(); + if (usersClient.authenticate(user, password)) { + GlusterDataModelManager.getInstance().initializeModel(usersClient.getSecurityToken()); + super.okPressed(); + } else { + MessageDialog.openError(getShell(), "Authentication Failed", "Invalid User ID or password"); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java new file mode 100644 index 00000000..14dbeba9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.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.gui.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.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 ClusterPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public ClusterPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * 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 DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java new file mode 100644 index 00000000..2d49af9b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.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.gui.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.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 ConsolePreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public ConsolePreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * 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 DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java new file mode 100644 index 00000000..23b2cff2 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.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.gui.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.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 { + + public GlusterPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * 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 DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java new file mode 100644 index 00000000..4c1bfcd5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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.gui.preferences; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants { + + public static final String P_PATH = "pathPreference"; + + public static final String P_BOOLEAN = "booleanPreference"; + + public static final String P_CHOICE = "choicePreference"; + + public static final String P_STRING = "stringPreference"; + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java new file mode 100644 index 00000000..74ace130 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.gui.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.gluster.storage.management.gui.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_BOOLEAN, true); + store.setDefault(PreferenceConstants.P_CHOICE, "choice2"); + store.setDefault(PreferenceConstants.P_STRING, + "Default value"); + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java new file mode 100644 index 00000000..a98c7862 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * 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.gui.toolbar; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; + +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; +import com.gluster.storage.management.gui.actions.IActionSetIDs; + +public class GlusterToolbarManager implements ToolbarManager { + private enum ENTITY_TYPE { + CLUSTER, VOLUMES, VOLUME, GLUSTER_SERVERS, GLUSTER_SERVER, DISCOVERED_SERVERS, DISCOVERED_SERVER + }; + + 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); + + return entityTypeMap; + } + + private Map createActionSetMap() { + Map actionSetMap = new HashMap(); + actionSetMap.put(ENTITY_TYPE.CLUSTER, IActionSetIDs.ACTION_SET_CLUSTER); + actionSetMap.put(ENTITY_TYPE.VOLUMES, IActionSetIDs.ACTION_SET_VOLUMES); + actionSetMap.put(ENTITY_TYPE.VOLUME, IActionSetIDs.ACTION_SET_VOLUME); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVERS, IActionSetIDs.ACTION_SET_GLUSTER_SERVERS); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVER, IActionSetIDs.ACTION_SET_GLUSTER_SERVER); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVERS, IActionSetIDs.ACTION_SET_DISCOVERED_SERVERS); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVER, IActionSetIDs.ACTION_SET_DISCOVERED_SERVER); + + 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.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java new file mode 100644 index 00000000..f68346d6 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java new file mode 100644 index 00000000..9cbf6664 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java new file mode 100644 index 00000000..ccd5d8ec --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java @@ -0,0 +1,363 @@ +/******************************************************************************* + * 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.gui.utils; + +import java.util.Iterator; + +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.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnLayoutData; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeSelection; +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.IWorkbenchSite; +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 com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.views.NavigationView; + +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 = 15; + layout.marginBottom = 20; + layout.marginTop = 5; + + 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); + } + }); + + 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 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.LEFT, SWT.CENTER, false, false); + data.widthHint = 300; + filterText.setLayoutData(data); + + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.RIGHT); + searchDecoration.setImage(getImage(IImageKeys.SEARCH)); + searchDecoration.show(); + searchDecoration.setShowHover(true); + searchDecoration.setDescriptionText(tooltipMessage); + + 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)); + 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 Object getSelectedEntity(IWorkbenchSite site, Class expectedType) { + ISelection selection = site.getWorkbenchWindow().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 selectedObj; + } + } + } + return null; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java new file mode 100644 index 00000000..efa169de --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java @@ -0,0 +1,51 @@ +/** + * 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.gui.utils; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.gui.Application; + +/** + * + */ +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.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java new file mode 100644 index 00000000..3c805ac8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java @@ -0,0 +1,55 @@ +/** + * LRUCache.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.gui.utils; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * An LRU cache, based on LinkedHashMap. + *

    + * This cache has a fixed maximum number of elements (cacheSize). If the cache is full and another entry is + * added, the LRU (least recently used) entry is dropped. + * + */ +public class LRUCache extends LinkedHashMap { + + private static final long serialVersionUID = 1L; + private static final float loadFactor = 0.75f; + private int cacheSize; + + /** + * Creates a new LRU cache. + * + * @param cacheSize + * the maximum number of entries that will be kept in this cache. + */ + public LRUCache(int cacheSize) { + super((int) Math.ceil(cacheSize / loadFactor) + 1, loadFactor, true); + this.cacheSize = cacheSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > cacheSize; + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java new file mode 100644 index 00000000..fd76c6e5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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.gui.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 { + private final String errorText; + private final ControlDecoration controlDecoration; + private 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); + } + } + linkedControl.setEnabled(true); + controlDecoration.hide(); + return Status.OK_STATUS; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java new file mode 100644 index 00000000..b2d2b93a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java @@ -0,0 +1,155 @@ +/** + * 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.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +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.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.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.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * @author root + * + */ +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; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (cluster == null) { + //cluster = (Cluster)guiHelper.getSelectedEntity(getSite(), Cluster.class); + cluster = (Cluster)GlusterDataModelManager.getInstance().getModel().getChildren().get(0); + } + + createSections(parent); + } + + private int getVolumeCountByStatus(Cluster cluster, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : cluster.getVolumes()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + 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 createVolumesSection() { + Composite section = guiHelper.createSection(form, toolkit, "Volumes", null, 1, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createServersSection() { + Composite section = guiHelper.createSection(form, toolkit, "Servers", null, 1, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.OFFLINE)) }; + + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + 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_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + + imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Add Server(s)"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.ADD_SERVER_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Cluster Summary"); + + createVolumesSection(); + createServersSection(); + createActionsSection(); + + 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.gui/src/com/gluster/storage/management/gui/views/DetailsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java new file mode 100644 index 00000000..efdb6457 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * 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.gui.views; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.views.details.TabCreatorFactory; +import com.gluster.storage.management.gui.views.details.TabCreatorFactoryImpl; + +/** + * This view is displayed on the right hand side of the platform UI. It updates itself with appropriate tabs + * whenever selection changes on the navigation view (cluster tree) on the left hand side of the UI. + */ +public class DetailsView extends ViewPart implements ISelectionListener { + public static final String ID = DetailsView.class.getName(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TabFolder tabFolder; + private Entity entity; + private TabCreatorFactory tabCreatorFactory = new TabCreatorFactoryImpl(); + private GlusterToolbarManager toolbarManager; + private IWorkbenchPartSite site; + + public DetailsView() { + super(); + } + + @Override + public void createPartControl(final Composite parent) { + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + tabFolder = new TabFolder(parent, SWT.TOP); + + // listen to selection event on the navigation tree view + IWorkbenchWindow window = getViewSite().getWorkbenchWindow(); + window.getSelectionService().addSelectionListener(this); + + // Create the toolbar manager + toolbarManager = new GlusterToolbarManager(window); + site = getSite(); + } + + @Override + public void setFocus() { + tabFolder.setFocus(); + } + + private void removeAllTabs() { + for (TabItem item : tabFolder.getItems()) { + item.getControl().dispose(); + item.dispose(); + } + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (entity == selectedEntity || selectedEntity == null) { + // entity selection has not changed. do nothing. + return; + } + + entity = selectedEntity; + removeAllTabs(); + + // Create tabs for newly selected entity + tabCreatorFactory.getTabCreator(entity).createTabs(entity, tabFolder, toolkit, site); + + // update toolbar buttons visibility based on selected entity + toolbarManager.updateToolbar(entity); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java new file mode 100644 index 00000000..e13912c6 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; + +/** + * @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, "" + 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) { + 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.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java new file mode 100644 index 00000000..69c506f4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java @@ -0,0 +1,109 @@ +/** + * 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.gui.views; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage; + +/** + * + */ +public class DiscoveredServersView extends ViewPart implements IDoubleClickListener, ISelectionListener { + 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) + */ + @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); + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(NavigationView.ID, 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()); + } + } + + /* + * (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) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (servers == selectedEntity || selectedEntity == null || !(selectedEntity instanceof EntityGroup) + || ((EntityGroup) selectedEntity).getEntityType() != Server.class) { + // entity selection has not changed. do nothing. + return; + } + + servers = (EntityGroup) selectedEntity; + page.setInput(servers); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java new file mode 100644 index 00000000..260d0d4c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java @@ -0,0 +1,44 @@ +package com.gluster.storage.management.gui.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.core.model.Disk; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; + +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; + + @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.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java new file mode 100644 index 00000000..624d968d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java @@ -0,0 +1,57 @@ +/** + * 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.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage; + +public class GlusterServerDisksView extends ViewPart { + public static final String ID = GlusterServerDisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + 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()); + + 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.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java new file mode 100644 index 00000000..acc8144d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerLogsPage; + +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.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java new file mode 100644 index 00000000..42a14dd4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java @@ -0,0 +1,246 @@ +/** + * 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.gui.views; + +import java.util.ArrayList; +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.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.widgets.Composite; +import org.eclipse.swt.widgets.Display; +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.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; +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; + + public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { + INTERFACE, IP_ADDRESS, NETMASK, GATEWAY + }; + + private static final String[] NETWORK_INTERFACE_TABLE_COLUMN_NAMES = { "Interface", "IP Address", "Netmask", + "Gateway" }; + + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + createSections(parent); + } + + 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) { + Composite section = createNetworkInterfacesSection(server, toolkit, form); + } + + parent.layout(); // IMP: lays out the form properly + } + + private void createServerSummarySection(GlusterServer server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + // toolkit.createLabel(section, "Preferred Network: ", SWT.NONE); + // toolkit.createLabel(section, server.getPreferredNetworkInterface().getName(), SWT.NONE); + + boolean online = server.getStatus() == SERVER_STATUS.ONLINE; + + if (online) { + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + // toolkit.createLabel(section, "CPU Usage (%): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getCpuUsage() : "NA", SWT.NONE); + + toolkit.createLabel(section, "% CPU Usage (avg): ", SWT.NONE); + CoolGauge gauge = new CoolGauge(section, guiHelper.getImage(IImageKeys.GAUGE_SMALL)); + gauge.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); + gauge.setGaugeNeedleColour(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + gauge.setGaugeNeedleWidth(2); + gauge.setGaugeNeedlePivot(new Point(66, 65)); + + gauge.setPoints(getPnts()); + gauge.setLevel(server.getCpuUsage() / 100); + gauge.setToolTipText(server.getCpuUsage() + "%"); + + toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + ProgressBar memoryUsageBar = new ProgressBar(section, SWT.SMOOTH); + memoryUsageBar.setMinimum(0); + memoryUsageBar.setMaximum((int) Math.round(server.getTotalMemory())); + memoryUsageBar.setSelection((int) Math.round(server.getMemoryInUse())); + memoryUsageBar.setToolTipText("Total: " + server.getTotalMemory() + "GB, In Use: " + + server.getMemoryInUse() + "GB"); + + // 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(section, "Disk Usage: ", SWT.NONE); + ProgressBar diskUsageBar = new ProgressBar(section, SWT.SMOOTH); + diskUsageBar.setMinimum(0); + diskUsageBar.setMaximum((int) Math.round(server.getTotalDiskSpace())); + diskUsageBar.setSelection((int) Math.round(server.getDiskSpaceInUse())); + diskUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber(server.getTotalDiskSpace()) + + "GB, In Use: " + NumberUtil.formatNumber(server.getDiskSpaceInUse()) + "GB"); + } + + toolkit.createLabel(section, "Status: ", SWT.NONE); + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(server.getStatusStr()); + lblStatusValue.setImage(server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + toolkit.adapt(lblStatusValue, true, 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.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); + // setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED, 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.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java new file mode 100644 index 00000000..428e55d5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java @@ -0,0 +1,123 @@ +/** + * 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.gui.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +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.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * + */ +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 EntityGroup servers; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + createSections(parent); + } + + /** + * @param parent + */ + 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 createSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.OFFLINE)) }; + createStatusChart(section, 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" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + + private void createAlertsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to servers\nwill be displayed here."); + } + + private void createRunningTasksSection() { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nservers will be displayed here."); + } + + /* (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.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java new file mode 100644 index 00000000..06b1e282 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java @@ -0,0 +1,77 @@ +/** + * 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.gui.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.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.GlusterServersPage; + +/** + * @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) + */ + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + page = new GlusterServersPage(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.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java new file mode 100644 index 00000000..2b2645fc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.gui.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); + } + + private void showViewsForVolume(Volume volume) throws PartInitException { + page.showView(VolumeSummaryView.ID); + page.showView(VolumeDisksView.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.gui/src/com/gluster/storage/management/gui/views/NavigationView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java new file mode 100644 index 00000000..4de5b61a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * 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.gui.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.client.GlusterDataModelManager; +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.Volume; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.views.navigator.ClusterAdapterFactory; + +public class NavigationView extends ViewPart implements ISelectionListener { + public static final String ID = NavigationView.class.getName(); + private GlusterDataModel model; + private TreeViewer treeViewer; + private IAdapterFactory adapterFactory = new ClusterAdapterFactory(); + private GlusterToolbarManager toolbarManager; + private Entity entity; + private GlusterViewsManager viewsManager; + + @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) { + 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); + + // Refresh the navigation tree whenever there is a change to the data model + GlusterDataModelManager.getInstance().addClusterListener(new DefaultClusterListener() { + public void clusterChanged() { + treeViewer.refresh(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + selectEntity(volume); // this makes sure that the toolbar buttons get updated accoring to new status + } + + @Override + public void volumeCreated(Volume volume) { + super.volumeCreated(volume); + selectEntity(volume); + } + }); + } + + 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(); + } + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java new file mode 100644 index 00000000..2b33308e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java new file mode 100644 index 00000000..cbf6736b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java @@ -0,0 +1,39 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; + +public class VolumeDisksView extends ViewPart { + public static final String ID = VolumeDisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private DisksPage 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 DisksPage(parent, SWT.NONE, getSite(), volume.getDisks()); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java new file mode 100644 index 00000000..b6c98ad3 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java @@ -0,0 +1,35 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage; + +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.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java new file mode 100644 index 00000000..e8695737 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java @@ -0,0 +1,36 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage; + +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.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java new file mode 100644 index 00000000..798c2a40 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java @@ -0,0 +1,270 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +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.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 org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +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.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.utils.GUIHelper; + +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; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createSections(parent); + + // Refresh the navigation tree whenever there is a change to the data model + volumeChangedListener = new DefaultClusterListener() { + @Override + public void volumeChanged(Volume volume, Event event) { + if(event.getEventType() == EVENT_TYPE.VOLUME_STATUS_CHANGED) { + updateVolumeStatusLabel(); + new GlusterToolbarManager(getSite().getWorkbenchWindow()).updateToolbar(volume); + } + } + }; + GlusterDataModelManager.getInstance().addClusterListener(volumeChangedListener); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#dispose() + */ + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(volumeChangedListener); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Volume Properties [" + volume.getName() + "]"); + + createVolumePropertiesSection(); + createVolumeMountingInfoSection(); + createVolumeAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createVolumeAlertsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 3, false); + toolkit.createLabel(section, "Volume related alerts will be displayed here"); + } + + private void createVolumeMountingInfoSection() { + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 3, false); + toolkit.createLabel(section, "Information about mounting the\nvolume will be printed here"); + } + + /** + * + */ + 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); + } + + createNumOfDisksField(section); + createDiskSpaceField(section); + createTransportTypeField(section); + createNASProtocolField(section); + createAccessControlField(section); + createStatusField(section); + } + + private GridData createDefaultLayoutData() { + GridData layoutData = new GridData(); + layoutData.minimumWidth = 150; + layoutData.widthHint = 150; + return layoutData; + } + + private void createAccessControlField(Composite section) { + toolkit.createLabel(section, "Access Control: ", SWT.NONE); + Text accessControlText = toolkit.createText(section, volume.getAccessControlList()); + accessControlText.setLayoutData(createDefaultLayoutData()); + accessControlText.setEnabled(false); + createChangeLinkForAccessControl(section, accessControlText); + } + + private void createChangeLinkForAccessControl(Composite section, final Text accessControlText) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + // TODO: Validation of entered text + volume.setAccessControlList(accessControlText.getText()); + accessControlText.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + accessControlText.setEnabled(true); + 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 createNASProtocolField(Composite section) { + toolkit.createLabel(section, "NAS Protocols: ", SWT.NONE); + + Composite nasProtocolsComposite = toolkit.createComposite(section); + nasProtocolsComposite.setLayout(new FillLayout()); + + createCheckbox(nasProtocolsComposite, "Gluster", true); + final Button nfsCheckBox = createCheckbox(nasProtocolsComposite, "NFS", + volume.getNASProtocols().contains(NAS_PROTOCOL.NFS)); + + createChangeLinkForNASProtocol(section, nfsCheckBox); + } + + private Button createCheckbox(Composite parent, String label, boolean selected) { + final Button checkBox = toolkit.createButton(parent, label, SWT.CHECK); + checkBox.setEnabled(false); + checkBox.setSelection(selected); + return checkBox; + } + + private void createChangeLinkForNASProtocol(Composite section, final Button nfsCheckBox) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + if (nfsCheckBox.getSelection()) { + volume.enableNFS(); + } else { + volume.disableNFS(); + } + nfsCheckBox.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + nfsCheckBox.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (nfsCheckBox.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void createDiskSpaceField(Composite section) { + Label diskSpaceLabel = toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + diskSpaceLabel.setToolTipText("boldnormal"); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(volume.getTotalDiskSpace()), 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) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + 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 createNumOfDisksField(Composite section) { + toolkit.createLabel(section, "Number of Disks: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getNumOfDisks(), 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(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java new file mode 100644 index 00000000..1983f6e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/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.gui.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.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; + +/** + * @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.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java new file mode 100644 index 00000000..9477e170 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java @@ -0,0 +1,145 @@ +/** + * 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.gui.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +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.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * + */ +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; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @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; + } + } + + createSections(parent); + } + + 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() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to volumes\nwill be displayed here."); + } + + private void createRunningTasksSection() { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + GlusterDataModel model = modelManager.getModel(); + Cluster cluster = (Cluster) model.getChildren().get(0); // Assume the first/root node of the model is cluster (invisible) + + List runningTasks = cluster.getRunningTasks(); + String taskMessage = ""; + for(RunningTask task : runningTasks) { + if (task.getStatus().isPercentageSupported()) { + //TODO Progress bar + } + //TODO show different labels for each task + taskMessage = taskMessage + CoreConstants.NEWLINE + task.getDescription(); + } + toolkit.createLabel(section, taskMessage); + } + + private void createSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, 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" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, + values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + 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.gui/src/com/gluster/storage/management/gui/views/VolumesView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java new file mode 100644 index 00000000..4ccf5325 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java @@ -0,0 +1,108 @@ +/** + * 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.gui.views; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage; +import com.gluster.storage.management.gui.views.pages.VolumesPage; + +/** + * + */ +public class VolumesView extends ViewPart implements IDoubleClickListener, ISelectionListener { + 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) + */ + @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); + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(NavigationView.ID, 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()); + } + } + + /* + * (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) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (volumes == selectedEntity || selectedEntity == null || !(selectedEntity instanceof EntityGroup) + || ((EntityGroup) selectedEntity).getEntityType() != Volume.class) { + // entity selection has not changed. do nothing. + return; + } + + volumes = (EntityGroup) selectedEntity; + page.setInput(volumes); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java new file mode 100644 index 00000000..e00fe3f8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java @@ -0,0 +1,315 @@ +/******************************************************************************* + * 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.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.TableEditor; +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.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.PartInitException; +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.progress.IProgressConstants; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IEntityListener; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.jobs.InitializeDiskJob; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public abstract class AbstractDisksPage extends Composite implements IEntityListener { + protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + protected TableViewer tableViewer; + private IWorkbenchSite site; + protected static final GUIHelper guiHelper = GUIHelper.getInstance(); + + /** + * Setup properties of the table e.g. column headers, widths, etc. + * + * @param parent + * The parent composite. (TableColumnLayout has to be set on this) + * @param table + * The table to be set up + */ + protected abstract void setupDiskTable(Composite parent, Table table); + + /** + * @return The label provider to be used with the disk table viewer + */ + protected abstract ITableLabelProvider getTableLabelProvider(); + + /** + * @return Index of the "status" column in the table. Return -1 if status column is not displayed + */ + protected abstract int getStatusColumnIndex(); + + private void init(final Composite parent, IWorkbenchSite site, List disks) { + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + this.site = site; + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupDiskTableViewer(createTableViewerComposite(), filterText); + + tableViewer.setInput(disks); + setupStatusCellEditor(); // creates hyperlinks for "unitialized" disks + + site.setSelectionProvider(tableViewer); + Application.getApplication().addEntityListener(this); + + parent.layout(); // Important - this actually paints the table + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + /** + * 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(); + } + }); + } + + public AbstractDisksPage(final Composite parent, int style, IWorkbenchSite site, List disks) { + super(parent, style); + init(parent, site, disks); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void createInitializeLink(final TableItem item, final int rowNum, final Disk disk) { + final Table table = tableViewer.getTable(); + final TableEditor editor = new TableEditor(table); + editor.grabHorizontal = true; + editor.horizontalAlignment = SWT.RIGHT; + + table.addPaintListener(new PaintListener() { + private TableItem myItem = item; + private int myRowNum = rowNum; + private ImageHyperlink myLink = null; + private TableEditor myEditor = null; + + private void createLinkFor(Disk disk1, TableItem item1, int rowNum1) { + myItem = item1; + myRowNum = rowNum1; + + myEditor = new TableEditor(table); + myEditor.grabHorizontal = true; + myEditor.horizontalAlignment = SWT.RIGHT; + + myLink = toolkit.createImageHyperlink(table, SWT.NONE); + // link.setImage(guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED)); + myLink.setText("Initialize"); + myLink.addHyperlinkListener(new StatusLinkListener(myLink, myEditor, myItem, tableViewer, disk1, site)); + + 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 = table.getItemCount(); + + // Find the table item corresponding to our disk + Disk disk1 = null; + int rowNum1 = -1; + TableItem item1 = null; + for (int i = 0; i < itemCount; i++) { + item1 = table.getItem(i); + disk1 = (Disk) item1.getData(); + if (disk1 != null && disk1 == disk) { + rowNum1 = i; + break; + } + } + + 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(disk1, item1, rowNum1); + } + + if (rowNum1 != myRowNum) { + // disk visible, but at a different row num. re-create the link + myLink.dispose(); + myEditor.dispose(); + createLinkFor(disk1, item1, rowNum1); + } + + myEditor.layout(); // IMPORTANT. Without this, the link location goes for a toss on maximize + restore + } + }); + } + + private void setupStatusCellEditor() { + final TableViewer viewer = tableViewer; + final Table table = viewer.getTable(); + for (int i = 0; i < table.getItemCount(); i++) { + final TableItem item = table.getItem(i); + if (item.isDisposed() || item.getData() == null) { + continue; + } + final Disk disk = (Disk) item.getData(); + if (disk.isUninitialized()) { + createInitializeLink(item, i, disk); + } + } + } + + 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)); + return tableViewerComposite; + } + + private TableViewer createDiskTableViewer(Composite parent) { + tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + + tableViewer.setLabelProvider(getTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupDiskTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private void setupDiskTableViewer(Composite parent, final Text filterText) { + tableViewer = createDiskTableViewer(parent); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + private final class StatusLinkListener extends HyperlinkAdapter { + private final Disk disk; + private final TableEditor myEditor; + private final ImageHyperlink myLink; + private final TableViewer viewer; + private final IWorkbenchSite site; + + private StatusLinkListener(ImageHyperlink link, TableEditor editor, TableItem item, TableViewer viewer, + Disk disk, IWorkbenchSite site) { + this.disk = disk; + this.viewer = viewer; + this.myEditor = editor; + this.myLink = link; + this.site = site; + } + + private void updateStatus(final DISK_STATUS status, final boolean disposeEditor) { + if (disposeEditor) { + myLink.dispose(); + myEditor.dispose(); + } + disk.setStatus(status); + viewer.update(disk, new String[] { "status" }); + Application.getApplication().entityChanged(disk, new String[] { "status" }); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + updateStatus(DISK_STATUS.INITIALIZING, true); + + try { + site.getWorkbenchWindow().getActivePage().showView(IProgressConstants.PROGRESS_VIEW_ID); + } catch (PartInitException e1) { + e1.printStackTrace(); + throw new GlusterRuntimeException("Could not open the progress view!", e1); + } + + new InitializeDiskJob(disk).schedule(); + } + } + + @Override + public void entityChanged(final Entity entity, final String[] paremeters) { + if (!(entity instanceof Disk)) { + return; + } + final Disk disk = (Disk) entity; + + Display.getDefault().syncExec(new Runnable() { + public void run() { + tableViewer.update(disk, paremeters); + + if (disk.isUninitialized()) { + Table table = tableViewer.getTable(); + + for (int rowNum = 0; rowNum < table.getItemCount(); rowNum++) { + TableItem item = table.getItem(rowNum); + if (item.getData() == disk) { + createInitializeLink(item, rowNum, disk); + } + } + } + } + }); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java new file mode 100644 index 00000000..9ea962de --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +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.core.model.Disk; +import com.gluster.storage.management.gui.DiskTableLabelProvider; + +public class DisksPage extends AbstractDisksPage { + + public enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_IN_USE, STATUS + }; + + private static final String[] DISK_TABLE_COLUMN_NAMES = new String[] { "Server", "Disk", "Space (GB)", + "Space in Use (GB)", "Status" }; + + public DisksPage(final Composite parent, int style, IWorkbenchSite site, List disks) { + super(parent, style, site, disks); + } + + @Override + protected void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SERVER.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.DISK.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal(), SWT.CENTER, 90); + } + + @Override + protected ITableLabelProvider getTableLabelProvider() { + return new DiskTableLabelProvider(); + } + + @Override + protected int getStatusColumnIndex() { + return DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java new file mode 100644 index 00000000..01766115 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * 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.gui.views.details; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +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.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.GlusterServerTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class GlusterServersPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum GLUSTER_SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_CPUS, TOTAL_MEMORY, TOTAL_DISK_SPACE, STATUS // Removed PREFERRED_NETWORK + }; + + private static final String[] GLUSTER_SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", + "IP Address(es)", "Number\nof CPUs", "Total\nMemory (GB)", "Total Disk\n Space (GB)", "Status" }; // Removed "Preferred\nNetwork", + + public GlusterServersPage(Composite parent, int style) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupServerTableViewer(filterText); + } + + public GlusterServersPage(final Composite parent, int style, EntityGroup servers) { + this(parent, style); + + tableViewer.setInput(servers); + parent.layout(); // Important - this actually paints the table + + /** + * 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(); + } + }); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupServerTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, GLUSTER_SERVER_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + 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_DISK_SPACE, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + private TableViewer createServerTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + //TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new GlusterServerTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider()); + + setupServerTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + 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)); + return tableViewerComposite; + } + + private void setupServerTableViewer(final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createServerTableViewer(tableViewerComposite); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + /** + * 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.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java new file mode 100644 index 00000000..bace2af9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.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.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +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.core.model.Disk; +import com.gluster.storage.management.gui.ServerDiskTableLabelProvider; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; + +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, SPACE, SPACE_IN_USE, STATUS + }; + + private static final String[] SERVER_DISK_TABLE_COLUMN_NAMES = new String[] { "Disk", "Space (GB)", + "Space in Use (GB)", "Status" }; + + @Override + protected void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, SERVER_DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.SPACE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(), SWT.LEFT, 90); + } + + @Override + protected int getStatusColumnIndex() { + return SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } + + @Override + protected TableLabelProviderAdapter getTableLabelProvider() { + return new ServerDiskTableLabelProvider(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java new file mode 100644 index 00000000..a499caf3 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * 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.gui.views.details; + +import java.util.ArrayList; +import java.util.List; + +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.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.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; + +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); + + 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.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java new file mode 100644 index 00000000..1f5f8a15 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.gui.views.details; + +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.Entity; + +/** + * For every entity that can be selected from the navigation view (cluster tree), a set of tabs are created on the + * details view. Each entity has a corresponding tab creator that creates these tabs. These tab creators must implement + * this interface. + *

    + * Important: Tab creators are cached for performance reasons. Hence they should not store any state information + * in class level variables. + */ +public interface TabCreator { + /** + * Creates tabs for the given entity + * + * @param entity + * Entity for which tabs are to be created + * @param tabFolder + * The tab folder in which the tabs are to be created + * @param toolkit + * The form toolkit that can be used for create components using Forms API + * @param site + * The workbench site that can be used to register as a selection provider + */ + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site); +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java new file mode 100644 index 00000000..f5098af5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.gui.views.details; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Interface for tab creator factory. + */ +public interface TabCreatorFactory { + /** + * @param entity The entity for which tab creator factory is to be returned + * @return A tab creator factory for given entity + */ + public TabCreator getTabCreator(Entity entity); +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.java new file mode 100644 index 00000000..28d3d4aa --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.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.gui.views.details; + +import java.util.HashMap; +import java.util.Map; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; + +public class TabCreatorFactoryImpl implements TabCreatorFactory { + + private Map tabCreatorCache = new HashMap(); + + /** + * Returns tab creator for given entity. The logic is as follows:
    + * 1) Check if an tab creator is already created for the "class" of the entity. In case of {@link EntityGroup}, + * append the class name with entity type
    + * 2) If the tab creator is found in the cache, return it
    + * 3) If not found, create one by instantiating the class ".tabcreators.TabCreator". + * Again, "class name" includes "entity type" in case of {@link EntityGroup}
    + * 4) Add the newly created tab creator to the cache and return it + */ + @SuppressWarnings("rawtypes") + @Override + public TabCreator getTabCreator(Entity entity) { + Class entityClass = entity.getClass(); + String key = entityClass.getSimpleName(); + if (entityClass == EntityGroup.class) { + // If it's an entity group, add the entity type to the key + key += ((EntityGroup) entity).getEntityType().getSimpleName(); + } + + TabCreator tabCreator = tabCreatorCache.get(key); + if (tabCreator == null) { + // Not created yet. Create one and add to the cache + String className = getClass().getPackage().getName() + ".tabcreators." + key + "TabCreator"; + try { + Class creatorFactoryClass = (Class) Class.forName(className); + tabCreator = creatorFactoryClass.newInstance(); + tabCreatorCache.put(key, tabCreator); + } catch (ClassNotFoundException e) { + throw new GlusterRuntimeException("Could not load creator factory class [" + className + "]", e); + } catch (InstantiationException e) { + throw new GlusterRuntimeException("Could not create instance of creator factory class [" + className + + "]", e); + } catch (IllegalAccessException e) { + throw new GlusterRuntimeException("Could not create instance of creator factory class [" + className + + "]", e); + } + } + + return tabCreator; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java new file mode 100644 index 00000000..d435201e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * 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.gui.views.details; + +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.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.core.model.GlusterDummyModel; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.VolumeLogTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumeLogsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Text text; + 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 VolumeLogsPage(Composite parent, int style, Volume volume) { + 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; + //layoutData.verticalIndent = 10; + 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); + + Label lblMessagesAndFilter = toolkit.createLabel(composite, "messages, and filter on disk", SWT.NONE); + lblMessagesAndFilter.setBounds(160, 15, 200, 20); + + Combo combo = new Combo(composite, SWT.NONE); + combo.setBounds(365, 15, 100, 20); + combo.setItems(new String[] {"ALL", "sda", "sdb", "sdc", "sdd"}); + toolkit.adapt(combo); + toolkit.paintBordersFor(combo); + combo.select(0); + + Label lblSeverity = toolkit.createLabel(composite, "Severity", SWT.NONE); + lblSeverity.setBounds(480, 15, 70, 20); + + Combo combo_1 = new Combo(composite, SWT.NONE); + combo_1.setBounds(555, 15, 110, 20); + combo_1.setItems(new String[] {"ALL", "SEVERE", "WARNING", "DEBUG", "INFO"}); + toolkit.adapt(combo_1); + toolkit.paintBordersFor(combo_1); + combo_1.select(1); + + Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE); + lblFrom.setBounds(0, 60, 40, 20); + + DateTime dateTime = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + dateTime.setBounds(45, 60, 120, 20); + toolkit.adapt(dateTime); + toolkit.paintBordersFor(dateTime); + + DateTime dateTime_1 = new DateTime(composite, SWT.BORDER | SWT.TIME); + dateTime_1.setBounds(171, 60, 120, 20); + toolkit.adapt(dateTime_1); + toolkit.paintBordersFor(dateTime_1); + + Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE); + lblTo.setBounds(329, 60, 26, 20); + + DateTime dateTime_2 = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + dateTime_2.setBounds(355, 60, 120, 20); + toolkit.adapt(dateTime_2); + toolkit.paintBordersFor(dateTime_2); + + DateTime dateTime_3 = new DateTime(composite, SWT.BORDER | SWT.TIME); + dateTime_3.setBounds(480, 60, 120, 20); + toolkit.adapt(dateTime_3); + toolkit.paintBordersFor(dateTime_3); + + Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE); + btngo.setBounds(605, 55, 60, 30); + + Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL); + separator.setBounds(0, 95, 680, 2); + + Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT); + lblFilterString.setBounds(0, 105, 85, 20); + + text = guiHelper.createFilterText(toolkit, composite); + text.setBounds(90, 105, 250, 20); + + Composite tableViewerComposite = createTableViewerComposite(); + + TableViewer 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, text, false); + tableViewer.setInput(GlusterDummyModel.getDummyLogMessages().toArray()); + } + + 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.DISK, 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)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java new file mode 100644 index 00000000..baa14a59 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.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.gui.views.details; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; +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.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.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.VolumeOptionsTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumeOptionsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum OPTIONS_TABLE_COLUMN_INDICES { + OPTION_KEY, OPTION_VALUE + }; + + private static final String[] OPTIONS_TABLE_COLUMN_NAMES = new String[] { "Option Key", "Option Value" }; + + public VolumeOptionsPage(Composite parent, int style) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupDiskTableViewer(filterText); + } + + public VolumeOptionsPage(final Composite parent, int style, Volume volume) { + this(parent, style); + + tableViewer.setInput(volume.getOptions().entrySet().toArray()); + + parent.layout(); // Important - this actually paints the table + + /** + * 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(); + } + }); + + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, OPTIONS_TABLE_COLUMN_NAMES); + 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 TableViewer createDiskTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeOptionsTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupDiskTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + 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)); + return tableViewerComposite; + } + + private void setupDiskTableViewer(final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createDiskTableViewer(tableViewerComposite); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + /** + * 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, 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.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java new file mode 100644 index 00000000..571afb2e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +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.ImageHyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.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.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class ClusterTabCreator implements TabCreator { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + private int getVolumeCountByStatus(Cluster cluster, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : cluster.getVolumes()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + 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 createVolumesSection(Cluster cluster, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Volumes", null, 1, false); + + // toolkit.createLabel(sectionClient, "Number of Volumes: ", SWT.NONE); + // toolkit.createLabel(sectionClient, "12", SWT.NONE); + // + // toolkit.createLabel(sectionClient, "Online: ", SWT.NONE); + // Label labelOnlineCount = toolkit.createLabel(sectionClient, "9", SWT.NONE); + // labelOnlineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN)); + // + // toolkit.createLabel(sectionClient, "Offline: ", SWT.NONE); + // Label lblOfflineCount = toolkit.createLabel(sectionClient, "3", SWT.NONE); + // lblOfflineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED)); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createServersSection(Cluster cluster, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Servers", null, 1, false); + +// toolkit.createLabel(sectionClient, "Number of Servers: ", SWT.NONE); +// toolkit.createLabel(sectionClient, "7", SWT.NONE); +// +// toolkit.createLabel(sectionClient, "Online: ", SWT.NONE); +// Label labelOnlineCount = toolkit.createLabel(sectionClient, "6", SWT.NONE); +// labelOnlineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN)); +// +// toolkit.createLabel(sectionClient, "Offline: ", SWT.NONE); +// Label lblOfflineCount = toolkit.createLabel(sectionClient, "1", SWT.NONE); +// lblOfflineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED)); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.OFFLINE)) }; + + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + private void createActionsSection(final Cluster cluster, final FormToolkit toolkit, final ScrolledForm form) { + 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_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + + imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Add Server(s)"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.ADD_SERVER_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + } + + private void createClusterSummaryTab(final Cluster cluster, final TabFolder tabFolder, final FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, cluster.getName(), IImageKeys.CLUSTER); + + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Cluster Summary"); + createVolumesSection(cluster, toolkit, form); + createServersSection(cluster, toolkit, form); + createActionsSection(cluster, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createClusterSummaryTab((Cluster) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java new file mode 100644 index 00000000..3c94c3cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +import java.util.ArrayList; +import java.util.List; + +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.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Disk; +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.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.DisksPage; +import com.gluster.storage.management.gui.views.details.GlusterServersPage; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class EntityGroupGlusterServerTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + 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 createAlertsSection(final EntityGroup servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to servers\nwill be displayed here."); + } + + private void createRunningTasksSection(final EntityGroup servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nservers will be displayed here."); + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createSummaryTab((EntityGroup)entity, tabFolder, toolkit); + createServersTab((EntityGroup)entity, tabFolder, toolkit); + createDisksTab((EntityGroup)entity, tabFolder, toolkit, site); + } + + private void createServersTab(EntityGroup servers, TabFolder tabFolder, FormToolkit toolkit) { + Composite serversTab = guiHelper.createTab(tabFolder, "Servers", IImageKeys.SERVERS); + GlusterServersPage page = new GlusterServersPage(serversTab, SWT.NONE, servers); + page.addDoubleClickListener(this); + } + + private void createSummaryTab(EntityGroup servers, TabFolder tabFolder, FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, "Summary", IImageKeys.SERVERS); + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Servers - Summary"); + createSummarySection(servers, toolkit, form); + createRunningTasksSection(servers, toolkit, form); + createAlertsSection(servers, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + private void createSummarySection(final EntityGroup servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + + private void createDisksTab(EntityGroup servers, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite disksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.SERVERS); + DisksPage page = new DisksPage(disksTab, SWT.NONE, site, getAllDisks(servers)); + + disksTab.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 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.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java new file mode 100644 index 00000000..3f49ba6b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.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.gui.views.details.tabcreators; + +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.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.pages.ServersPage; + +public class EntityGroupServerTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createServersTab((EntityGroup) entity, tabFolder); + } + + private void createServersTab(EntityGroup servers, TabFolder tabFolder) { + Composite serversTab = guiHelper.createTab(tabFolder, "Discovered Servers", IImageKeys.SERVERS); + ServersPage page = new ServersPage(serversTab, null, servers); + page.addDoubleClickListener(this); + } + + @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.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java new file mode 100644 index 00000000..22ffd94d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.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.gui.views.details.tabcreators; + +import java.util.List; + +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.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.pages.VolumesPage; + +public class EntityGroupVolumeTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createSummaryTab((EntityGroup) entity, tabFolder, toolkit); + createVolumesTab((EntityGroup) entity, tabFolder, toolkit); + } + + 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" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, + values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + private void createAlertsSection(final EntityGroup volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to volumes\nwill be displayed here."); + } + + private void createRunningTasksSection(final EntityGroup volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nvolumes will be displayed here."); + } + + private void createSummarySection(final EntityGroup volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createSummaryTab(final EntityGroup volumes, TabFolder tabFolder, FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, "Summary", IImageKeys.VOLUMES); + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Volumes - Summary"); + createSummarySection(volumes, toolkit, form); + createRunningTasksSection(volumes, toolkit, form); + createAlertsSection(volumes, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + private void createVolumesTab(EntityGroup volumes, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumesTab = guiHelper.createTab(tabFolder, "Volumes", IImageKeys.VOLUMES); + VolumesPage page = new VolumesPage(volumesTab, null, volumes); + page.addDoubleClickListener(this); + } + + @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.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java new file mode 100644 index 00000000..e1aa59ff --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +import java.util.ArrayList; +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.custom.CLabel; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +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.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage; +import com.gluster.storage.management.gui.views.details.ServerLogsPage; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.richclientgui.toolbox.gauges.CoolGauge; + +public class GlusterServerTabCreator implements TabCreator { + public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { + INTERFACE, IP_ADDRESS, NETMASK, GATEWAY + }; + + private static final String[] NETWORK_INTERFACE_TABLE_COLUMN_NAMES = { "Interface", "IP Address", "Netmask", + "Gateway" }; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private void createServerSummarySection(GlusterServer server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + +// toolkit.createLabel(section, "Preferred Network: ", SWT.NONE); +// toolkit.createLabel(section, server.getPreferredNetworkInterface().getName(), SWT.NONE); + + boolean online = server.getStatus() == SERVER_STATUS.ONLINE; + + if (online) { + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + // toolkit.createLabel(section, "CPU Usage (%): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getCpuUsage() : "NA", SWT.NONE); + + toolkit.createLabel(section, "% CPU Usage (avg): ", SWT.NONE); + CoolGauge gauge = new CoolGauge(section, guiHelper.getImage(IImageKeys.GAUGE_SMALL)); + gauge.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); + gauge.setGaugeNeedleColour(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + gauge.setGaugeNeedleWidth(2); + gauge.setGaugeNeedlePivot(new Point(66, 65)); + + gauge.setPoints(getPnts()); + gauge.setLevel(server.getCpuUsage() / 100); + gauge.setToolTipText(server.getCpuUsage() + "%"); + + toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + ProgressBar memoryUsageBar = new ProgressBar(section, SWT.SMOOTH); + memoryUsageBar.setMinimum(0); + memoryUsageBar.setMaximum((int) Math.round(server.getTotalMemory())); + memoryUsageBar.setSelection((int) Math.round(server.getMemoryInUse())); + memoryUsageBar.setToolTipText("Total: " + server.getTotalMemory() + "GB, In Use: " + + server.getMemoryInUse() + "GB"); + + // 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(section, "Disk Usage: ", SWT.NONE); + ProgressBar diskUsageBar = new ProgressBar(section, SWT.SMOOTH); + diskUsageBar.setMinimum(0); + diskUsageBar.setMaximum((int) Math.round(server.getTotalDiskSpace())); + diskUsageBar.setSelection((int) Math.round(server.getDiskSpaceInUse())); + diskUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber(server.getTotalDiskSpace()) + + "GB, In Use: " + NumberUtil.formatNumber(server.getDiskSpaceInUse()) + "GB"); + } + + toolkit.createLabel(section, "Status: ", SWT.NONE); + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(server.getStatusStr()); + lblStatusValue.setImage(server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + toolkit.adapt(lblStatusValue, true, 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 void createServerSummaryTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverSummaryTab = guiHelper.createTab(tabFolder, serverName, IImageKeys.SERVER); + final ScrolledForm form = guiHelper.setupForm(serverSummaryTab, toolkit, "Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + if (server.getStatus() == SERVER_STATUS.ONLINE) { + Composite section = createNetworkInterfacesSection(server, toolkit, form); + } + + serverSummaryTab.layout(); // IMP: lays out the form properly + } + + 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.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); + // setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED, SWT.CENTER, 70); + } + + /** + * 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)); + } + + 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 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; + } + + 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 void createServerLogsTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverLogsTab = guiHelper.createTab(tabFolder, "Logs", IImageKeys.SERVER); + ServerLogsPage logsPage = new ServerLogsPage(serverLogsTab, SWT.NONE, server); + + serverLogsTab.layout(); // IMP: lays out the form properly + } + + private void createServerDisksTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite serverDisksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.SERVER); + ServerDisksPage page = new ServerDisksPage(serverDisksTab, SWT.NONE, site, server.getDisks()); + + serverDisksTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + GlusterServer server = (GlusterServer) entity; + + createServerSummaryTab(server, tabFolder, toolkit); + if (server.getStatus() == SERVER_STATUS.ONLINE) { + createServerDisksTab(server, tabFolder, toolkit, site); + createServerLogsTab(server, tabFolder, toolkit); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java new file mode 100644 index 00000000..80c9c807 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +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.Bounds; +import org.eclipse.birt.chart.model.attribute.ChartDimension; +import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; +import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; +import org.eclipse.birt.chart.model.component.Series; +import org.eclipse.birt.chart.model.component.impl.SeriesImpl; +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.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.ChartWithoutAxesImpl; +import org.eclipse.birt.chart.model.layout.Legend; +import org.eclipse.birt.chart.model.layout.Plot; +import org.eclipse.birt.chart.model.type.PieSeries; +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; + +/** + * + */ +public final class PieChartViewerComposite extends Composite implements + PaintListener, IUpdateNotifier { + + private IDeviceRenderer deviceReader = null; + private Chart chart = null; + private GeneratedChartState generatedChartState = null; + private boolean needsGeneration = true; + + private static Logger logger = Logger + .getLogger(PieChartViewerComposite.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 PieChartViewerComposite(Composite parent, int style, String[] categories, + Double[] values) { + super(parent, style); + 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; + } + }); + + chart = createPieChart(categories, values); + addPaintListener(this); + } + + /** + * @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(2); + 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.getText().getFont().setSize(8); + 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.getSeriesPalette().shift(0); + sd.getSeries().add(seCategory); + + // Orthogonal Series + PieSeries sePie = (PieSeries) PieSeriesImpl.create(); + sePie.setDataSet(seriesOneValues); + sePie.setSeriesIdentifier("Cities");//$NON-NLS-1$ + sePie.getTitle().setVisible(false); + sePie.setExplosion(2); + + 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(58d / 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); + } + } + + /* + * (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.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java new file mode 100644 index 00000000..d634253e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class ServerTabCreator implements TabCreator { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + 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, "CPU Usage (%): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getCpuUsage(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + server.getTotalMemory(), SWT.NONE); + +// toolkit.createLabel(section, "Memory in Use (GB): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getMemoryInUse(), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(server.getTotalDiskSpace()), SWT.NONE); + +// toolkit.createLabel(section, "Disk Space in Use (GB): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getDiskSpaceInUse(), SWT.NONE); + } + + private void createServerSummaryTab(Server server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverSummaryTab = guiHelper.createTab(tabFolder, serverName, IImageKeys.SERVER); + final ScrolledForm form = guiHelper.setupForm(serverSummaryTab, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + serverSummaryTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createServerSummaryTab((Server) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java new file mode 100644 index 00000000..3e5382cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * 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.gui.views.details.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +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.Label; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.Text; +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.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +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.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage; + +public class VolumeTabCreator implements TabCreator { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private void createVolumePropertiesSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Properties", null, 3, false); + + createVolumeTypeField(volume, toolkit, section); + + VOLUME_TYPE volumeType = volume.getVolumeType(); + if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + createReplicaCountField(volume, toolkit, section); + } + + if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + createStripeCountField(volume, toolkit, section); + } + + createNumOfDisksField(volume, toolkit, section); + createDiskSpaceField(volume, toolkit, section); + createTransportTypeField(volume, toolkit, section); + createNASProtocolField(volume, toolkit, section); + createAccessControlField(volume, toolkit, section); + createStatusField(volume, toolkit, section); + } + + private void createDiskSpaceField(final Volume volume, FormToolkit toolkit, Composite section) { + Label diskSpaceLabel = toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + diskSpaceLabel.setToolTipText("boldnormal"); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(volume.getTotalDiskSpace()), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStatusField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Status: ", SWT.NONE); + + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(volume.getStatusStr()); + lblStatusValue.setImage(volume.getStatus() == Volume.VOLUME_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createTransportTypeField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Transport Type: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getTransportTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createNumOfDisksField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Number of Disks: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getNumOfDisks(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStripeCountField(final Volume volume, FormToolkit toolkit, 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(final Volume volume, FormToolkit toolkit, 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(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Volume Type: ", SWT.NONE); + toolkit.createLabel(section, volume.getVolumeTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); + } + + private void createVolumeAlertsSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 3, false); + toolkit.createLabel(section, "Volume related alerts will be displayed here"); + } + + private void createVolumeMountingInfoSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 3, false); + toolkit.createLabel(section, "Information about mounting the\nvolume will be printed here"); + } + + private GridData createDefaultLayoutData() { + GridData layoutData = new GridData(); + layoutData.minimumWidth = 150; + layoutData.widthHint = 150; + return layoutData; + } + + private void createAccessControlField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Access Control: ", SWT.NONE); + Text accessControlText = toolkit.createText(section, volume.getAccessControlList()); + accessControlText.setLayoutData(createDefaultLayoutData()); + accessControlText.setEnabled(false); + createChangeLinkForAccessControl(volume, toolkit, section, accessControlText); + } + + private void createChangeLinkForAccessControl(final Volume volume, FormToolkit toolkit, Composite section, + final Text accessControlText) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + // TODO: Validation of entered text + volume.setAccessControlList(accessControlText.getText()); + accessControlText.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + accessControlText.setEnabled(true); + 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 createNASProtocolField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "NAS Protocols: ", SWT.NONE); + + Composite nasProtocolsComposite = toolkit.createComposite(section); + nasProtocolsComposite.setLayout(new FillLayout()); + + createCheckbox(toolkit, nasProtocolsComposite, "Gluster", true); + final Button nfsCheckBox = createCheckbox(toolkit, nasProtocolsComposite, "NFS", volume.getNASProtocols().contains(NAS_PROTOCOL.NFS)); + + createChangeLinkForNASProtocol(volume, toolkit, section, nfsCheckBox); + } + + private void createChangeLinkForNASProtocol(final Volume volume, FormToolkit toolkit, Composite section, + final Button nfsCheckBox) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + if (nfsCheckBox.getSelection()) { + volume.enableNFS(); + } else { + volume.disableNFS(); + } + nfsCheckBox.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + nfsCheckBox.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (nfsCheckBox.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private Button createCheckbox(FormToolkit toolkit, Composite parent, String label, boolean selected) { + final Button checkBox = toolkit.createButton(parent, label, SWT.CHECK); + checkBox.setEnabled(false); + checkBox.setSelection(selected); + return checkBox; + } + + private void createVolumePropertiesTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, volume.getName() + " - Properties", IImageKeys.VOLUME); + final ScrolledForm form = guiHelper.setupForm(volumeTab, toolkit, "Volume Properties [" + volume.getName() + "]"); + createVolumePropertiesSection(volume, toolkit, form); + createVolumeMountingInfoSection(volume, toolkit, form); + createVolumeAlertsSection(volume, toolkit, form); + + volumeTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeLogsTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, "Logs", IImageKeys.VOLUME); + VolumeLogsPage logsPage = new VolumeLogsPage(volumeTab, SWT.NONE, volume); + + volumeTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeDisksTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite volumeDisksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.VOLUME); + DisksPage page = new DisksPage(volumeDisksTab, SWT.NONE, site, volume.getDisks()); + + volumeDisksTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeOptionsTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, "Options", IImageKeys.VOLUME); + VolumeOptionsPage page = new VolumeOptionsPage(volumeTab, SWT.NONE, volume); + + volumeTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createVolumePropertiesTab((Volume) entity, tabFolder, toolkit); + createVolumeDisksTab((Volume) entity, tabFolder, toolkit, site); + createVolumeOptionsTab((Volume) entity, tabFolder, toolkit); + createVolumeLogsTab((Volume) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java new file mode 100644 index 00000000..d7ef44ac --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/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.gui.views.navigator; + +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.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; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; + +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; + } + + if(object instanceof EntityGroup) { + Class entityType = ((EntityGroup) object).getEntityType(); + if(entityType == Volume.class) { + iconPath = IImageKeys.VOLUMES; + } else { + iconPath = IImageKeys.SERVERS; + } + } + + if(object instanceof Volume) { + iconPath = IImageKeys.VOLUME; + } + + if(object instanceof Server || object instanceof GlusterServer) { + iconPath = IImageKeys.SERVER; + } + + 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.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java new file mode 100644 index 00000000..4cdc2e66 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/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.gui.views.navigator; + +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.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; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; + +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)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE)); + } + } + + 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)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE)); + } + } + + if (element instanceof Server) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR)); + } + + if(element instanceof EntityGroup && ((EntityGroup)element).getEntityType() == Server.class) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR)); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java new file mode 100644 index 00000000..6be3e78c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * 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.gui.views.pages; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +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.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.ServerTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class ServersPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + 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 enum SERVER_DISK_TABLE_COLUMN_INDICES { + // NAME, NUM_OF_CPUS, CPU_USAGE, TOTAL_MEMORY, MEMORY_IN_USE, TOTAL_DISK_SPACE, DISK_SPACE_IN_USE + // }; + // + // private static final String[] SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", + // "Number\nof CPUs", "CPU\nUsage (%)", "Total\nMemory (GB)", "Memory\nIn Use (GB)", + // "Total Disk\n Space (GB)", "Disk Space\nin Use (GB)"}; + + public ServersPage(final Composite parent, IWorkbenchSite site, EntityGroup servers) { + super(parent, SWT.NONE); + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + setupPage(site, servers); + parent.layout(); // Important - this actually paints the table + + /** + * 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(); + } + }); + } + + public void setInput(EntityGroup servers) { + tableViewer.setInput(servers); + tableViewer.refresh(); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupServerTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, SERVER_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + 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); + } + + private TableViewer createServerTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new ServerTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider()); + + setupServerTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private void setupPage(IWorkbenchSite site, EntityGroup servers) { + Text filterText = guiHelper.createFilterText(toolkit, this); + + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createServerTableViewer(tableViewerComposite); + site.setSelectionProvider(tableViewer); + + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + + tableViewer.setInput(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.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java new file mode 100644 index 00000000..9e25a018 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * 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.gui.views.pages; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +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.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.VolumeTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumesPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum VOLUME_TABLE_COLUMN_INDICES { + NAME, VOLUME_TYPE, NUM_OF_DISKS, TRANSPORT_TYPE, VOLUME_STATUS + }; + + private static final String[] VOLUME_TABLE_COLUMN_NAMES = new String[] { "Name", + "Volume Type", "Number of\nDisks", "Transport Type", "Status" }; + + public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup volumes) { + super(parent, SWT.NONE); + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + setupVolumeTableViewer(site, volumes); + + parent.layout(); // Important - this actually paints the table + + /** + * 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(); + } + }); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupVolumeTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(true); + + TableColumnLayout columnLayout = guiHelper.createTableColumnLayout(table, VOLUME_TABLE_COLUMN_NAMES); + parent.setLayout(columnLayout); + + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.NUM_OF_DISKS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.TRANSPORT_TYPE, SWT.CENTER, 70); + } + + private TableViewer createVolumeTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider()); + + setupVolumeTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + 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)); + return tableViewerComposite; + } + + private void setupVolumeTableViewer(IWorkbenchSite site, EntityGroup volumes) { + Text filterText = guiHelper.createFilterText(toolkit, this); + + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createVolumeTableViewer(tableViewerComposite); + site.setSelectionProvider(tableViewer); + + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + tableViewer.setInput(volumes); + } + + /** + * 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)); + } + + public void setInput(EntityGroup volumes) { + tableViewer.setInput(volumes); + tableViewer.refresh(); + } +} diff --git a/src/com.gluster.storage.management.releng/.project b/src/com.gluster.storage.management.releng/.project new file mode 100644 index 00000000..f4723731 --- /dev/null +++ b/src/com.gluster.storage.management.releng/.project @@ -0,0 +1,17 @@ + + + com.gluster.storage.management.releng + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/src/com.gluster.storage.management.releng/build.properties b/src/com.gluster.storage.management.releng/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/src/com.gluster.storage.management.releng/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery new file mode 100644 index 00000000..7bb4b868 --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery @@ -0,0 +1,4 @@ + + + + diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery new file mode 100644 index 00000000..a97d350d --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery @@ -0,0 +1,4 @@ + + + + diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery new file mode 100644 index 00000000..4d5dc425 --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery @@ -0,0 +1,4 @@ + + + + diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery new file mode 100644 index 00000000..346b39bf --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery @@ -0,0 +1,4 @@ + + + + diff --git a/src/com.gluster.storage.management.releng/feature.xml b/src/com.gluster.storage.management.releng/feature.xml new file mode 100644 index 00000000..22a0938f --- /dev/null +++ b/src/com.gluster.storage.management.releng/feature.xml @@ -0,0 +1,20 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + diff --git a/src/com.gluster.storage.management.releng/gluster-management-console.target b/src/com.gluster.storage.management.releng/gluster-management-console.target new file mode 100644 index 00000000..e30fcf49 --- /dev/null +++ b/src/com.gluster.storage.management.releng/gluster-management-console.target @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.releng/glustermc.rmap b/src/com.gluster.storage.management.releng/glustermc.rmap new file mode 100644 index 00000000..e4048df6 --- /dev/null +++ b/src/com.gluster.storage.management.releng/glustermc.rmap @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.releng/glustermc_build.properties b/src/com.gluster.storage.management.releng/glustermc_build.properties new file mode 100644 index 00000000..b808ec9d --- /dev/null +++ b/src/com.gluster.storage.management.releng/glustermc_build.properties @@ -0,0 +1,10 @@ +# Where all the output should go +buckminster.output.root=/tmp/buckminster/glustermc +# Where the temp files should go +buckminster.temp.root=/tmp/buckminster +# How .qualifier in versions should be replaced +qualifier.replacement.*=generator:lastRevision + +target.os=linux +target.ws=gtk +target.arch=x86_64 diff --git a/src/com.gluster.storage.management.server.scripts/.project b/src/com.gluster.storage.management.server.scripts/.project new file mode 100644 index 00000000..beda33b7 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/.project @@ -0,0 +1,17 @@ + + + com.gluster.storage.management.server.scripts + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/src/com.gluster.storage.management.server.scripts/.pydevproject b/src/com.gluster.storage.management.server.scripts/.pydevproject new file mode 100644 index 00000000..0a912df5 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/.pydevproject @@ -0,0 +1,10 @@ + + + + +Default +python 3.0 + +/com.gluster.storage.management.server.scripts/src + + diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Commands.py b/src/com.gluster.storage.management.server.scripts/src/common/Commands.py new file mode 100644 index 00000000..c728b565 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Commands.py @@ -0,0 +1,78 @@ +COMMAND_CREATE_VOLUME = "create-volume" +COMMAND_DELETE_VOLUME = "delete-volume" +COMMAND_START_VOLUME = "start-volume" +COMMAND_STOP_VOLUME = "stop-volume" +COMMAND_GET_VOLUME_HEALTH_STATUS = "get-volume-health-status" +COMMAND_GET_VOLUME_LIST = "get-volume-list" +COMMAND_GET_VOLUME_LOG = "get-volume-log" +COMMAND_CLEAR_VOLUME_LOGS = "clear-volume-logs" +COMMAND_GET_VOLUME_PROPERTY = "get-volume-property" +COMMAND_SET_VOLUME_PROPERTY = "set-volume-property" +COMMAND_GET_VOLUME_STATUS = "get-volume-status" +COMMAND_DOWNLOAD_VOLUME_LOGS = "download-volume-logs" +COMMAND_DELETE_SERVER = "delete-server" +COMMAND_GET_SERVER_DATE = "get-server-date" +COMMAND_GET_SERVER_VERSION_INFO = "get-server-version-info" +COMMAND_GET_INSTALLER_INFO = "get-installer-info" +COMMAND_GET_SERVER_LIST = "get-server-list" +COMMAND_GET_SERVER_SERVICE_STATUS = "get-server-service-status" +COMMAND_GET_STORAGE_SERVER_POOL_INFO = "get-storage-server-pool-info" +COMMAND_INSTALL_SERVER_BACKGROUND = "install-server-background" +COMMAND_PREPARE_DATA_DISK_BACKGROUND = "prepare-data-disk-background" +COMMAND_SET_SERVER_DATE = "set-server-date" +COMMAND_SET_SERVER_NETWORK_CONFIG = "set-server-network-config" +COMMAND_SET_STORAGE_SERVER_POOL_INFO = "set-storage-server-pool-info" +COMMAND_GET_SERVER_NETWORK_CONFIG = "get-server-network-config" +COMMAND_INSTALL_SERVER_STATUS = "install-server-status" +COMMAND_GET_SERVER_DISK_LIST = "get-server-disk-list" +COMMAND_PREPARE_DATA_DISK_STATUS = "prepare-data-disk-status" +COMMAND_GET_SERVER_SYSTEM_RESOURCE = "get-server-system-resource" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SHUTDOWN_SERVER = "shutdown-server" +COMMAND_GET_SERVER_STATUS = "get-server-status" +COMMAND_GET_SERVER_LOG = "get-server-log" +COMMAND_DOWNLOAD_SERVER_LOGS = "download-server-logs" +COMMAND_CLEAR_SERVER_LOGS = "clear-server-logs" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_GET_GSN_USER_INFO = "get-gsn-user-info" +COMMAND_SET_GSN_USER_INFO = "set-gsn-user-info" +COMMAND_GET_GLUSTER_UPDATE_INFO = "get-gluster-update-info" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_BACKGROUND = "download-gluster-update-background" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_STATUS = "download-gluster-update-status" +COMMAND_INSTALL_GLUSTER_UPDATE = "install-gluster-update" +COMMAND_EXPORT_CONFIG = "export-config" +COMMAND_IMPORT_CONFIG = "import-config" +COMMAND_SET_SYSTEM_PASSWORD = "set-system-password" +COMMAND_GET_SERVER_VOLUME_LIST = "get-server-volume-list" +COMMAND_RECONFIGURE_VOLUME = "reconfigure-volume" +COMMAND_SET_SERVER_DIRECTORY_SERVICE_CONFIG = "set-server-directory-service-config" +COMMAND_GET_SERVER_DIRECTORY_SERVICE_CONFIG = "get-server-directory-service-config" +COMMAND_JOIN_SERVER_TO_DIRECTORY_SERVICE = "join-server-to-directory-service" +COMMAND_SET_SERVER_TIME_CONFIG = "set-server-time-config" +COMMAND_GET_SERVER_TIME_CONFIG = "get-server-time-config" +COMMAND_LOGIN = "login" +COMMAND_LOGOUT = "logout" +COMMAND_GET_LOGIN_STATUS = "get-login-status" +COMMAND_GET_SERVER_TRANSPORT_LIST = "get-server-transport-list" +COMMAND_ADD_SERVER_PARTITION = "add-server-partition" +COMMAND_ADD_VOLUME_USER = "add-volume-user" +COMMAND_GET_PARTITION_VOLUME_LIST = "get-partition-volume-list" +COMMAND_GET_VOLUME_USER_INFO = "get-volume-user-info" +COMMAND_GET_VOLUME_USER_LIST = "get-volume-user-list" +COMMAND_MIGRATE_PARTITION_BACKGROUND = "migrate-partition-background" +COMMAND_MIGRATE_PARTITION_STATUS = "migrate-partition-status" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_BACKGROUND = "migrate-volume-server-partition-background" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_STATUS = "migrate-volume-server-partition-status" +COMMAND_REMOVE_SERVER_PARTITION = "remove-server-partition" +COMMAND_REMOVE_VOLUME_USER = "remove-volume-user" +COMMAND_RENAME_VOLUME_USER = "rename-volume-user" +COMMAND_RENAME_VOLUME = "rename-volume" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SET_VOLUME_USER_PASSWORD = "set-volume-user-password" +COMMAND_STOP_PARTITION_MIGRATION = "stop-partition-migration" +COMMAND_STOP_VOLUME_SERVER_PARTITION_MIGRATION = "stop-volume-server-partition-migration" +COMMAND_GET_SERVER_DISK_INFO = "get-server-disk-info" +COMMAND_INITIALIZE_SERVER_DISK = "initialize-server-disk" +COMMAND_SET_SERVER_COUNT = "set-server-count" +COMMAND_GET_SERVER_COUNT = "get-server-count" diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Common.py b/src/com.gluster.storage.management.server.scripts/src/common/Common.py new file mode 100644 index 00000000..60f200fe --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Common.py @@ -0,0 +1,34 @@ +# Copyright (c) 2009 Gluster, Inc. +# This file is part of GlusterSP. +# +# GlusterSP is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# GlusterSP 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog + +def log(priority, message=None): + if type(priority) == type(""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + if not logMessage: + return + #if Globals.DEBUG: + # sys.stderr.write(logMessage) + else: + syslog.syslog(logPriority, logMessage) + return diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Globals.py b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py new file mode 100644 index 00000000..365d4af7 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py @@ -0,0 +1,119 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +MULTICAST_GROUP = '224.224.1.1' +MULTICAST_PORT = 5353 +GLUSTER_PLATFORM_VERSION = "3.2" + +## System configuration constants +SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" +DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" + +FSTAB_FILE = "/etc/fstab" +NFS_EXPORTS_FILE = "/etc/exports" +SAMBA_CONF_FILE = "/etc/samba/smb.conf" +TIMEZONE_FILE = "/etc/timezone" +ZONEINFO_DIR = "/usr/share/zoneinfo" +LOCALTIME_FILE = "/etc/localtime" +KERBEROS_CONF_FILE = "/etc/krb5.conf" +NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" +NTP_CONF_FILE = "/etc/ntp.conf" +MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" +SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" +RESOLV_CONF_FILE = "/etc/resolv.conf" +DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" +LIVE_MODE_FILE = "/etc/live" +ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" + +DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" +DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" +## + +## Base constants +MAX_PARTITION_SIZE = 16777216 # 16 TB +OS_PARTITION_SIZE = 4000 # 4 GB +SESSION_TIMEOUT = 1800 # 30 minutes +SERVER_AGENT_PORT = 50000 + +BOOT_PARTITION_LABEL = "GLUSTEROS" +DATA_PARTITION_LABEL = "GLUSTERDATA" +VOLUME_USER_DESCRIPTION = "Gluster Volume User" +SERVER_AGENT_RUN_USERNAME = "transport" +INSTALLER_SERVER_NAME = "$installer$" + +GLUSTER_BASE_DIR = "/GLUSTER" +GLUSTER_LUN_DIR = "/data" +REEXPORT_DIR = "/reexport" +NFS_EXPORT_DIR = "/nfs" +CIFS_EXPORT_DIR = "/cifs" +WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" +UPDATES_DIR = "/UPDATES" +TRANSPORT_HOME_DIR = "/transport" +GLUSTERFS_LOG_DIR = "/var/log/glusterfs" +LOG_DIR = "/var/log/platform" + +GLUSTER_UPDATES_FILE = "updates.xml" +INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" +INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" +LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" +PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" +## + +## Derived constants +GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" +GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" +VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" +SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" +DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" +INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME + +GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" +GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" +GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" +GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" +GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" +TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" +SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" +SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" +GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" +GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" + +VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" + +GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" +INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" +INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" +INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" + +SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" + +GENERAL_LOG_FILE = LOG_DIR + "/general.log" +INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" +SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" +TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" +## + + +## Global variables +## TODO: These should be removed +DOWNLOAD_GLUSTER_UPDATE_PROCESS = None +DOWNLOAD_GLUSTER_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None +REQUEST_MAP = {} +VERSION_DICTONARY = {} +## diff --git a/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py b/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py new file mode 100644 index 00000000..1ce1b132 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py @@ -0,0 +1,422 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys + +if not "/usr/share/system-config-network/" in sys.path: + sys.path.append("/usr/share/system-config-network") + +import os +import tempfile +import Globals + +from Utils import * +from netconfpkg.NCHardwareList import getHardwareList + +def readHostFile(fileName=None): + hostEntryList = [] + if not fileName: + fileName = "/etc/hosts" + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + hostEntryList.append({tokens[0] : tokens[1:]}) + return hostEntryList + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeHostFile(hostEntryList, fileName=None): + if fileName: + hostFile = fileName + else: + hostFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(hostFile, "w") + for host in hostEntryList: + fp.write("%s\t%s\n" % (host.keys()[0], " ".join(host.values()[0]))) + fp.close() + if hostFile == fileName: + return True + except IOError: + log("failed to write %s file" % hostFile) + return False + if runCommandFG("mv -f %s /etc/hosts" % hostFile, root=True) != 0: + log("failed to rename file %s to /etc/hosts" % hostFile) + return False + return True + + +def readResolvConfFile(fileName=None, includeLocalHost=False): + nameServerList = [] + domain = None + searchDomain = None + if not fileName: + fileName = Globals.RESOLV_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + if tokens[0].upper() == "NAMESERVER": + if includeLocalHost == False and tokens[1] == "127.0.0.1": + continue + nameServerList.append(tokens[1]) + continue + if tokens[0].upper() == "DOMAIN": + domain = tokens[1:] + continue + if tokens[0].upper() == "SEARCH": + searchDomain = tokens[1:] + continue + return nameServerList, domain, searchDomain + except IOError: + log("failed to read %s file" % fileName) + return None, None, None + + +def writeResolvConfFile(nameServerList, domain, searchDomain, fileName=None, appendLocalHost=True): + if fileName: + resolvConfFile = fileName + else: + resolvConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(resolvConfFile, "w") + if appendLocalHost: + fp.write("nameserver 127.0.0.1\n") + for nameServer in nameServerList: + fp.write("nameserver %s\n" % nameServer) + if domain: + fp.write("domain %s\n" % " ".join(domain)) + if searchDomain: + fp.write("search %s\n" % " ".join(searchDomain)) + fp.close() + if resolvConfFile == fileName: + return True + except IOError: + log("failed to write %s file" % resolvConfFile) + return False + if runCommandFG("mv -f %s %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE), root=True) != 0: + log("failed to rename file %s to %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE)) + return False + return True + + +def readIfcfgConfFile(deviceName, root=""): + conf = {} + fileName = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + try: + for line in open(fileName): + tokens = line.split("#")[0].split("=") + if len(tokens) != 2: + continue + conf[tokens[0].strip().lower()] = tokens[1].strip() + return conf + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeIfcfgConfFile(deviceName, conf, root="", deviceFile=None): + if not deviceFile: + deviceFile = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + if root: + ifcfgConfFile = deviceFile + else: + ifcfgConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(ifcfgConfFile, "w") + for key in conf.keys(): + if key == "description": + fp.write("#%s=%s\n" % (key.upper(), conf[key])) + continue + if key in ['link', 'mode']: + continue + if conf["device"].startswith("bond") and key in ['hwaddr', 'master', 'slave']: + continue + if key == "slave" and conf['master']: + fp.write("SLAVE=yes\n") + continue + if key == "onboot": + if conf[key] == True: + fp.write("ONBOOT=yes\n") + elif isString(conf[key]) and conf[key].upper() == "YES": + fp.write("ONBOOT=yes\n") + else: + fp.write("ONBOOT=no\n") + continue + if not conf[key]: + continue + fp.write("%s=%s\n" % (key.upper(), conf[key])) + fp.close() + if ifcfgConfFile == deviceFile: + return True + except IOError: + log("failed to write %s file" % ifcfgConfFile) + return False + if runCommandFG("mv -f %s %s" % (ifcfgConfFile, deviceFile), root=True) != 0: + log("failed to rename file %s to %s" % (ifcfgConfFile, deviceFile)) + return False + return True + + +def getLinkStatus(deviceName): + return True + ## ethtool takes very long time to respond. So its disabled now + rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) + if rv["Status"] != 0: + return False + for line in rv["Stdout"].split("\n"): + tokens = line.strip().split(":") + if tokens[0].upper() == "LINK DETECTED": + if tokens[1].strip().upper() == "YES": + return True + else: + return False + return False + + +def getBondMode(deviceName, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].split() + if len(tokens) < 4: + continue + if tokens[0].upper() == "OPTIONS" and tokens[1] == deviceName: + if tokens[2].startswith("mode="): + return tokens[2].split("=")[1] + if tokens[3].startswith("mode="): + return tokens[3].split("=")[1] + if tokens[4].startswith("mode="): + return tokens[4].split("=")[1] + if tokens[5].startswith("mode="): + return tokens[5].split("=")[1] + return None + except IOError: + log("failed to read %s file" % fileName) + return None + + +def setBondMode(deviceName, mode, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + tempFileName = getTempFileName() + try: + fp = open(tempFileName, "w") + lines = open(fileName).readlines() + except IOError: + log("unable to open file %s" % Globals.MODPROBE_CONF_FILE) + return False + for line in lines: + tokens = line.split() + if len(tokens) > 1 and "OPTIONS" == tokens[0].upper() and "BOND" in tokens[1].upper() and deviceName == tokens[1]: + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + deviceName = None + continue + fp.write(line) + if deviceName: + fp.write("alias %s bonding\n" % deviceName) + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + fp.close() + if runCommandFG(["mv", "-f", tempFileName, fileName], root=True) != 0: + log("unable to move file from %s to %s" % (tempFileName, fileName)) + return False + return True + +def getNetDeviceList(root=""): + netDeviceList = [] + for device in getHardwareList(): + netDevice = {} + netDevice["device"] = None + netDevice["description"] = None + netDevice["hwaddr"] = None + netDevice["type"] = None + netDevice["onboot"] = None + netDevice["bootproto"] = None + netDevice["ipaddr"] = None + netDevice["netmask"] = None + netDevice["gateway"] = None + netDevice["peerdns"] = None + netDevice["autodns"] = None + netDevice["dns1"] = None + netDevice["dns2"] = None + netDevice["dns3"] = None + netDevice["master"] = None + netDevice["slave"] = None + netDevice["nmcontrolled"] = None + netDevice["link"] = None + netDevice["mode"] = None + + netDevice["device"] = device.Name + netDevice["description"] = device.Description + netDevice["type"] = device.Type + netDevice["link"] = getLinkStatus(device.Name) + netDevice["mode"] = getBondMode(device.Name, root + Globals.MODPROBE_CONF_FILE) + try: + netDevice["hwaddr"] = open("/sys/class/net/%s/address" % device.Name).read().strip() + except IOError: + pass + netDeviceList.append(netDevice) + + conf = readIfcfgConfFile(device.Name, root) + if not conf: + continue + try: + netDevice["onboot"] = conf["onboot"] + except KeyError: + pass + try: + netDevice["bootproto"] = conf["bootproto"] + except KeyError: + pass + try: + netDevice["ipaddr"] = conf["ipaddr"] + except KeyError: + pass + try: + netDevice["netmask"] = conf["netmask"] + except KeyError: + pass + try: + netDevice["gateway"] = conf["gateway"] + except KeyError: + pass + try: + netDevice["peerdns"] = conf["peerdns"] + except KeyError: + pass + try: + netDevice["autodns"] = conf["autodns"] + except KeyError: + pass + try: + netDevice["dns1"] = conf["dns1"] + except KeyError: + pass + try: + netDevice["dns2"] = conf["dns2"] + except KeyError: + pass + try: + netDevice["dns3"] = conf["dns3"] + except KeyError: + pass + try: + netDevice["master"] = conf["master"] + except KeyError: + pass + try: + netDevice["slave"] = conf["slave"] + except KeyError: + pass + try: + netDevice["nmcontrolled"] = conf["nmcontrolled"] + except KeyError: + pass + + return netDeviceList + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + ## for deviceName in bondDevices: + ## if deviceName in linkedBondList: + ## if deviceName in sysConfigDeviceList: + ## deviceList[deviceName] = sysConfigDeviceList[deviceName] + ## else: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + ## continue + ## if len(ethDevices) > 2: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + + +def configureDhcpServer(serverIpAddress, dhcpIpAddress): + tmpDhcpConfFile = tempfile.mktemp(prefix="GSPSA") + + serverPortString = "68" + try: + for arg in open("/proc/cmdline").read().strip().split(): + token = arg.split("=") + if token[0] == "dhcp": + serverPortString = token[1] + break + except IOError: + log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") + try: + serverPort = int(serverPortString) + except ValueError: + log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) + serverPort = 68 + + try: + fp = open(tmpDhcpConfFile, "w") + fp.write("bind-interfaces\n") + fp.write("except-interface=lo\n") + fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) + fp.write("dhcp-lease-max=1\n") + fp.write("dhcp-alternate-port=%s\n" % serverPort) + fp.write("dhcp-leasefile=%s\n" % Globals.DNSMASQ_LEASE_FILE) + #fp.write("server=%s\n" % serverIpAddress) + #fp.write("dhcp-script=/usr/sbin/server-info\n") + fp.close() + except IOError: + log(syslog.LOG_ERR, "unable to write dnsmasq dhcp configuration %s" % tmpDhcpConfFile) + return False + if runCommandFG("mv -f %s %s" % (tmpDhcpConfFile, Globals.DNSMASQ_DHCP_CONF_FILE), root=True) != 0: + log(syslog.LOG_ERR, "unable to copy dnsmasq dhcp configuration to %s" % Globals.DNSMASQ_DHCP_CONF_FILE) + return False + return True + + +def isDhcpServer(): + return os.path.exists(Globals.DNSMASQ_DHCP_CONF_FILE) + + +def getDhcpServerStatus(): + if runCommandFG("service dnsmasq status", root=True) == 0: + return True + return False + + +def startDhcpServer(): + if runCommandFG("service dnsmasq start", root=True) == 0: + return True + return False + + +def stopDhcpServer(): + if runCommandFG("service dnsmasq stop", root=True) == 0: + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return True + return False + + +def restartDhcpServer(): + stopDhcpServer() + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return startDhcpServer() + + +def reloadDhcpServer(): + if runCommandFG("service dnsmasq reload", root=True) == 0: + return True + return False diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py b/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py @@ -0,0 +1,438 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc.strip() + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTextNode(self, text): + if not self._domObj: + return False + if not text: + return False + return self._domObj.createTextNode(str(text)) + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def getAttribute(self, attributeName): + if not attributeName: + return None + try: + return self.getElementsByTagName("command")[0].getAttribute(attributeName) + except IndexError: + return False + + def setAttribute(self, attributeName, attributeValue): + if not (attributeName and attributeValue): + return None + try: + return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue) + except IndexError: + return False + + def getRequestCommand(self): + return self.getAttribute("request") + + def getResponseCommand(self): + return self.getAttribute("response") + + def getResponseCode(self): + return self.getAttribute("response-code") + + def getMessageId(self): + return self.getAttribute("id") + + def getVersion(self): + return self.getAttribute("version") + + def getRequestAction(self): + return self.getAttribute("action") + + def setVersion(self, value): + return self.setAttribute("version", value) + + def setRequestAction(self, value): + return self.setAttribute("action", value) + + def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + commandTag = self._domObj.createElement("command") + commandTag.setAttribute("response", command) + commandTag.setAttribute("response-code", responseCode) + commandTag.setAttribute("id", id) + commandTag.setAttribute("version", version) + return commandTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + +class ResponseXml(XDOM): + _commandTag = None + def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + XDOM.__init__(self) + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + + def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + return True + return False + + def append(self, tagName, tagValue=None): + if not self._commandTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._commandTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._commandTag: + return False + self._commandTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._commandTag: + return False + if not tagRoute: + return False + + parentTagE = self._commandTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def appendTagRouteOld(self, tagRoute, value=None): + if not tagRoute: + return False + if not self._commandTag: + return False + + tmpTagRoute = "" + previousTagE = self._commandTag + tagE = None + for tagName in tagRoute.split("."): + if not tmpTagRoute: + tagE = self.getElementsByTagRoute("command." + tagName) + else: + tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName) + if not tagE: + break + if len(tagE) != 1: + return False + previousTagE = tagE[0] + if not tmpTagRoute: + tmpTagRoute = tagName + else: + tmpTagRoute = tmpTagRoute + "." + tagName + + if tmpTagRoute == tagRoute: + return False + newTagRoute = tagRoute[len(tmpTagRoute):] + if newTagRoute[0] == '.': + newTagRoute = newTagRoute[1:] + + if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE: + return False + previousTagE.appendChild(self.createTagRoute(newTagRoute, value)) + return True +##--end of ResponseXml + +def test(): + #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume") + requestStr = ''' + +movies1 +cluster mirror +512000 +zresearch +192.168.20.* +192.168.30.* + +no + + +no + + +no + + +''' + + requestXml = RequestXml(requestStr) + print requestXml.getAttribute("") + +def test1(): + rs = ResponseXml("create-volume", "OK", "xyz") + rs.appendTagRoute("volume.detail.name", "music") + print rs.toprettyxml() + rs.append("volume", "data") + print rs.toprettyxml() + rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1") + print rs.toprettyxml() + print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::") + print rs.toprettyxml() + + print rs.getTextByTagRoute("command.volume.detail") + +def test2(): + rs = ResponseXml("download-volume-logs", "OK", "xyz") + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE1")) + te.appendChild(rs.createTag("description", "my device one")) + rs.appendTag(te) + + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE2")) + te.appendChild(rs.createTag("description", "my device two")) + rs.appendTag(te) + print rs.toprettyxml() + diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Utils.py b/src/com.gluster.storage.management.server.scripts/src/common/Utils.py new file mode 100644 index 00000000..c605eecd --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Utils.py @@ -0,0 +1,704 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import os +import re +import socket +import struct +import syslog +import subprocess +#import spwd +import time +#import uuid +import tempfile +import grp +import pwd +import inspect +from datetime import datetime +import urllib + +import Globals +import Protocol + + +RUN_COMMAND_ERROR = -1024 +LOG_SYSLOG = 1 +SYSLOG_REQUIRED = False +LOG_FILE_NAME = None +LOG_FILE_OBJ = None + + +def _getLogCode(priority): + if syslog.LOG_EMERG == priority: + return "M" + elif syslog.LOG_ALERT == priority: + return "A" + elif syslog.LOG_CRIT == priority: + return "C" + elif syslog.LOG_ERR == priority: + return "E" + elif syslog.LOG_WARNING == priority: + return "W" + elif syslog.LOG_NOTICE == priority: + return "N" + elif syslog.LOG_INFO == priority: + return "I" + elif syslog.LOG_DEBUG == priority: + return "D" + else: # UNKNOWN + return "X" + + +def setLogFile(fileName): + global LOG_FILE_NAME + + if fileName: + LOG_FILE_NAME = fileName + return True + return False + + +def closeLog(): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if SYSLOG_REQUIRED: + syslog.closelog() + SYSLOG_REQUIRED = False + return True + + if LOG_FILE_OBJ: + try: + LOG_FILE_OBJ.close() + LOG_FILE_OBJ = None + except IOError, e: + sys.stderr.write("Failed to close file: %s\n" % e) + return False + return True + + +def openLog(fileName=None): + global LOG_FILE_NAME + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if fileName == LOG_SYSLOG: + syslog.openlog(os.path.basename(sys.argv[0])) + SYSLOG_REQUIRED = True + return True + + if fileName: + LOG_FILE_NAME = fileName + + if not LOG_FILE_NAME: + return False + + closeLog() + + try: + LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") + except IOError, e: + sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) + return False + return True + + +def log(priority, message=None): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + stack = inspect.stack()[1] + if stack[3] == "": + prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3]) + else: + prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3]) + + if type(priority) == type("") or type(priority) == type(u""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + + if SYSLOG_REQUIRED: + syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage)) + return + + fp = sys.stderr + if LOG_FILE_OBJ: + fp = LOG_FILE_OBJ + + fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage)) + if logMessage[-1] != '\n': + fp.write("\n") + fp.flush() + return + + +def trace(message): + if message: + log(syslog.LOG_DEBUG, message) + + +def isString(value): + return (type(value) == type("") or type(value) == type(u"")) + + +def getTempFileName(): + return tempfile.mkstemp(prefix="GSP_")[1] + + +def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, + shell=False, root=None): + log("runCommandBG(): Trying to execute command [%s]" % command) + + if shell: + if not isString(command): + return None + else: + if isString(command): + command = command.split() + + if root == True: + if shell: + command = "sudo " + command + else: + command = ['sudo'] + command + elif isString(root): + if shell: + command = "sudo -u " + root + " " + command + else: + command = ['sudo', '-u', root] + command + + if not stdinFileObj: + stdinFileObj=subprocess.PIPE + if not stdoutFileObj: + stdoutFileObj=subprocess.PIPE + if not stderrFileObj: + stderrFileObj=subprocess.PIPE + + try: + process = subprocess.Popen(command, + bufsize=-1, + stdin=stdinFileObj, + stdout=stdoutFileObj, + stderr=stderrFileObj, + shell=shell) + return process + except OSError, e: + log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) + return None + + +def runCommand(command, + input='', output=False, + shell=False, root=None): + rv = {} + rv["Status"] = RUN_COMMAND_ERROR + rv["Stdout"] = None + rv["Stderr"] = None + + try: + stdinFileName = getTempFileName() + stdinFileObj = open(stdinFileName, "w") + stdinFileObj.write(input) + stdinFileObj.close() + stdinFileObj = open(stdinFileName, "r") + + stdoutFileName = getTempFileName() + stdoutFileObj = open(stdoutFileName, "w") + + stderrFileName = getTempFileName() + stderrFileObj = open(stderrFileName, "w") + except IOError, e: + log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) + if output: + return rv + return rv["Status"] + + stdoutContent = None + stderrContent = None + + process = runCommandBG(command, + stdinFileObj=stdinFileObj, + stdoutFileObj=stdoutFileObj, + stderrFileObj=stderrFileObj, + shell=shell, root=root) + if process: + rv['Status'] = process.wait() + rv['Stdout'] = open(stdoutFileName).read() + rv['Stderr'] = open(stderrFileName).read() + + os.remove(stdinFileName) + os.remove(stdoutFileName) + os.remove(stderrFileName) + + log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) + + if output: + return rv + return rv["Status"] + + +def runCommandFG(command, stdout=False, stderr=False, + shell=False, root=None): + if stdout or stderr: + output = True + else: + output = False + return runCommand(command, output=output, shell=shell, root=root) + + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + + +def computeHostName(hostName): + if not hostName: + return False + + hostPrefix = "" + for i in range(len(hostName), 0, -1): + pos = i - 1 + if hostName[pos].isdigit(): + continue + break + hostPrefix = hostName[:pos+1] + try: + hostIndex = int(hostName[pos+1:]) + except ValueError: + hostIndex = 0 + # TODO: Check the availablity of the (server) name + return "%s%s" % (hostPrefix, hostIndex + 1) + + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + + +def getDownloadStatus(fileName): + try: + lines = [line for line in open(fileName) + if "saved" in line or "%" in line] + except IOError: + return 0 + if not lines: + return 0 + if "saved" in lines[-1]: + return 100 + return lines[-1].split("%")[0].split()[-1] + + +def getMeminfo(): + """-> dict of data from meminfo (str:int). + Values are in kilobytes. + """ + import re + re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB' ) + result = {} + for line in open('/proc/meminfo'): + match = re_parser.match(line) + if not match: + continue # skip lines that don't parse + key, value = match.groups(['key', 'value']) + result[key] = int(value) + return result + + +def getCpuUsage(): + """-> dict of cpuid : (usertime, nicetime, systemtime, idletime) + cpuid "cpu" means the total for all CPUs. + cpuid "cpuN" means the value for CPU N. + """ + wanted_records = [line for line in open('/proc/stat') if + line.startswith('cpu')] + result = {} + for cpuline in wanted_records: + fields = cpuline.split()[:5] + data = map(int, fields[1:]) + result[fields[0]] = tuple(data) + return result + + +def getLoadavg(): + """-> 5-tuple containing the following numbers in order: + - 1-minute load average (float) + - 5-minute load average (float) + - 15-minute load average (float) + - Number of threads/processes currently executing (<= number of + CPUs) (int) + - Number of threads/processes that exist on the system (int) + - The PID of the most recently-created process on the system (int) + """ + loadavgstr = open('/proc/loadavg', 'r').readline().strip() + data = loadavgstr.split() + avg1, avg5, avg15 = map(float, data[:3]) + threads_and_procs_running, threads_and_procs_total = map(int, + data[3].split('/')) + most_recent_pid = int(data[4]) + ncpus = 1 + final_avg = "" + if hasattr(os, "sysconf"): + if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): + # Linux + ncpus = os.sysconf("SC_NPROCESSORS_ONLN") + if isinstance(ncpus, int) and ncpus > 0: + final_avg = "%.2f" % (1.0 * avg1 / ncpus) + + # Future return everything when needed + # Commenting this for the time being + # avg5, avg15, threads_and_procs_running, threads_and_procs_total, most_recent_pid + return final_avg + + +def getInfinibandPortStatus(): + + """ Check for availability of infiniband port + and return which port is active in a key pair value + """ + + # Check for existence of infiniband ports + value = os.popen ("ls /sys/class/infiniband").readline().strip() + + if not value: + return None + + portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split() + + portkeys = {} + + for port in portlist: + value = os.popen ("cat %s/state" % + port.strip()).readline().split(':')[1].strip() + portkeys[port.strip()] = value + + return portkeys + + +def getServerCount(): + try: + return int(open(Globals.SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE) + return 1 + + +def setServerCount(count): + try: + open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.SERVER_COUNT_FILE) + return False + + +def getInstalledServerCount(): + try: + return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + + +def setInstalledServerCount(count): + try: + open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return False + + +def getLastInstalledServerIpList(): + ipList = {} + networkDom = Protocol.XDOM() + if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE): + log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE) + for tagE in networkDom.getElementsByTagRoute("server.interface"): + interfaceDom = Protocol.XDOM() + interfaceDom.setDomObj(tagE) + ipAddress = interfaceDom.getTextByTagRoute("ipaddr") + if ipAddress: + ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress + return ipList + + +def getFreeIpAddress(device=None): + serverCount = getServerCount() + installedServerCount = getInstalledServerCount() + if serverCount == installedServerCount: + return None + + availableServerCount = serverCount - installedServerCount + ipList = getLastInstalledServerIpList() + + if not ipList: + return None + + if device: + if device not in ipList.keys(): + return None + deviceIpAddress = ipList[device] + else: + deviceIpAddress = ipList.values()[0] + ipNumber = IP2Number(deviceIpAddress) + + for i in range((ipNumber + availableServerCount), ipNumber, -1): + ipAddress = Number2IP(i) + if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0: + return ipAddress + return None + + +def getPasswordHash(userName): + try: + #return spwd.getspnam(userName).sp_pwd + return "Not implimented" + except KeyError: + return None + + +def getTransactionKey(): + try: + tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',') + except IOError: + return None, None + return tokens + + +def generateSignature(): + #return str(uuid.uuid4()) + ('--%f' % time.time()) + return ('--%f' % time.time()) + + +def getSignature(): + try: + return open(Globals.SIGNATURE_FILE).read().strip() + except IOError: + log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE) + return False + + +def storeSignature(signature, fileName=Globals.SIGNATURE_FILE): + try: + open(fileName, "w").write(signature + "\n") + except IOError: + log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName)) + return False + return True + + +def isUserExist(userName): + try: + grp.getgrnam(userName).gr_gid + return True + except KeyError: + pass + try: + pwd.getpwnam(userName).pw_uid + return True + except KeyError: + pass + return False + + +def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE): + userInfo = {} + userInfo["UserId"] = None + userInfo["Password"] = None + try: + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "GSN_ID": + userInfo["UserId"] = v + if k.upper() == "GSN_PASSWORD": + userInfo["Password"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return userInfo + + +def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE): + try: + fp = open(fileName, "w") + fp.write("GSN_ID=%s\n" % userInfo["UserId"]) + fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"]) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE): + versionInfo = {} + versionInfo["Version"] = None + versionInfo["Update"] = None + try: + lines = open(Globals.GLUSTER_VERSION_FILE).readlines() + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "VERSION": + versionInfo["Version"] = v + if k.upper() == "UPDATE": + versionInfo["Update"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return versionInfo + + +def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE): + if isString(versionInfo): + tokens = versionInfo.strip().split(".") + if len(tokens) < 2: + log("Invalid version format %s. Expecting .." % versionInfo) + return False + version = ".".join(tokens[:2]) + update = ".".join(tokens[2:]) + if not update: + update = "0" + else: + version = versionInfo["Version"] + update = versionInfo["Update"] + try: + fp = open(fileName, "w") + fp.write("VERSION=%s\n" % version) + fp.write("UPDATE=%s\n" % update) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getGlusterUpdateDom(serverVersion): + errorMessage = "" + updateInfoDom = None + try: + baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip() + except IOError, e: + log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e)) + errorMessage = "Failed to read update site file" + return updateInfoDom, errorMessage + + try: + url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE) + connection = urllib.urlopen(url) + if connection.getcode() != 200: + connection.close() + errorMessage = "Error received from server to open URL %s" % url + return updateInfoDom, errorMessage + updateInfoString = connection.read() + connection.close() + except IOError, e: + log("Failed to get update information from URL %s: %s" % (url, e)) + errorMessage = "Error getting update information" + return updateInfoDom, errorMessage + + updateInfoDom = Protocol.XDOM() + if not updateInfoDom.parseString(updateInfoString): + log("XML parse error on update information content [%s]" % updateInfoString) + errorMessage = "Parse error on update information" + updateInfoDom = None + return updateInfoDom, errorMessage + + +def removeFile(fileName, root=False): + if root: + if runCommand("rm %s" % fileName, root=True) == 0: + return True + return False + try: + os.remove(fileName) + return True + except OSError, e: + Utils.log("Failed to remove file %s: %s" % (fileName, e)) + return False + + +def isLiveMode(): + return os.path.exists(Globals.LIVE_MODE_FILE) diff --git a/src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm b/src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm new file mode 100644 index 00000000..4b07c4e4 Binary files /dev/null and b/src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm differ diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py b/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py new file mode 100644 index 00000000..6d867d9e --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py @@ -0,0 +1,118 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xmpp +import sys +import syslog + +class Agent: + def __init__(self, jidString, jidResource, password, proxySettings=None): + if jidString and jidResource and password: + self.password = password + self.proxySettings = proxySettings + self.jid = xmpp.protocol.JID(jid=jidString) + self.jid.setResource(jidResource) + self.xmppClient = xmpp.Client(self.jid.getDomain(), debug=[]) + self.presenceHandler = None + self.messageHandler = None + return + raise ValueError("jid, resource and password should not be empty") + + def registerPresenceHandler(self, function): + self.presenceHandler = function + + def registerMessageHandler(self, function): + self.messageHandler = function + + def __defaultMessageHandler(self, connection, event): + syslog.syslog(syslog.LOG_DEBUG, + "[Received]: from_jid=%s, type=%s, message=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getBody(), event.getError())) + if self.messageHandler: + self.messageHandler(connection, event) + else: + sys.stderr.write("[Message]: from_jid=%s, type=%s, message=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getBody(), event.getError())) + + def __defaultPresenceHandler(self, connection, event): + syslog.syslog(syslog.LOG_DEBUG, + "[Presence]: from_jid=%s, type=%s, status=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getShow(), event.getError())) + if self.presenceHandler: + self.presenceHandler(connection, event) + else: + sys.stderr.write("[Presence]: from_jid=%s, type=%s, status=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getShow(), event.getError())) + + def connect(self): + syslog.syslog("Connecting to server %s\n" % self.jid.getDomain()) + connection = self.xmppClient.connect() + if not connection: + syslog.syslog("failed\n") + if not self.proxySettings: + return False + syslog.syslog("Connecting to server %s through proxy server %s, port %s, username %s\n" % + (self.jid.getDomain(), + self.proxySettings["host"], + self.proxySettings["port"], + self.proxySettings["user"])) + connection = self.xmppClient.connect(proxy=self.proxySettings) + if not connection: + syslog.syslog("failed\n") + return False + + syslog.syslog("Authenticating with username %s\n" % self.jid) + auth = self.xmppClient.auth(self.jid.getNode(), + self.password, + self.jid.getResource()) + if not auth: + syslog.syslog("failed\n") + return False + syslog.syslog("done\n") + syslog.syslog("connection type is %s. authentication type is %s\n" % (connection, auth)) + + self.xmppClient.RegisterHandler("presence", self.__defaultPresenceHandler) + self.xmppClient.RegisterHandler("message", self.__defaultMessageHandler) + + self.xmppClient.sendInitPresence() + return True + + def disconnect(self): + self.xmppClient.disconnect() + + def processMessage(self, timeout=1): + return self.xmppClient.Process(timeout) + #if not self.xmppClient.isConnected(): + # self.xmppClient.reconnectAndReauth() + + def sendMessage(self, jidString, message, messageType="chat"): + syslog.syslog(syslog.LOG_DEBUG, + "[send]: from_jid=%s, type=%s, message=%s\n" % + (jidString, messageType, message)) + self.xmppClient.send(xmpp.protocol.Message(to=jidString, + body=message, + typ=messageType)) + + def getNetworkSocket(self): + return self.xmppClient.Connection._sock; + + def getRoster(self): + return self.xmppClient.getRoster() + + def isConnected(self): + return self.xmppClient.isConnected() +##--end of Agent diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py b/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py new file mode 100644 index 00000000..3311eb56 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py @@ -0,0 +1,96 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog +import Globals +import Commands +import re +from ServerUtils import * +from Protocol import * +from NetworkUtils import * + +def getServerNetworkConfig(requestXml): + serverName = requestXml.getTextByTagRoute("command.server-name") + version = requestXml.getVersion() + messageId = requestXml.getAttribute("id") + + if not serverName: + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) + responseDom.appendTagRoute("server.name", serverName) + return responseDom + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "OK", messageId, version) + serverTag = responseDom.createTag("server", None) + serverTag.appendChild(responseDom.createTag("name", serverName)) + nameServerList, domain, searchDomain = readResolvConfFile() + if domain: + domainName = domain[0] + else: + domainName = None + serverTag.appendChild(responseDom.createTag("domainname", domainName)) + i = 1 + for dns in nameServerList: + serverTag.appendChild(responseDom.createTag("dns%s" % i, dns)) + i += 1 + #TODO: probe and retrieve timezone, ntp-server, preferred-network details and update the tags + configDom = XDOM() + if configDom.parseFile("%s/%s/network.xml" % (Globals.SERVER_CONF_DIR, serverName)): + serverTag.appendChild(responseDom.createTag("timezone", configDom.getTextByTagRoute("network.timezone"))) + serverTag.appendChild(responseDom.createTag("ntp-server", configDom.getTextByTagRoute("network.ntp-server"))) + preferredNetwork = configDom.getTextByTagRoute("network.preferred-network") + if not preferredNetwork: + preferredNetwork = "any" + serverTag.appendChild(responseDom.createTag("preferred-network", preferredNetwork)) + + deviceList = {} + for device in getNetDeviceList(): + deviceList[device["device"]] = device + try: + macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() + except IOError: + continue + interfaceTag = responseDom.createTag("interface", None) + interfaceTag.appendChild(responseDom.createTag("device", device["device"])) + interfaceTag.appendChild(responseDom.createTag("description", device["description"])) + interfaceTag.appendChild(responseDom.createTag("hwaddr", macAddress)) + if deviceList[device["device"]]: + if deviceList[device["device"]]["onboot"]: + interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", deviceList[device["device"]]["bootproto"])) + interfaceTag.appendChild(responseDom.createTag("ipaddr", deviceList[device["device"]]["ipaddr"])) + interfaceTag.appendChild(responseDom.createTag("netmask", deviceList[device["device"]]["netmask"])) + interfaceTag.appendChild(responseDom.createTag("gateway", deviceList[device["device"]]["gateway"])) + if deviceList[device["device"]]["mode"]: + interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) + if deviceList[device["device"]]["master"]: + interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) + spliter = re.compile(r'[\D]') + interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", "none")) + serverTag.appendChild(interfaceTag) + responseDom.appendTag(serverTag) + return responseDom + +def test(): + requestString = """ +s1""" + requestDom = RequestXml(requestString) + print getServerNetworkConfig(requestDom).toxml() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py new file mode 100755 index 00000000..bcb2bac1 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py @@ -0,0 +1,179 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import sys +import signal +import atexit +import socket +import syslog +import pwd +from optparse import OptionParser + +import Globals +import Socket +import Utils +import ServerRequestHandler + + +ME = os.path.basename(sys.argv[0]) +PID_FILE = "/var/run/serveragent.pid" +serverSocket = None +clientSocket = None +clientAddress = None +clientInputStream = None +clientOutputStream = None + + +def sigTermHandler(signal, frame): + sys.exit(0) + + +def cleanup(): + try: + if os.path.exists(PID_FILE): + os.unlink(PID_FILE) + except OSError, e: + Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(e))) + + try: + if clientSocket: + clientSocket.close() + except socket.error, e: + Utils.log("Failed to close client socket: %s" % str(e)) + + try: + if serverSocket: + serverSocket.close() + except socket.error, e: + Utils.log("Failed to close server socket: " % str(e)) + + +def main(): + global PID_FILE + global serverSocket + global clientSocket + global clientAddress + global clientInputStream + global clientOutputStream + + username = Globals.SERVER_AGENT_RUN_USERNAME + + Utils.openLog(Globals.SERVER_AGENT_LOG_FILE) + + parser = OptionParser(version="%s %s" % (ME, Globals.GLUSTER_PLATFORM_VERSION)) + + parser.add_option("-N", "--no-daemon", + action="store_false", dest="daemonMode", default=True, + help="Run in foreground") + parser.add_option("-r", "--run-as", dest="username", + help="Run the daemon as USERNAME (default: %s)" % Globals.SERVER_AGENT_RUN_USERNAME, + metavar="USERNAME") + (options, args) = parser.parse_args() + + if options.username: + username = options.username + try: + userInfo = pwd.getpwnam(username) + except KeyError, e: + sys.stderr.write("%s\n" % str(e)) + serverSocket.close() + sys.exit(-1) + uid = userInfo.pw_uid + gid = userInfo.pw_gid + + try: + Utils.log("__DEBUG__ Opening server socket on port %s" % Globals.SERVER_AGENT_PORT) + serverSocket = Socket.openServerSocket() + except socket.error, e: + sys.stderr.write("Failed to open server socket: %s\n" % str(e)) + sys.exit(-1) + + if options.daemonMode: + if os.path.exists(PID_FILE): + sys.stderr.write("fatal: %s file exists\n" % PID_FILE) + serverSocket.close() + sys.exit(-1) + + if not Utils.daemonize(): + sys.stderr.write("fatal: unable to run as daemon\n") + serverSocket.close() + sys.exit(-1) + try: + fp = open(PID_FILE, "w") + fp.write("%s\n" % os.getpid()) + fp.close() + except IOError, e: + Utils.log("Pid file %s: %s" % (PID_FILE, str(e))) + serverSocket.close() + sys.exit(-1) + try: + os.chown(PID_FILE, uid, gid) + except OSError, e: + Utils.log("Pid file %s: %s" % (PID_FILE, str(e))) + serverSocket.close() + try: + os.unlink(PID_FILE) + except OSError, ex: + Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(ex))) + sys.exit(-1) + else: + Globals.GLUSTER_DEBUG = True + + try: + os.setregid(gid, gid) + except OSError, e: + Utils.log("Failed to set effective and real gid to %s: %s" % (gid, str(e))) + cleanup() + sys.exit(-1) + try: + os.setreuid(uid, uid) + except OSError, e: + Utils.log("Failed to set effective and real uid to %s: %s" % (uid, str(e))) + cleanup() + sys.exit(-1) + + atexit.register(cleanup) + signal.signal(signal.SIGTERM, sigTermHandler) + + while True: + Utils.log("__DEBUG__ Waiting for new connection on port %s" % Globals.SERVER_AGENT_PORT) + try: + clientSocket, clientAddress, clientInputStream, clientOutputStream = Socket.acceptClient(serverSocket) + except socket.error, e: + Utils.log("Failed to accept new connection: %s" % str(e)) + sys.exit(-1) + + Utils.log('__DEBUG__ Connected by %s' % str(clientAddress)) + try: + requestString = Socket.readPacket(clientInputStream) + Utils.log('__DEBUG__ Received %s' % repr(requestString)) + responseString = ServerRequestHandler.handleRequest(requestString) + if responseString: + Socket.writePacket(clientOutputStream, responseString) + clientOutputStream.flush() + else: + Utils.log('__DEBUG__ empty response string') + Utils.log('__DEBUG__ Closing client %s' % str(clientAddress)) + clientSocket.close() + except socket.error, e: + Utils.log("Socket error on client: %s" % str(e)) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py new file mode 100644 index 00000000..31d4eb8c --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py @@ -0,0 +1,76 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os + +import Commands +from Protocol import * +from Globals import * +from GetServerNetworkConfig import * + +def handleRequestGetServerNetworkConfig(requestDom): + return getServerNetworkConfig(requestDom) + +def handleRequest(requestString): + log("Received request %s" % repr(requestString)) + + requestDom = XDOM() + requestDom.parseString(requestString) + if not requestDom: + log("Invalid request") + return None + + preRequestMap = {} + + postRequestMap = {} + + cleanupRequestMap = {} + + requestMap = { Commands.COMMAND_GET_SERVER_NETWORK_CONFIG : handleRequestGetServerNetworkConfig } + + messageId = requestDom.getMessageId() + if not messageId: + log("Invalid message Id") + return None + + requestCommand = requestDom.getRequestCommand() + if not requestCommand: + log("invalid request command") + return None + + requestAction = requestDom.getRequestAction() + version = requestDom.getVersion() + #if not isSupportedVersion(version): + # log("Unsupported version request %s" % requestDom.toxml()) + # return ResponseXml(requestCommand, "Unsupported version request", messageId, version).toxml() + + try: + if not requestAction: + responseDom = requestMap[requestCommand](requestDom) + elif requestAction.upper() == "PRE": + responseDom = preRequestMap[requestCommand](requestDom) + elif requestAction.upper() == "POST": + responseDom = postRequestMap[requestCommand](requestDom) + elif requestAction.upper() == "CLEANUP": + responseDom = cleanupRequestMap[requestCommand](requestDom) + else: + log("Unknown request action %s" % requestAction) + return None + return responseDom.toxml() + except KeyError: + log("No handler found for command %s for action %s" % (requestCommand, requestAction)) + return ResponseXml(requestCommand, "Invalid command", messageId, version).toxml() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py new file mode 100644 index 00000000..1fec994c --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py @@ -0,0 +1,308 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import re +import subprocess +import glob +import Globals +from Protocol import * +from Utils import * + +def isValidServer(serverName): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + if serverName == profile.DNS.Hostname: + return True + return False + +def getHostname(): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + return profile.DNS.Hostname + return None + +def getDomainName(): + try: + domainName = open(Globals.DOMAINNAME_FILE).read() + except IOError: + return None + return domainName.split()[0] + +def replaceServerIp(fileName, findWhat, replaceWith): + try: + data = open(fileName).read() + fp = open(fileName, "w") + fp.write(re.sub(findWhat, replaceWith, data)) + fp.close() + return True + except IOError: + return False + except ValueError: + return False + except OSError: + return False + +def serverName2IpAddress(serverName): + command = "dig %s | grep '^%s'" % (serverName, serverName) + ps = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True) + ipAddress = serverName + if ps.wait() == 0: + output = ps.communicate() + ipAddress = output[0].split()[-1] + return ipAddress + +def getInstallerIp(): + if not os.path.exists(Globals.INSTALLER_INFO_FILE): + return None + try: + for line in open(Globals.INSTALLER_INFO_FILE): + tokens = line.split("=") + if tokens[0] == "IP-ADDRESS": + return tokens[1].split(",")[0].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def setInstallerIp(installerIp): + try: + open(Globals.INSTALLER_INFO_FILE, "w").write("IP-ADDRESS=%s\n" % installerIp) + return True + except IOError: + log(syslog.LOG_ERR, "unable to create %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def getCurrentServerName(): + try: + for line in open(Globals.SYSCONFIG_NETWORK_FILE): + tokens = line.split("=") + if tokens[0] == "HOSTNAME": + return tokens[1].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.SYSCONFIG_NETWORK_FILE) + return False + +def getLastAccessedNetwork(serverName): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + return open(lastAccessedNetworkFile).read().strip() + except IOError: + log(syslog.LOG_ERR, "failed to read last accessed network file %s" % lastAccessedNetworkFile) + pass + return False + +def setLastAccessedNetwork(serverName, ipAddress): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + open(lastAccessedNetworkFile, "w").write(ipAddress.strip() + "\n") + except IOError: + log(syslog.LOG_ERR, "failed to write last accessed network file %s" % lastAccessedNetworkFile) + return False + return True + +def getServerIpList(serverName, preferredNetworkOnly=False): + networkXmlFile = ("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + configDom = XDOM() + if not configDom.parseFile(networkXmlFile): + log(syslog.LOG_ERR, "failed to read %s file" % networkXmlFile) + return None + preferredNetwork = configDom.getTextByTagRoute("preferred-network") + ipList = [] + interfaceDom = XDOM() + for tagE in configDom.getElementsByTagName("interface"): + interfaceDom.setDomObj(tagE) + deviceName = interfaceDom.getTextByTagRoute("device") + hostIp = interfaceDom.getTextByTagRoute("ipaddr") + if not hostIp: + continue + if preferredNetworkOnly: + if preferredNetwork.upper() == "ANY" or preferredNetwork.upper() == deviceName.upper(): + ipList.append(hostIp) + else: + ipList.append(hostIp) + if preferredNetworkOnly: + lastAccessedNetworkIp = getLastAccessedNetwork(serverName) + if lastAccessedNetworkIp in ipList: + ipList.remove(lastAccessedNetworkIp) + ipList = [lastAccessedNetworkIp] + ipList + return ipList + +def getServerPreferredIpList(serverName): + return getServerIpList(serverName, True) + +def getExecuteServerList(serverList): + executeServerList = {} + for serverName in serverList: + if serverName == Globals.INSTALLER_SERVER_NAME: + installerIp = getInstallerIp() + if installerIp: + executeServerList[serverName] = [installerIp] + continue + executeServerList[serverName] = getServerPreferredIpList(serverName) + return executeServerList + +def getAllServerList(): + serverList = [] + for filePath in glob.glob("%s/servers/*" % Globals.GLUSTER_CONF_DIR): + if os.path.isdir(filePath): + serverList.append(os.path.basename(filePath)) + try: + serverList.remove(Globals.INSTALLER_SERVER_NAME) + except ValueError: + pass + return serverList + +def getServerNetworkConfigFromLocalFile(serverName): + configDom = XDOM() + configDom.parseFile("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + return configDom + +def updateServerNetworkConfigXmlFile(serverName, serverNetworkDom): + configDom = XDOM() + serverTag = serverNetworkDom.getElementsByTagRoute("server")[0] + configDom.setDomObj(serverTag) + if not configDom.writexml("%s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): + log("Faild to write xml file %s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + +def compareServerNetworkDom(serverNetworkDomA, serverNetworkDomB, requestFlag=True): + command = "command.server." + if not requestFlag: + command = "" + sourceServer = {} + tagText = serverNetworkDomA.getTextByTagRoute("name") + if not tagText: + taxText = None + sourceServer["name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("domain-name") + if not tagText: + tagText = None + sourceServer["domain-name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("search-domain") + if not tagText: + tagText = None + sourceServer["search-domain"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns1") + if not tagText: + tagText = None + sourceServer["dns1"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns2") + if not tagText: + tagText = None + sourceServer["dns2"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns3") + if not tagText: + tagText = None + sourceServer["dns3"] = tagText + for tagE in serverNetworkDomA.getElementsByTagRoute("interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + sourceServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + sourceServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + sourceServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + sourceServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + sourceServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + sourceServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + sourceServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + sourceServerList["gateway"] = tagText + sourceServer[interfaceDom.getTextByTagRoute("device")] = sourceServerList + objServer = {} + tagText = serverNetworkDomB.getTextByTagRoute(command + "name") + if not tagText: + taxText = None + objServer["name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "domain-name") + if not tagText: + tagText = None + objServer["domain-name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "search-domain") + if not tagText: + tagText = None + objServer["search-domain"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns1") + if not tagText: + tagText = None + objServer["dns1"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns2") + if not tagText: + tagText = None + objServer["dns2"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns3") + if not tagText: + tagText = None + objServer["dns3"] = tagText + for tagE in serverNetworkDomB.getElementsByTagRoute(command + "interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + objServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + objServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + objServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + objServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + objServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + objServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + objServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + objServerList["gateway"] = tagText + objServer[interfaceDom.getTextByTagRoute("device")] = objServerList + return sourceServer == objServer diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py b/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py new file mode 100644 index 00000000..ba6b6ad0 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py @@ -0,0 +1,47 @@ +import socket +import sys +import Globals + +def openServerSocket(bindAddress="", port=Globals.SERVER_AGENT_PORT): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((bindAddress, port)) + sock.listen(1) + return sock + + +def connectToServer(serverName, port=Globals.SERVER_AGENT_PORT): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((serverName, port)) + print "__DEBUG__ connected to ", serverName, " on port ", port + inputStream = sock.makefile("r") + outputStream = sock.makefile("w") + return sock, inputStream, outputStream + + +def acceptClient(serverSocket): + clientSocket, clientAddress = serverSocket.accept() + clientInputStream = clientSocket.makefile("r") + clientOutputStream = clientSocket.makefile("w") + return clientSocket, clientAddress, clientInputStream, clientOutputStream + + +def readPacket(inputStream): + packetString = "" + while True: + line = inputStream.readline() + print "__DEBUG__", line + if not line: + break + if line.strip() == "": + # end of input received + return packetString + packetString += line + return packetString + + +def writePacket(outputStream, packetString): + rv = outputStream.write(packetString.strip() + "\n\n") + outputStream.flush() + + diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py b/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py new file mode 100644 index 00000000..d5a1fe19 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py @@ -0,0 +1,346 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def createResponseTag(self): + responseTag = self._domObj.createElement("response") + return responseTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + + +class ResponseXml(XDOM): + _responseTag = None + def __init__(self): + XDOM.__init__(self) + self._responseTag = self.createResponseTag() + self._domObj.appendChild(self._responseTag) + + @classmethod + def errorResponse(self, message): + if not self.responseTag: + return False + self.appendTagRoute("status.code", "-1"); + self.appendTagRoute("status.message", message) + + def append(self, tagName, tagValue=None): + if not self._responseTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._responseTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._responseTag: + return False + self._responseTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._responseTag: + return None + if not tagRoute: + return None + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return None + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return None + return newTagE + + def appendTagRouteOld(self, tagRoute, value=None): + if not self._responseTag: + return False + if not tagRoute: + return False + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True +##--end of ResponseXml + +def test(): + rs = ResponseXml() + rs.appendTagRoute("status.code", "0"); + rs.appendTagRoute("status.message", "SUCCESS") + serverTag = rs.appendTagRoute("server.name", "Server1") + networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface1")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40")) + networkInterfaces.appendChild(networkTag) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface2")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41")) + networkInterfaces.appendChild(networkTag) + print rs.toprettyxml() + +test() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py b/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py new file mode 100644 index 00000000..64bc0899 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import socket +import struct +import Globals + +def response(multiCastGroup, port): + # waiting for the request! + socketRequest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketRequest.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketRequest.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + socketRequest.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + + #TODO: Remove infinite loop and make this as a deamon (service) + while True: + request = socketRequest.recvfrom(1024) + if request and request[0].upper() == "SERVERDISCOVERY": + socketSend.sendto(socket.gethostname(), (multiCastGroup, port)) + request = None + +def main(): + response(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py b/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py new file mode 100644 index 00000000..1800234f --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py @@ -0,0 +1,287 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import socket +#import paramiko +import syslog +import sys +import Socket +import Globals +from copy import deepcopy +from ServerUtils import * + +SERVER_AGENT_COMMAND = "/usr/sbin/server-agent" +SERVER_AGENT_CLEANUP_COMMAND = SERVER_AGENT_COMMAND + " --cleanup" +SERVER_AGENT_PRE_COMMAND = SERVER_AGENT_COMMAND + " --pre" +SERVER_AGENT_POST_COMMAND = SERVER_AGENT_COMMAND + " --post" +TRANSPORT_USER_NAME = "transport" +TRANSPORT_PRIVATE_KEY_FILE = Globals.TRANSPORT_HOME_DIR + "/.ssh/id_rsa" + +def remoteExecute(serverList, command, commandInput=None): + print "REMOTE:", serverList + statusDict = {} + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + privateKey = paramiko.RSAKey.from_private_key_file(TRANSPORT_PRIVATE_KEY_FILE) + except IOError: + log(syslog.LOG_ERR, "Private key file %s not found" % TRANSPORT_PRIVATE_KEY_FILE) + return None + print "STAGE1" + for serverName in serverList.keys(): + serverStatus = {} + serverStatus["ConnectionStatus"] = None + serverStatus["ExecutionStatus"] = None + serverStatus["StdOutString"] = None + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = None + serverStatus["Error"] = None + + isConnected = False + for serverIp in serverList[serverName]: + try: + ssh.connect(serverIp, username=TRANSPORT_USER_NAME, pkey=privateKey) + isConnected = True + break + except socket.error: + log(syslog.LOG_ERR, "Server %s:%s is inaccessible" % (serverName, serverIp)) + continue + if not isConnected: + serverStatus["ConnectionStatus"] = "inaccessible" + statusDict[serverName] = serverStatus + continue + + try: + transport = ssh.get_transport() + channel = transport.open_session() + serverStatus["ConnectionStatus"] = True + channel.exec_command(command) + stdin = channel.makefile('wb') + stdout = channel.makefile('rb') + stderr = channel.makefile_stderr('rb') + if commandInput: + stdin.write(commandInput) + channel.shutdown_write() + + returnValue = channel.recv_exit_status() ## this is blocking call + serverStatus["ExecutionStatus"] = returnValue + print "RRRRRRRRRRRRRRRR:", returnValue + errorString = "" + if -1 == returnValue: + errorString = stderr.read() + serverStatus["StdErrString"] = errorString + if "bash: " + command.split()[0] + ": command not found\n" == errorString: + log(syslog.LOG_ERR, "command %s not found in server %s" % (command, serverName)) + serverStatus["Error"] = "Command not found" + else: + serverStatus["StdErrString"] = stderr.read() + serverStatus["StdOutString"] = stdout.read() + ssh.close() + except paramiko.SSHException: + # Channel error (channel not open) + log(syslog.LOG_ERR, "Server %s:%s connection aborted" % (serverName, serverIp)) + serverStatus["ConnectionStatus"] = "aborted" + except socket.error: + log(syslog.LOG_ERR, "Server %s:%s is inaccessible" % (serverName, serverIp)) + serverStatus["ConnectionStatus"] = "inaccessible" + except paramiko.AuthenticationException: + log(syslog.LOG_ERR, "Authentication error on server %s:%s of user %s" % + (serverName, serverIp, TRANSPORT_USER_NAME)) + serverStatus["ConnectionStatus"] = "authentication error" + serverStatus["ConnectedIp"] = serverIp + statusDict[serverName] = serverStatus + return statusDict + +def cleanupExecuteSsh(serverList, requestDom): + return remoteExecute(serverList, SERVER_AGENT_CLEANUP_COMMAND, requestDom.toxml()) + +def executeRequestCommandSsh(serverList, command, requestDom, cleanupFlag): + cleanupStatusDict = {} + successStatusDict = {} + failureServerList = {} + cleanupServerList = {} + serverList = deepcopy(serverList) + statusDict = remoteExecute(serverList, command, requestDom.toxml()) + for serverName in statusDict.keys(): + statusDict["Response"] = None + if statusDict[serverName]["ConnectionStatus"] == True: + setLastAccessedNetwork(serverName, statusDict[serverName]["ConnectedIp"]) + if statusDict[serverName]["ConnectedIp"]: + ipList = serverList[serverName] + ipList.remove(statusDict[serverName]["ConnectedIp"]) + cleanupServerList[serverName] = [statusDict[serverName]["ConnectedIp"]] + ipList + if statusDict[serverName]["ExecutionStatus"] != 0: + failureServerList[serverName] = statusDict[serverName] + continue + responseDom = XDOM() + if not responseDom.parseString(statusDict[serverName]["StdOutString"]): + failureServerList[serverName] = statusDict[serverName] + continue + statusDict["Response"] = responseDom + if "OK" != responseDom.getAttribute("response-code"): + failureServerList[serverName] = statusDict[serverName] + continue + successStatusDict[serverName] = statusDict[serverName] + if cleanupFlag and failureServerList: + cleanupStatusDict = remoteExecute(cleanupServerList, SERVER_AGENT_CLEANUP_COMMAND, requestDom.toxml()) + return successStatusDict, failureServerList, cleanupStatusDict + +def preExecuteSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_PRE_COMMAND, requestDom, cleanupFlag) + +def executeSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_COMMAND, requestDom, cleanupFlag) + +def postExecuteSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_POST_COMMAND, requestDom, cleanupFlag) + +def runPullUpdatesDir(sourceServerIp, destServerIpList): + command = "/usr/sbin/pull-dir.sh %s %s %s" % (sourceServerIp, + Globals.UPDATES_DIR[1:], + Globals.UPDATES_DIR) + statusDict = remoteExecute(destServerIpList, command) + status = True + for serverName in statusDict.keys(): + if statusDict[serverName]["ExecutionStatus"] != 0: + log(syslog.LOG_ERR, "Failed to execute [%s] in server %s" % (command, serverName)) + status = False + return status + +def runPullGlusterDir(sourceServerIp, destServerIpList): + command = "/usr/sbin/pull-dir.sh %s %s %s" % (sourceServerIp, + Globals.GLUSTER_BASE_DIR[1:], + Globals.GLUSTER_BASE_DIR) + statusDict = remoteExecute(destServerIpList, command) + status = True + for serverName in statusDict.keys(): + if statusDict[serverName]["ExecutionStatus"] != 0: + log(syslog.LOG_ERR, "Failed to execute [%s] in server %s" % (command, serverName)) + status = False + return status + +def syncConfiguration(syncToInstaller=False, sourceServerIpList=None): + thisServerName = getCurrentServerName() + serverList = getAllServerList() + serverList.remove(thisServerName) + serverIpList = getExecuteServerList(serverList) + if syncToInstaller: + installerIp = getInstallerIp() + if not installerIp: + log(syslog.LOG_ERR, "Installer IP address is not found") + return False + serverIpList[Globals.INSTALLER_SERVER_NAME] = [installerIp] + + if not serverIpList: + log(syslog.LOG_ERR, "No servers found for sync configuration") + return False + + signature = generateSignature() + if not storeSignature(signature, Globals.SIGNATURE_FILE): + log(syslog.LOG_ERR, "failed to store signature %s to %s file" % + (signature, Globals.SIGNATURE_FILE)) + return False + + thisServerIpList = getExecuteServerList([thisServerName]) + if sourceServerIpList: + thisServerIpList = sourceServerIpList + return runPullGlusterDir(thisServerIpList[thisServerName][0], serverIpList) + +def remoteExecuteTcp(serverIpList, requestString): + serverStatus = {} + serverStatus["ConnectionStatus"] = False + serverStatus["ExecutionStatus"] = -1 + serverStatus["StdOutString"] = None + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = None + serverStatus["Error"] = None + + for ipAddress in serverIpList.values()[0]: + try: + sock, inputStream, outputStream = Socket.connectToServer(ipAddress) + Socket.writePacket(outputStream, requestString) + packetString = Socket.readPacket(inputStream) + log('__DEBUG__ Received: %s' % repr(packetString)) + sock.close() + serverStatus["ConnectionStatus"] = True + serverStatus["ExecutionStatus"] = 0 + serverStatus["StdOutString"] = packetString + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = ipAddress + serverStatus["Error"] = None + return serverStatus + except socket.error, e: + log("socket error on [%s:%s]: %s" % (serverIpList.keys()[0], ipAddress, str(e))) + return serverStatus + +def executeRequestCommand(serverList, command, requestDom, cleanupFlag): + cleanupStatusDict = {} + successStatusDict = {} + failureServerList = {} + cleanupServerList = {} + serverList = deepcopy(serverList) + + statusDict = {} + for serverName in serverList.keys(): + serverStatus = remoteExecuteTcp({serverName : serverList[serverName]}, requestDom.toxml()) + statusDict[serverName] = serverStatus + for serverName in statusDict.keys(): + statusDict["Response"] = None + if statusDict[serverName]["ConnectionStatus"] == True: + setLastAccessedNetwork(serverName, statusDict[serverName]["ConnectedIp"]) + if statusDict[serverName]["ConnectedIp"]: + ipList = serverList[serverName] + ipList.remove(statusDict[serverName]["ConnectedIp"]) + cleanupServerList[serverName] = [statusDict[serverName]["ConnectedIp"]] + ipList + if statusDict[serverName]["ExecutionStatus"] != 0: + failureServerList[serverName] = statusDict[serverName] + continue + responseDom = XDOM() + if not responseDom.parseString(statusDict[serverName]["StdOutString"]): + failureServerList[serverName] = statusDict[serverName] + continue + statusDict["Response"] = responseDom + if "OK" != responseDom.getResponseCode(): + failureServerList[serverName] = statusDict[serverName] + continue + successStatusDict[serverName] = statusDict[serverName] + if cleanupFlag and failureServerList: + rq = deepcopy(requestDom) + rq.setRequestAction("cleanup") + cleanupStatusDict = {} + for serverName in cleanupServerList.keys(): + serverStatus = remoteExecuteTcp({serverName : cleanupServerList[serverName]}, rq.toxml()) + cleanupStatusDict[serverName] = serverStatus + return successStatusDict, failureServerList, cleanupStatusDict + +def preExecute(serverList, requestDom, cleanupFlag=True): + rq = deepcopy(requestDom) + rq.setRequestAction("pre") + return executeRequestCommand(serverList, SERVER_AGENT_PRE_COMMAND, rq, cleanupFlag) + +def execute(serverList, requestDom, cleanupFlag=True): + return executeRequestCommand(serverList, SERVER_AGENT_COMMAND, requestDom, cleanupFlag) + +def postExecute(serverList, requestDom, cleanupFlag=True): + rq = deepcopy(requestDom) + rq.setRequestAction("post") + return executeRequestCommand(serverList, SERVER_AGENT_POST_COMMAND, rq, cleanupFlag) + +def cleanupExecute(serverList, requestDom): + rq = deepcopy(requestDom) + rq.setRequestAction("cleanup") + return executeRequestCommand(serverList, SERVER_AGENT_CLEANUP_COMMAND, rq, False) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py b/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py new file mode 100644 index 00000000..e6fe88ff --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py @@ -0,0 +1,58 @@ +import os +import glob +#import paramiko +import tempfile +#import uuid +import socket +import tarfile +import time +import Globals +import Commands +from Protocol import * +from RemoteExecute import * +from NetworkUtils import * + +def handleRequestGetServerNetworkConfig(requestDom): + messageId = requestDom.getAttribute("id") + serverName = requestDom.getTextByTagRoute("command.server-name") + version = requestDom.getVersion() + request = requestDom.getAttribute("request") + + if not serverName: + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) + responseDom.appendTagRoute("server.name", serverName) + return responseDom + + #serverIpList = getExecuteServerList([serverName]) + #if not serverIpList: + # responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "Unable to get server ip", messageId, version) + # responseDom.appendTagRoute("server.name", serverName) + # return responseDom + + successStatusDict, failureServerList, cleanupStatusDict = \ + execute({serverName:[serverName]}, requestDom, Globals.REQUEST_MAP[request]["cleanup"]) + if failureServerList: + response = failureServerList[serverName]["StdOutString"] + if not response: + return ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Failed to execute get server network config", messageId, version) + responseDom = XDOM() + if responseDom.parseString(response): + return responseDom + errorResponseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Invalid response of get server network config", messageId, version) + errorResponseDom.appendTagRoute("server.name", serverName) + return errorResponseDom + + responseDom = XDOM() + if not responseDom.parseString(successStatusDict[serverName]["StdOutString"]): + errorResponseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Invalid response of get server network config", messageId, version) + errorResponseDom.appendTagRoute("server.name", serverName) + return errorResponseDom + + #configDom = getServerNetworkConfigFromLocalFile(serverName) + #if not (configDom and compareServerNetworkDom(configDom, responseDom)): + # updateServerNetworkConfigXmlFile(serverName, responseDom) + # syncConfiguration() + return responseDom diff --git a/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py b/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py new file mode 100644 index 00000000..5f39b585 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py @@ -0,0 +1,26 @@ +import Commands +#from Common import log +from Protocol import * +from RequestHandler import * + +def processRequest(requestDom): + Globals.REQUEST_MAP = { + Commands.COMMAND_GET_SERVER_NETWORK_CONFIG : {"handle":handleRequestGetServerNetworkConfig, + "pre-run":False, "run":True, "post-run":False, \ + "cleanup":False, "sync-config":False, "safemode":False}} + + messageId = requestDom.getMessageId() + if not messageId: + log("invalid message from web agent") + return None + + requestCommand = requestDom.getRequestCommand() + if not requestCommand: + log("invalid request from web agent") + return None + + try: + requestCommand = Globals.REQUEST_MAP[requestCommand]['handle'] + except KeyError: # Handler not found! + return ResponseXml(requestCommand, "Invalid command", messageId, version) + return requestCommand(requestDom) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/transport.py b/src/com.gluster.storage.management.server.scripts/src/server/transport.py new file mode 100755 index 00000000..9255ff40 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/transport.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog +import signal +import datetime +from Globals import * +from Protocol import * +from TransportAgent import * +from optparse import OptionParser + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def main(): + openLog(Globals.TRANSPORT_AGENT_LOG_FILE) + parser = OptionParser(version="%transport " + Globals.GLUSTER_PLATFORM_VERSION) + parser.add_option("-f", "--force", + action="store_true", dest="force", default=False, + help="Execute command forcefully") + + parser.add_option("-t", "--timeout", + type="int", nargs=1, dest="timeout", + help="Session time-out") + + parser.add_option("--debug", + action="store_true", dest="debug", default=False, + help="Enable debug mode") + (options, args) = parser.parse_args() + Globals.GLUSTER_DEBUG = options.debug + + if len(args) != 1: + #print "usage: Transport.py [-f | --force] [-t N | --timeout=N] [--debug] " + log(syslog.LOG_ERR, "invalid arguments") + sys.exit(-1) + + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(options.timeout) + inputFile = args[0] + #outputFile = args[1] + try: + requestString = open(inputFile).read() + if not requestString: + sys.exit(-1) + fp = open("/tmp/transport.log", "a") + fp.write("\n%s: Send: %s\n" % (str(datetime.now()), requestString)) + fp.close() + except IOError: + log(syslog.LOG_ERR, "Unable to read input xml file %s" % inputFile) + sys.exit(-1) + + requestDom = RequestXml(requestString) + if not requestDom: + log(syslog.LOG_ERR, "error: invalid request: %s" % requestString) + sys.exit(-1) + + responseDom = processRequest(requestDom) + if not responseDom: + log(syslog.LOG_ERR, "command execution failed") + sys.exit(-1) + + #fp = open("/tmp/transport.log", "a") + #fp.write("%s: Receive: %s\n" % (str(datetime.now()), responseDom.toxml())) + #fp.close() + + #responseDom.writexml(outputFile) + print responseDom.toxml() + sys.exit(0) + +if __name__ == "__main__": + try: + main() + except TimeoutException: + log(syslog.LOG_ERR, "session timed out") + sys.exit(-1) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py b/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py new file mode 100755 index 00000000..6ac15fed --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import socket +import signal +import struct +import syslog +import Globals +import Common + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if response and response[0].upper() != "SERVERDISCOVERY": + servers.append(response[0]) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Common.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + #fp = open(Globals.DISCOVERED_SERVER_LIST_FILENAME, "w") + #fp.writelines(list(servers)) + #fp.close() + for server in servers: + print server + except IOError: + Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + + #for serverName in servers: + # print serverName + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/.classpath b/src/com.gluster.storage.management.server/.classpath new file mode 100644 index 00000000..59631d14 --- /dev/null +++ b/src/com.gluster.storage.management.server/.classpath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project new file mode 100644 index 00000000..86d34a3b --- /dev/null +++ b/src/com.gluster.storage.management.server/.project @@ -0,0 +1,42 @@ + + + com.gluster.storage.management.server + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.jsdt.core.jsNature + org.python.pydev.pythonNature + + diff --git a/src/com.gluster.storage.management.server/.pydevproject b/src/com.gluster.storage.management.server/.pydevproject new file mode 100644 index 00000000..a9cca037 --- /dev/null +++ b/src/com.gluster.storage.management.server/.pydevproject @@ -0,0 +1,7 @@ + + + + +Default +python 2.7 + diff --git a/src/com.gluster.storage.management.server/.settings/.jsdtscope b/src/com.gluster.storage.management.server/.settings/.jsdtscope new file mode 100644 index 00000000..3a28de0c --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..476db350 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 29 14:57:23 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.server/.settings/org.eclipse.ltk.core.refactoring.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 00000000..5d9c71b6 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..bb2eaf45 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..8f960f27 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..3bd5d0a4 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..05bd71b6 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs new file mode 100644 index 00000000..e5ca6272 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar new file mode 100644 index 00000000..578b1a0c Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar new file mode 100644 index 00000000..8217cae0 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar new file mode 100644 index 00000000..8758a96b Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar new file mode 100644 index 00000000..dc8ae8df Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar new file mode 100644 index 00000000..ca367aae Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar new file mode 100644 index 00000000..a3248188 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar new file mode 100644 index 00000000..faf12cf6 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar new file mode 100644 index 00000000..ca612580 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar new file mode 100644 index 00000000..57c2c670 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar new file mode 100644 index 00000000..62f790fa Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar new file mode 100644 index 00000000..92b38466 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar new file mode 100644 index 00000000..01d8c83b Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar new file mode 100644 index 00000000..a29d7409 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar new file mode 100644 index 00000000..c79b4490 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar new file mode 100644 index 00000000..e4e9c8c3 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar new file mode 100644 index 00000000..23782c02 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar new file mode 100644 index 00000000..ec8bc818 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar new file mode 100644 index 00000000..a5d37aa1 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar new file mode 100644 index 00000000..db6f529f Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..7cd3a626 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar new file mode 100644 index 00000000..11fc11b9 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar new file mode 100644 index 00000000..f2e2e927 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar new file mode 100644 index 00000000..bd1367d8 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e46f9eb8 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar new file mode 100644 index 00000000..ea9500d6 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6ef99d8d Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e149290e Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar new file mode 100644 index 00000000..dcd1e4d9 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar new file mode 100644 index 00000000..f7a3b837 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar new file mode 100644 index 00000000..9cea2aef Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..d0550ccd Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..1688cf74 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd new file mode 100644 index 00000000..b3aa6af8 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd @@ -0,0 +1,21 @@ +Library-SymbolicName: org.springframework.spring +Library-Version: 3.0.5.RELEASE +Library-Name: Spring Framework +Import-Bundle: + org.springframework.aop;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.asm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.aspects;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.beans;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context.support;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.core;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.expression;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jdbc;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jms;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.orm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.oxm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.transaction;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.servlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.portlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + com.springsource.org.aopalliance;version="[1.0.0, 1.0.0]" diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar new file mode 100644 index 00000000..237995c5 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar new file mode 100644 index 00000000..2f52122b Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar new file mode 100644 index 00000000..5a2381a0 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6ec9d681 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6d13bd40 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e351ae7b Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar new file mode 100644 index 00000000..56222cbf Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar new file mode 100644 index 00000000..d321e76c Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar new file mode 100644 index 00000000..e5bc672b Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar new file mode 100644 index 00000000..78818fc5 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar new file mode 100644 index 00000000..a8077d5d Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar new file mode 100644 index 00000000..26611b55 Binary files /dev/null and b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml new file mode 100644 index 00000000..34337a5d --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -0,0 +1,72 @@ + + + com.gluster.storage.management.server + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + + + + contextConfigLocation + + classpath:spring/gluster-server-security.xml + classpath:spring/gluster-server-base.xml + + + + org.springframework.web.context.ContextLoaderListener + + + org.springframework.web.context.request.RequestContextListener + + + + + gluster-resources + + com.sun.jersey.spi.spring.container.servlet.SpringServlet + + com.sun.jersey.config.property.packages + com.gluster.storage.management.server.resources + + 1 + + + gluster-resources + /resources/* + + + + + JnlpDownloadServlet + jnlp.sample.servlet.JnlpDownloadServlet + + + JnlpDownloadServlet + *.jnlp + + + JnlpDownloadServlet + *.jar + + + + + springSecurityFilterChain + + org.springframework.web.filter.DelegatingFilterProxy + + + + springSecurityFilterChain + /* + + diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Common.py b/src/com.gluster.storage.management.server/WebContent/scripts/Common.py new file mode 100644 index 00000000..60f200fe --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Common.py @@ -0,0 +1,34 @@ +# Copyright (c) 2009 Gluster, Inc. +# This file is part of GlusterSP. +# +# GlusterSP is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# GlusterSP 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog + +def log(priority, message=None): + if type(priority) == type(""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + if not logMessage: + return + #if Globals.DEBUG: + # sys.stderr.write(logMessage) + else: + syslog.syslog(logPriority, logMessage) + return diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py b/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py new file mode 100644 index 00000000..6e68adbd --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py @@ -0,0 +1,3 @@ +MULTICAST_GROUP = '224.224.1.1' +MULTICAST_PORT = 5353 +DISCOVERED_SERVER_LIST_FILENAME = "/tmp/discovered-server-list" diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py b/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py new file mode 100755 index 00000000..6ac15fed --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import socket +import signal +import struct +import syslog +import Globals +import Common + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if response and response[0].upper() != "SERVERDISCOVERY": + servers.append(response[0]) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Common.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + #fp = open(Globals.DISCOVERED_SERVER_LIST_FILENAME, "w") + #fp.writelines(list(servers)) + #fp.close() + for server in servers: + print server + except IOError: + Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + + #for serverName in servers: + # print serverName + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/buckminster.cspex b/src/com.gluster.storage.management.server/buckminster.cspex new file mode 100644 index 00000000..31eb9d67 --- /dev/null +++ b/src/com.gluster.storage.management.server/buckminster.cspex @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.server/build/glusterserver.ant b/src/com.gluster.storage.management.server/build/glusterserver.ant new file mode 100644 index 00000000..88602fb6 --- /dev/null +++ b/src/com.gluster.storage.management.server/build/glusterserver.ant @@ -0,0 +1,64 @@ + + + + + + + + + + + -------------------------------------------------- + compile - Compile + archive - Generate WAR file + -------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java new file mode 100644 index 00000000..384038f4 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java @@ -0,0 +1,120 @@ +/** + * DefaultVolumeOptions.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.server.constants; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +@XmlRootElement +public class VolumeOptionsDefaults { + @XmlElementWrapper(name = "volumeOptions") + @XmlElement(name = "volumeOption", type = VolumeOptionInfo.class) + public List options; + + public VolumeOptionsDefaults() { + } + + public VolumeOptionsDefaults getDefaults() { + options = getVolumeOptionsInfo(); + return this; + } + + /** + * Fetches the list of all volume options with their information from GlusterFS and returns the same + * + * @return List of volume option information objects + */ + private List getVolumeOptionsInfo() { + List volumeOptionsInfo = new ArrayList(); + + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.stripe-block-size", + "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " + + CoreConstants.NEWLINE + + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern . ", + "*:128KB")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.self-heal-window-size", + "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", + "16")); + volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", + "cluster.data-self-heal-algorithm", "auto")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "network.frame-timeout", + "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", + "1800")); + volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", + "The time duration for which the client waits to check if the server is responsive.", "42")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", + "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", + "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.cache-refresh-timeout", + "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", + "1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", + "Size of the per-file write-behind buffer.", "1MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", + "performance.cache-max-file-size", "-1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", + "performance.cache-min-file-size", "0")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.io-thread-count", + " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", + "16")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "diagnostics.latency-measurement", + "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", + "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", + "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", + "Changes the log-level of the bricks (servers).", "NORMAL")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", + "Changes the log-level of the clients.", "NORMAL")); + volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", + "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", + "off")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "nfs.mem-factor", + "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", + "15")); + volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); + + return volumeOptionsInfo; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java new file mode 100644 index 00000000..e669a130 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java @@ -0,0 +1,48 @@ +/** + * GlusterDataSource.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.server.data; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.stereotype.Component; + +@Component +public class GlusterDataSource extends DriverManagerDataSource { + @Autowired + ServletContext servletContext; + + public GlusterDataSource() { + setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); + + setUsername("gluster"); + // TODO: change to a stronger (encrypted) password + setPassword("gluster"); + } + + public DriverManagerDataSource getDataSource() { + // Database directory = work/data relative to context root + setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); + + return this; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java new file mode 100644 index 00000000..004160a7 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java @@ -0,0 +1,79 @@ +/** + * AbstractServersResource.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.server.resources; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.Server; + +/** + * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". + */ +public class AbstractServersResource { + // TODO: Used for generating dummy ip address. To be removed after implementing actual logic for fetching server + // details + private static int ipCount = 1; + + /** + * Fetch details of the given server. The server name must be populated in the object before calling this method. + * + * @param server + * Server whose details are to be fetched + */ + protected void fetchServerDetails(Server server) { + String serverName = server.getName(); + + // TODO: Fetch the server details and populate in the object. + // For now, populating dummy data. + populateDummyData(server); + } + + /** + * @param server + */ + private void populateDummyData(Server server) { + server.setNumOfCPUs((int) (Math.ceil(Math.random() * 8))); + server.setCpuUsage(Math.random() * 100); + server.setTotalMemory(Math.ceil(Math.random() * 8)); + server.setMemoryInUse(Math.random() * server.getTotalMemory()); + addDummyDisks(server); + addDummyNetworkInterfaces(server, (int) Math.ceil(Math.random() * 4)); + } + + private void addDummyNetworkInterfaces(Server server, int interfaceCount) { + for (int i = 0; i < interfaceCount; i++) { + server.addNetworkInterface(new NetworkInterface("eth" + i, server, "192.168.1." + ipCount++, + "255.255.255.0", "192.168.1.1")); + } + } + + /** + * @param server + */ + private void addDummyDisks(Server server) { + double dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sda", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sdb", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sdc", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java new file mode 100644 index 00000000..5987857a --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * 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.server.resources; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerListResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.StringListResponse; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path("/discoveredservers") +public class DiscoveredServersResource extends AbstractServersResource { + private List discoveredServerNames = new ArrayList(); + + public List getDiscoveredServerNames() { + return discoveredServerNames; + } + + @GET + @Produces(MediaType.TEXT_XML) + public Response getDiscoveredServers(@QueryParam("details") Boolean getDetails) { + if(getDetails != null && getDetails == true) { + return new ServerListResponse(Status.STATUS_SUCCESS, getDiscoveredServerDetails()); + } + return new StringListResponse(getDiscoveredServerNames()); + } + + private List getDiscoveredServerDetails() { + List discoveredServers = new ArrayList(); + List serverNames = getDiscoveredServerNames(); + for (String serverName : serverNames) { + discoveredServers.add(getDiscoveredServer(serverName)); + } + return discoveredServers; + } + + public void setDiscoveredServerNames(List discoveredServerNames) { + synchronized (discoveredServerNames) { + this.discoveredServerNames = discoveredServerNames; + } + } + + @Path("/{serverName}") + @GET + @Produces(MediaType.TEXT_XML) + public Server getDiscoveredServer(@PathParam("serverName") String serverName) { + Server server = new Server(serverName); + fetchServerDetails(server); + return server; + } + + public static void main(String[] args) { + StringListResponse listResponse = (StringListResponse)new DiscoveredServersResource().getDiscoveredServers(false); + for (String server : listResponse.getData()) { + System.out.println(server); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java new file mode 100644 index 00000000..6204bf9b --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * 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.server.resources; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.GlusterServerListResponse; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.utils.GlusterUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path("/cluster/servers") +public class GlusterServersResource extends AbstractServersResource { + private GlusterUtil glusterUtil = new GlusterUtil(); + public static final String HOSTNAMETAG = "hostname:"; + + private List getServerDetails() { + List glusterServers = glusterUtil.getGlusterServers(); + for (GlusterServer server : glusterServers) { + if (server.getStatus() == SERVER_STATUS.ONLINE) { + fetchServerDetails(server); + // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); + } + } + return glusterServers; + } + + @GET + @Produces(MediaType.TEXT_XML) + public GlusterServerListResponse getGlusterServers() { + return new GlusterServerListResponse(Status.STATUS_SUCCESS, getServerDetails()); + } + + @GET + @Path("{serverName}") + @Produces(MediaType.TEXT_XML) + public GlusterServer getGlusterServer(@PathParam("serverName") String serverName) { + GlusterServer server = new GlusterServer(serverName); + fetchServerDetails(server); + // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); + server.setStatus(SERVER_STATUS.ONLINE); + return server; + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.server.resources.AbstractServersResource#fetchServerDetails(com.gluster.storage + * .management.core.model.Server) + */ + @Override + protected void fetchServerDetails(Server server) { + // fetch standard server details like cpu, disk, memory details + super.fetchServerDetails(server); + + // TODO: Fetch gluster server details like status + } + + @POST + @Produces(MediaType.TEXT_XML) + public GlusterServerResponse addServer(@FormParam("serverName") String serverName) { + ProcessResult result = glusterUtil.addServer(serverName); + + if (!result.isSuccess()) { + Status failure = new Status(Status.STATUS_CODE_FAILURE, "Add server [" + serverName + "] failed: [" + result.getExitValue() + + "][" + result.getOutput() + "]"); + return new GlusterServerResponse(failure, null); + } + return new GlusterServerResponse(Status.STATUS_SUCCESS, getGlusterServer(serverName)); + } + + public static void main(String[] args) { + GlusterServersResource glusterServersResource = new GlusterServersResource(); + System.out.println(glusterServersResource.getServerDetails()); + + // To add a server + GlusterServerResponse response = glusterServersResource.addServer("my-server"); + System.out.println(response.getData().getName()); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java new file mode 100644 index 00000000..4e379199 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * 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.server.resources; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +//Sets the path to base URL + /hello +@Path("/hello") +public class Hello { + // This method is called if TEXT_PLAIN is request + @GET + @Produces(MediaType.TEXT_PLAIN) + public String sayPlainTextHello() { + return "Hello Jersey"; + } + + // This method is called if XMLis request + @GET + @Produces(MediaType.TEXT_XML) + public String sayXMLHello() { + return "" + " Hello Jersey" + ""; + } + + // This method is called if HTML is request + @GET + @Produces(MediaType.TEXT_HTML) + public String sayHtmlHello() { + return " " + "" + "Hello Jersey" + "" + + "

    " + "Hello Jersey" + "

    " + " "; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java new file mode 100644 index 00000000..2cec4c36 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * 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.server.resources; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_RUNNING_TASKS; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.RunningTaskListResponse; +import com.gluster.storage.management.core.model.RunningTaskStatus; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.server.runningtasks.managers.RunningTaskManager; + +@Component +@Path(RESOURCE_PATH_RUNNING_TASKS) +public class RunningTaskResource { + + @GET + @Produces(MediaType.TEXT_XML) + public RunningTaskListResponse getRunningTasks() { + + RunningTaskStatus status = new RunningTaskStatus(); + List runningTasks = new ArrayList(); + + status.setCode(Status.STATUS_CODE_RUNNING); + status.setPercentageSupported(false); + + // Volume rebalance + RunningTask task = new RunningTask(); + task.setId("0001"); + task.setType("VolumeRebalance"); + task.setReference(""); + task.setDescription("Volume [Volume1] rebalance is running"); + task.setStatus(status); + runningTasks.add(task); + + task = new RunningTask(); + task.setId("0002"); + task.setType("VolumeRebalance"); + task.setReference(""); + task.setDescription("Volume [Volume2] rebalance is running"); + //task.setDescription("Error: volume rebalance operation failed at fd 0000 [/export/test-song-volume/mydirectory/test-video.avi"); + task.setStatus(status); + runningTasks.add(task); + + // MigrateDisk + task = new RunningTask(); + task.setId("0003"); + task.setType("MigrateDisk"); + task.setReference(""); + task.setDescription("Disk migration [Volume3/sda] is running"); + task.setStatus(status); + runningTasks.add(task); + + // FormatDisk + task = new RunningTask(); + task.setId("0004"); + task.setType("FormatDisk"); + task.setReference(""); + task.setDescription("Volume [vol1] rebalance is running"); + status.setPercentageSupported(true); + status.getPercentCompleted(45); + task.setStatus(status); + runningTasks.add(task); + return new RunningTaskListResponse(Status.STATUS_SUCCESS, runningTasks); + } + + @SuppressWarnings("rawtypes") + public Response startTask(@FormParam("taskType") String taskType) { + String managerClassName = "com.gluster.storage.management.server.runningtasks.managers." + taskType + "Manager"; + Class managerClass; + RunningTaskManager manager = null; + try { + managerClass = Class.forName(managerClassName); + manager = (RunningTaskManager) managerClass.newInstance(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + // TODO: set form params on the manager + Map params = null; + manager.setFormParams(params); + manager.start(); + return null; + } + + // TODO Remove the test script for production + public static void main(String[] args) { + RunningTaskResource rt = new RunningTaskResource(); + RunningTaskListResponse tasks = rt.getRunningTasks(); + List runningTasks = tasks.getRunningTasks(); + for( RunningTask x : runningTasks) { + System.out.println( x.getId() + " : " + x.getType() + " : " + x.getDescription() ); + } + } +} + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java new file mode 100644 index 00000000..97b874e2 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.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.server.resources; + +import java.io.File; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.gluster.storage.management.core.utils.FileUtil; +import com.gluster.storage.management.core.utils.MD5Crypt; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; + +@Path("/server") +public class ServerResource { + // TODO: xml should be read from a "work" directory under the tomcat server. + // Use relative path - do not hard code the absolute path. + public static final String DISCOVERED_SERVERS_XML = "/GLUSTER/discovered-servers.xml"; + + /** + * Discover newly available servers + * + * @return list of discovered servers + */ + private String GetDiscoveredServers() { + File discoveredServersFile = new File(DISCOVERED_SERVERS_XML); + String serverNames = new FileUtil().readFileAsString(discoveredServersFile); + return serverNames; + } + + @Path("/discover") + @GET + @Produces(MediaType.TEXT_XML) + public String discoveredServers() { + return GetDiscoveredServers(); + } + + private String GetDetails() { + ProcessResult result = new ProcessUtil().executeCommand("get-server-details.py"); + if (!result.isSuccess()) { + //TODO:Generate error message and return + } + return result.getOutput(); + } + + @Path("/details") + @GET + @Produces(MediaType.TEXT_XML) + public String serverDetails() { + return GetDetails(); + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java new file mode 100644 index 00000000..51134317 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.server.resources; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.encoding.PasswordEncoder; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.provisioning.JdbcUserDetailsManager; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Status; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Component +@Path("/users") +public class UsersResource { + @Autowired + private JdbcUserDetailsManager jdbcUserService; + + @Autowired + private PasswordEncoder passwordEncoder; + + /** + * Authenticates given user with given password for login on current system + * + * @param user + * @param password + * @return true is user can be successfully authenticated using given password, else false + */ + /* + * NOTE: This method is no more required as user authentication is performed on every request by the spring security + * framework. Can be removed after testing. + */ + /* + * private boolean authenticate(String user, String password) { String tmpFileName = "tmp"; File saltFile = new + * File(tmpFileName); ProcessResult result = new ProcessUtil().executeCommand("get-user-password.py", user, + * tmpFileName); if (result.isSuccess()) { String salt = new FileUtil().readFileAsString(saltFile); String + * encryptedPassword = MD5Crypt.crypt(password, salt); return encryptedPassword.equals(salt); } + * + * return false; } + */ + + @Path("{user}") + @GET + @Produces(MediaType.TEXT_XML) + public Status login(@PathParam("user") String user) { + // success only if the user passed in query is same as the one passed in security header + return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? Status.STATUS_SUCCESS + : Status.STATUS_FAILURE); + } + + @Path("{user}") + @PUT + @Produces(MediaType.TEXT_XML) + public Status changePassword(@FormParam("oldpassword") String oldPassword, + @FormParam("newpassword") String newPassword) { + try { + jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); + } catch (AuthenticationException ex) { + ex.printStackTrace(); + return new Status(Status.STATUS_CODE_FAILURE, "Could not change password: [" + ex.getMessage() + "]"); + } + return Status.STATUS_SUCCESS; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java new file mode 100644 index 00000000..dfa5a5cc --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -0,0 +1,93 @@ +/** + * VolumesResource.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.server.resources; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_START; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_STOP; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_VOLUMES; +import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_DEFAULT_OPTIONS; + +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.GlusterUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.server.constants.VolumeOptionsDefaults; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Path(RESOURCE_PATH_VOLUMES) +public class VolumesResource { + private final GlusterUtil glusterUtil = new GlusterUtil(); + + @POST + @Consumes(MediaType.TEXT_XML) + @Produces(MediaType.TEXT_XML) + public GenericResponse createVolume(Volume volume) { + ProcessResult response = glusterUtil.createVolume(volume); + if (!response.isSuccess()) { + return new GenericResponse(Status.STATUS_FAILURE, "Volume creation failed: [" + + response.getOutput() + "]"); + } + + response = glusterUtil.setVolumeAccessControl(volume); + + return new GenericResponse(Status.STATUS_SUCCESS, response.getOutput()); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.TEXT_XML) + public Status performOperation(@FormParam(FORM_PARAM_OPERATION) String operation, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + + if (operation.equals(FORM_PARAM_VALUE_START)) { + return new Status(glusterUtil.startVolume(volumeName)); + } + if (operation.equals(FORM_PARAM_VALUE_STOP)) { + return new Status(glusterUtil.stopVolume(volumeName)); + } + return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + } + + @GET + @Path(SUBRESOURCE_DEFAULT_OPTIONS) + @Produces(MediaType.TEXT_XML) + public VolumeOptionsDefaults getDefaultOptions() { + // TODO: Fetch all volume options with their default values from GlusterFS + // whenever such a CLI command is made available in GlusterFS + return new VolumeOptionsDefaults().getDefaults(); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java new file mode 100644 index 00000000..37cc22f6 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class FormatDiskManager implements RunningTaskManager { + + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java new file mode 100644 index 00000000..97916abe --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java @@ -0,0 +1,50 @@ +package com.gluster.storage.management.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class MigrateDiskManager implements RunningTaskManager { + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java new file mode 100755 index 00000000..a21c6b81 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public interface RunningTaskManager { + + public String getId(); + + public RunningTaskStatus start(); + + public RunningTaskStatus stop(); + + public RunningTaskStatus pause(); + + public RunningTaskStatus resume(); + + public RunningTaskStatus getStatus(); + + @SuppressWarnings("rawtypes") + public void setFormParams(Map params); + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java new file mode 100644 index 00000000..01a5dc25 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java @@ -0,0 +1,50 @@ +package com.gluster.storage.management.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class VolumeRebalanceManager implements RunningTaskManager { + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java new file mode 100644 index 00000000..21c13a03 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java @@ -0,0 +1,31 @@ +/** + * GlusterUserDetailsService.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.server.security; + +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * + */ +public interface GlusterUserDetailsService extends UserDetailsService { + void changePassword(String username, String password); +} + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java new file mode 100644 index 00000000..cfc6e572 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java @@ -0,0 +1,42 @@ +/** + * UserAuthDao.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.server.security; + +import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; + +/** + * @author root + * + */ +public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.server.security.GlusterUserDetailsService#changePassword(java.lang.String, + * java.lang.String) + */ + @Override + public void changePassword(String username, String password) { + getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java new file mode 100644 index 00000000..d96db6ca --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java @@ -0,0 +1,99 @@ +/** + * GlusterServerInitializer.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.server.tasks; + +import java.io.ByteArrayOutputStream; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.apache.derby.tools.ij; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.security.authentication.encoding.PasswordEncoder; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.utils.FileUtil; + +/** + * Initializes the Gluster Management Server. + */ +public class InitServerTask extends JdbcDaoSupport { + @Autowired + private PasswordEncoder passwordEncoder; + + public void securePasswords() { + getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + String username = rs.getString(1); + String password = rs.getString(2); + String encodedPassword = passwordEncoder.encodePassword(password, null); + getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); + logger.debug("Updating password for username: " + username); + } + }); + } + + private void executeScript(String script) { + ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); + int numOfExceptions; + try { + numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), + new FileUtil().loadResource(script), CoreConstants.ENCODING_UTF8, sqlOut, + CoreConstants.ENCODING_UTF8); + String output = sqlOut.toString(); + sqlOut.close(); + logger.debug("Data script [" + script + "] returned with exit status [" + numOfExceptions + + "] and output [" + output + "]"); + if (numOfExceptions != 0) { + throw new GlusterRuntimeException("Server data initialization script [ " + script + "] failed with [" + + numOfExceptions + "] exceptions! [" + output + "]"); + } + } catch (Exception ex) { + ex.printStackTrace(); + throw new GlusterRuntimeException("Server data initialization script [" + script + "] failed!", ex); + } + } + + private void initDatabase() { + logger.debug("Initializing server data..."); + executeScript("data/scripts/security-schema.sql"); + executeScript("data/scripts/users-authorities-groups.sql"); + securePasswords(); // encrypt the passwords + } + + /** + * Initializes the server database, if running for the first time. + */ + public synchronized void initServer() { + try { + // Query to check whether the user table exists + getJdbcTemplate().queryForInt("select count(*) from users"); + logger.debug("Server data is already initialized!"); + } catch (DataAccessException ex) { + // Database not created yet. Create it! + initDatabase(); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java new file mode 100644 index 00000000..9fcb28e6 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java @@ -0,0 +1,75 @@ +/** + * ServerDiscoveryTask.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.server.tasks; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.server.resources.DiscoveredServersResource; +import com.gluster.storage.management.server.utils.ServerUtil; +import com.sun.jersey.spi.resource.Singleton; + +/** + * Task for auto-discovery of servers eligible to be added to the Gluster cluster. This task runs periodically and keeps + * the discovered server list at a common place. The server resource can then pick it and send to client whenever + * demanded. + */ +@Singleton +@Component +public class ServerDiscoveryTask { + private static final String ENV_AWS = "aws"; + private static final String ENV_VMWARE = "vmware"; + private static final String ENV_PHYCAL = "physical"; + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private ServletContext servletContext; + + @Autowired + private DiscoveredServersResource discoveredServersResource; + + @Autowired + private String environment; + + public void discoverServers() { + List serverNameList = new ArrayList(); + + ProcessResult result = serverUtil.executeGlusterScript(true, environment + SCRIPT_NAME_SFX, new ArrayList()); + if(result.isSuccess()) { + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + serverNameList = Arrays.asList(parts); + } + + discoveredServersResource.setDiscoveredServerNames(serverNameList); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java new file mode 100644 index 00000000..1d237461 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java @@ -0,0 +1,58 @@ +/** + * ServerUtil.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.server.utils; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Component +public class ServerUtil { + @Autowired + ServletContext servletContext; + + private static final String SCRIPT_DIR = "scripts"; + private static final String SCRIPT_COMMAND = "python"; + + public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List arguments) { + List command = new ArrayList(); + + command.add(SCRIPT_COMMAND); + command.add(getScriptPath(scriptName)); + command.addAll(arguments); + return new ProcessUtil().executeCommand(runInForeground, command); + } + + private String getScriptPath(String scriptName) { + String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; + return scriptPath; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql b/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql new file mode 100644 index 00000000..fdde5823 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql @@ -0,0 +1,26 @@ +create table users( + username varchar(50) not null primary key, + password varchar(50) not null, + enabled smallint not null + ); + + create table authorities ( + username varchar(50) not null, + authority varchar(50) not null, + constraint fk_authorities_users foreign key(username) references users(username)); + create unique index ix_auth_username on authorities (username,authority); + +create table groups ( + id bigint generated by default as identity(start with 0) primary key, + group_name varchar(50) not null); + +create table group_authorities ( + group_id bigint not null, + authority varchar(50) not null, + constraint fk_group_authorities_group foreign key(group_id) references groups(id)); + +create table group_members ( + id bigint generated by default as identity(start with 0) primary key, + username varchar(50) not null, + group_id bigint not null, + constraint fk_group_members_group foreign key(group_id) references groups(id)); diff --git a/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql b/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql new file mode 100644 index 00000000..35ccf965 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql @@ -0,0 +1,21 @@ +-- Create users +insert into users(username, password, enabled) values ('gluster','gluster',1); +insert into users(username, password, enabled) values ('guest','guest',1); + +-- Assign authorities to users (to be removed after implementing user group functionality) +insert into authorities(username,authority) values ('gluster','ROLE_USER'); +insert into authorities(username,authority) values ('gluster','ROLE_ADMIN'); +insert into authorities(username,authority) values ('guest','ROLE_USER'); + +-- Create user groups +insert into groups(group_name) values ('Users'); +insert into groups(group_name) values ('Administrators'); + +-- Add authorities to groups (functionality not yet implemented in code) +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Users'; +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Administrators'; +insert into group_authorities(group_id, authority) select id,'ROLE_ADMIN' from groups where group_name='Administrators'; + +-- Assign group members +insert into group_members(group_id, username) select id,'guest' from groups where group_name='Users'; +insert into group_members(group_id, username) select id,'gluster' from groups where group_name='Administrators'; \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml new file mode 100644 index 00000000..86a8708f --- /dev/null +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + getDataSource + + + + + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml new file mode 100644 index 00000000..0de97761 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com.sun.jersey/.project b/src/com.sun.jersey/.project new file mode 100644 index 00000000..52ec5691 --- /dev/null +++ b/src/com.sun.jersey/.project @@ -0,0 +1,28 @@ + + + com.sun.jersey + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + -- cgit