diff options
| author | Selvasundaram <selvam@gluster.com> | 2011-06-14 17:44:18 +0530 |
|---|---|---|
| committer | Selvasundaram <selvam@gluster.com> | 2011-06-14 17:44:18 +0530 |
| commit | a9a363955177bf1909b827a64faf9aa8a8a394bc (patch) | |
| tree | 000b0e8f23b96f89e2cec59c553e8e3082abc2fd | |
| parent | b69820a90ab95748b357c953cc84d8d34fbb3d67 (diff) | |
| parent | 4b130d0a4ea2ee00c664fd6c7406268a565a8f03 (diff) | |
Merge branch 'master' of github.com:gluster/console
47 files changed, 1936 insertions, 820 deletions
diff --git a/build/package-server.sh b/build/package-server.sh index 62aae70d..0f4f1b0d 100755 --- a/build/package-server.sh +++ b/build/package-server.sh @@ -1,4 +1,4 @@ -WAR_NAME="glustermc.war" +WAR_NAME="glustermg.war" TAR_NAME=${WAR_NAME}.tar SERVER_DIST_DIR="${WORKSPACE}/../../gmc-server/lastSuccessful" 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 index 0fc0f507..8e0311f5 100644 --- 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 @@ -20,20 +20,21 @@ package com.gluster.storage.management.core.model; import java.util.List; -public class EntityGroup<T> extends Entity { - private Class<? extends Entity> type; +public class EntityGroup<T extends Entity> extends Entity { + private Class<T> type; - public EntityGroup(String name, Class<? extends Entity> type, Cluster cluster) { + public EntityGroup(String name, Class<T> type, Cluster cluster) { this(name, type, cluster, null); } - public EntityGroup(String name, Class<? extends Entity> type, Cluster cluster, List<T> entities) { + @SuppressWarnings("unchecked") + public EntityGroup(String name, Class<T> type, Cluster cluster, List<T> entities) { super(name, cluster, (List<Entity>)entities); this.type = type; } - public List<? extends Entity> getEntities() { - return children; + public List<T> getEntities() { + return (List<T>)children; } public void setEntities(List<T> entities) { 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 index d93ab2fb..d10dfee5 100644 --- 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 @@ -107,20 +107,28 @@ public class FileUtil { * the file or dir to delete * @return true if all files are successfully deleted */ - public static boolean recursiveDelete(File fileOrDir) + public static void recursiveDelete(File fileOrDir) { if(fileOrDir.isDirectory()) { // recursively delete contents for(File innerFile: fileOrDir.listFiles()) { - if(!recursiveDelete(innerFile)) - { - return false; - } + recursiveDelete(innerFile); } } - return fileOrDir.delete(); + if(!fileOrDir.delete()) { + throw new GlusterRuntimeException("Couldn't delete file/directory [" + fileOrDir + "]"); + } + } + + public static void renameFile(String fromPath, String toPath) { + File fromFile = new File(fromPath); + File toFile = new File(toPath); + + if(!fromFile.renameTo(toFile)) { + throw new GlusterRuntimeException("Couldn't rename [" + fromFile + "] to [" + toFile + "]"); + } } -}
\ No newline at end of file +} diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index f4c3c8f6..af065b7d 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -900,7 +900,7 @@ </view> <view closeable="false" - id="com.gluster.storage.management.gui.views.VolumeDisksView" + id="com.gluster.storage.management.gui.views.VolumeBricksView" minimized="false" moveable="false" ratio="0.30f" @@ -1012,7 +1012,7 @@ point="org.eclipse.ui.decorators"> <decorator adaptable="false" - class="com.gluster.storage.management.gui.views.navigator.NavigationTreeLabelDecorator" + class="com.gluster.storage.management.gui.views.NavigationTreeLabelDecorator" id="com.gluster.storage.management.gui.views.navigator.decorator" label="Navigation Tree Decorator" lightweight="true" diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/BrickTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/BrickTableLabelProvider.java index aeea7c90..2d64782b 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/BrickTableLabelProvider.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/BrickTableLabelProvider.java @@ -27,8 +27,8 @@ 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.BricksPage.BRICK_TABLE_COLUMN_INDICES; -import com.gluster.storage.management.gui.views.details.DisksPage.DISK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.gui.views.pages.BricksPage.BRICK_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.gui.views.pages.DisksPage.DISK_TABLE_COLUMN_INDICES; public class BrickTableLabelProvider extends TableLabelProviderAdapter { private GUIHelper guiHelper = GUIHelper.getInstance(); 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 index c09331fa..c355ac50 100644 --- 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 @@ -26,7 +26,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.DisksPage.DISK_TABLE_COLUMN_INDICES; public class DiskTableLabelProvider extends TableLabelProviderAdapter { private GUIHelper guiHelper = GUIHelper.getInstance(); 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 index 61e98cb8..03b2d978 100644 --- 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 @@ -24,7 +24,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.GlusterServersPage.GLUSTER_SERVER_TABLE_COLUMN_INDICES; public class GlusterServerTableLabelProvider extends TableLabelProviderAdapter { private GUIHelper guiHelper = GUIHelper.getInstance(); 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 index ecff0ca7..57a7b312 100644 --- 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 @@ -27,7 +27,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.ServerDisksPage.SERVER_DISK_TABLE_COLUMN_INDICES; public class ServerDiskTableLabelProvider extends TableLabelProviderAdapter { private GUIHelper guiHelper = GUIHelper.getInstance(); 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 index 396d1821..39eea7ba 100644 --- 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 @@ -21,7 +21,7 @@ package com.gluster.storage.management.gui; import com.gluster.storage.management.core.model.VolumeLogMessage; import com.gluster.storage.management.core.utils.DateUtil; -import com.gluster.storage.management.gui.views.details.VolumeLogsPage.LOG_TABLE_COLUMN_INDICES; +import com.gluster.storage.management.gui.views.pages.VolumeLogsPage.LOG_TABLE_COLUMN_INDICES; public class VolumeLogTableLabelProvider extends TableLabelProviderAdapter { @Override 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 index cf1ceaf7..007c7adb 100644 --- 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 @@ -21,7 +21,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.VolumeOptionsPage.OPTIONS_TABLE_COLUMN_INDICES; public class VolumeOptionsTableLabelProvider extends TableLabelProviderAdapter { private GUIHelper guiHelper = GUIHelper.getInstance(); 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 index 4fd99cc7..67948fb8 100644 --- 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 @@ -23,6 +23,7 @@ import java.util.Set; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; import com.gluster.storage.management.client.GlusterDataModelManager; @@ -34,10 +35,11 @@ import com.gluster.storage.management.core.response.GlusterServerResponse; import com.gluster.storage.management.gui.utils.GUIHelper; public class AddServerAction extends AbstractActionDelegate { + private GUIHelper guiHelper = GUIHelper.getInstance(); + @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - + final Runnable addServerThread = new Runnable() { @Override public void run() { GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); @@ -49,6 +51,7 @@ public class AddServerAction extends AbstractActionDelegate { String errMsg = ""; String partErrMsg = ""; for (Server server : selectedServers) { + guiHelper.setStatusMessage("Adding server [" + server.getName() + "]..."); GlusterServerResponse response = glusterServersClient.addServer(server); Status status = response.getStatus(); if (status.isSuccess()) { @@ -65,8 +68,16 @@ public class AddServerAction extends AbstractActionDelegate { } } + guiHelper.clearStatusMessage(); showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, errMsg, partErrMsg); } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + Display.getDefault().asyncExec(addServerThread); + } }); } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java index d7a63323..8de8aa2d 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java @@ -26,22 +26,21 @@ import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; -import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; /** * */ public class DownloadVolumeLogsAction extends AbstractActionDelegate { + private GUIHelper guiHelper = GUIHelper.getInstance(); /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() */ @Override public void dispose() { - // TODO Auto-generated method stub - } /* (non-Javadoc) @@ -49,13 +48,14 @@ public class DownloadVolumeLogsAction extends AbstractActionDelegate { */ @Override protected void performAction(IAction action) { - final Volume volume = (Volume)selectedEntity; final VolumesClient client = new VolumesClient(); final Runnable downloadLogsThread = new Runnable() { @Override public void run() { + Volume volume = guiHelper.getSelectedEntity(getWindow(), Volume.class); + FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); dialog.setFilterNames(new String[] {"GZipped Tar (*.tar.gz)"}); dialog.setFilterExtensions(new String[] {"*.tar.gz"}); 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 index f8f611fb..83489c37 100644 --- 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 @@ -18,7 +18,6 @@ *******************************************************************************/ package com.gluster.storage.management.gui.actions; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -28,29 +27,31 @@ import java.util.Set; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.PlatformUI; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; public class RemoveServerAction extends AbstractActionDelegate { private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private GUIHelper guiHelper = GUIHelper.getInstance(); @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { + final Runnable removeServerThread = new Runnable() { @Override public void run() { final String actionDesc = action.getDescription(); - Set<GlusterServer> selectedServers = GUIHelper.getInstance().getSelectedEntities(getWindow(), + Set<GlusterServer> selectedServers = guiHelper.getSelectedEntities(getWindow(), GlusterServer.class); if (!validate(action, selectedServers)) { @@ -66,6 +67,8 @@ public class RemoveServerAction extends AbstractActionDelegate { Set<GlusterServer> successServers = new HashSet<GlusterServer>(); String errMsg = ""; for (GlusterServer server : selectedServers) { + guiHelper.setStatusMessage("Removing server [" + server.getName() + "]..."); + GlusterServersClient client = new GlusterServersClient(); Status status = client.removeServer(server.getName()); if (status.isSuccess()) { @@ -77,8 +80,16 @@ public class RemoveServerAction extends AbstractActionDelegate { } } + guiHelper.clearStatusMessage(); showStatusMessage(action.getDescription(), selectedServers, successServers, errMsg); } + }; + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + @Override + public void run() { + Display.getDefault().asyncExec(removeServerThread); + } }); } 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 index 4c1bfcd5..a8826772 100644 --- 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 @@ -23,12 +23,10 @@ package com.gluster.storage.management.gui.preferences; */ public class PreferenceConstants { + // TODO: Remove after proper preferences are added 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/utils/GUIHelper.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java index 9e2ec9e0..ac29ecf0 100644 --- 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 @@ -290,15 +290,16 @@ public class GUIHelper { 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); + GridData data = new GridData(SWT.RIGHT, SWT.CENTER, false, false); data.widthHint = 300; filterText.setLayoutData(data); - ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.RIGHT); + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.LEFT); searchDecoration.setImage(getImage(IImageKeys.SEARCH)); searchDecoration.show(); searchDecoration.setShowHover(true); searchDecoration.setDescriptionText(tooltipMessage); + searchDecoration.setMarginWidth(5); filterText.setToolTipText(tooltipMessage); return filterText; 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/ClusterAdapterFactory.java index d7ef44ac..95c16a3c 100644 --- 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/ClusterAdapterFactory.java @@ -16,7 +16,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.navigator; +package com.gluster.storage.management.gui.views; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.jface.resource.ImageDescriptor; 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 index 260d0d4c..0910c080 100644 --- 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 @@ -11,7 +11,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.DisksPage; public class DisksView extends ViewPart { public static final String ID = DisksView.class.getName(); 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 index 624d968d..2a240706 100644 --- 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 @@ -26,7 +26,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.ServerDisksPage; public class GlusterServerDisksView extends ViewPart { public static final String ID = GlusterServerDisksView.class.getName(); 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 index acc8144d..84568ca6 100644 --- 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 @@ -26,7 +26,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.ServerLogsPage; public class GlusterServerLogsView extends ViewPart { public static final String ID = GlusterServerLogsView.class.getName(); 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 index dfaf904a..05bf6778 100644 --- 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 @@ -31,7 +31,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.GlusterServersPage; /** * @author root 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/NavigationTreeLabelDecorator.java index 4cdc2e66..241b6967 100644 --- 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/NavigationTreeLabelDecorator.java @@ -16,7 +16,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.navigator; +package com.gluster.storage.management.gui.views; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelProviderListener; 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 index a5da2f62..458dcf61 100644 --- 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 @@ -41,7 +41,6 @@ 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(); @@ -61,7 +60,7 @@ public class NavigationView extends ViewPart implements ISelectionListener { viewsManager = new GlusterViewsManager(getSite().getPage()); // listen to selection events to update views/toolbar accordingly - getSite().getPage().addPostSelectionListener(this); + getSite().getPage().addSelectionListener(this); } private void createNavigationTree(Composite parent) { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeBricksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeBricksView.java index e6b9bec3..712882ee 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeBricksView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeBricksView.java @@ -7,7 +7,7 @@ import org.eclipse.ui.part.ViewPart; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.gui.utils.GUIHelper; -import com.gluster.storage.management.gui.views.details.BricksPage; +import com.gluster.storage.management.gui.views.pages.BricksPage; public class VolumeBricksView extends ViewPart { public static final String ID = VolumeBricksView.class.getName(); 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 index b6c98ad3..89c343d7 100644 --- 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 @@ -6,7 +6,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.VolumeLogsPage; public class VolumeLogsView extends ViewPart { VolumeLogsPage logsPage; 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 index e8695737..0780cf6a 100644 --- 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 @@ -6,7 +6,7 @@ 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; +import com.gluster.storage.management.gui.views.pages.VolumeOptionsPage; public class VolumeOptionsView extends ViewPart { public static final String ID = VolumeOptionsView.class.getName(); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractBricksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractBricksPage.java deleted file mode 100644 index c752a488..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractBricksPage.java +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> - * 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 - * <http://www.gnu.org/licenses/>. - *******************************************************************************/ -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.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 com.gluster.storage.management.core.model.Brick; -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.Entity; -import com.gluster.storage.management.gui.Application; -import com.gluster.storage.management.gui.IEntityListener; -import com.gluster.storage.management.gui.jobs.InitializeDiskJob; -import com.gluster.storage.management.gui.utils.GUIHelper; - -public abstract class AbstractBricksPage 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<Brick> bricks) { - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - toolkit.dispose(); - } - }); - - this.site = site; - - setupPageLayout(); - Text filterText = guiHelper.createFilterText(toolkit, this); - setupBrickTableViewer(createTableViewerComposite(), filterText); - site.setSelectionProvider(tableViewer); - - tableViewer.setInput(bricks); - - 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 AbstractBricksPage(final Composite parent, int style, IWorkbenchSite site, List<Brick> bricks) { - super(parent, style); - init(parent, site, bricks); - } - - private void setupPageLayout() { - final GridLayout layout = new GridLayout(1, false); - layout.verticalSpacing = 10; - layout.marginTop = 10; - setLayout(layout); - } - - 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 createBrickTableViewer(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 setupBrickTableViewer(Composite parent, final Text filterText) { - tableViewer = createBrickTableViewer(parent); - // Create a case insensitive filter for the table viewer using the filter text field - guiHelper.createFilter(tableViewer, filterText, false); - } -} 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 deleted file mode 100644 index 1f5f8a15..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> - * 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 - * <http://www.gnu.org/licenses/>. - *******************************************************************************/ -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. - * <p> - * <b>Important:</b> 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 deleted file mode 100644 index f5098af5..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> - * 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 - * <http://www.gnu.org/licenses/>. - *******************************************************************************/ -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 deleted file mode 100644 index 28d3d4aa..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> - * 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 - * <http://www.gnu.org/licenses/>. - *******************************************************************************/ -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<String, TabCreator> tabCreatorCache = new HashMap<String, TabCreator>(); - - /** - * Returns tab creator for given entity. The logic is as follows: <br> - * 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 <br> - * 2) If the tab creator is found in the cache, return it <br> - * 3) If not found, create one by instantiating the class "<current package>.tabcreators.<class name>TabCreator". - * Again, "class name" includes "entity type" in case of {@link EntityGroup} <br> - * 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<TabCreator> creatorFactoryClass = (Class<TabCreator>) 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/AbstractDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractDisksPage.java index 6b516019..133aed38 100644 --- 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/pages/AbstractDisksPage.java @@ -16,13 +16,12 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; 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.IContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; @@ -30,106 +29,55 @@ 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.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; 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.core.model.Entity; 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(); +public abstract class AbstractDisksPage extends AbstractTableViewerPage<Disk> implements IEntityListener { + private List<Disk> disks; + /** * @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<Disk> disks) { - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - toolkit.dispose(); - } - }); - - this.site = site; - - setupPageLayout(); - Text filterText = guiHelper.createFilterText(toolkit, this); - setupDiskTableViewer(createTableViewerComposite(), filterText); - site.setSelectionProvider(tableViewer); - - tableViewer.setInput(disks); - setupStatusCellEditor(); // creates hyperlinks for "unitialized" disks - - site.setSelectionProvider(tableViewer); + public AbstractDisksPage(final Composite parent, int style, IWorkbenchSite site, List<Disk> disks) { + super(site, parent, style, disks); + this.disks = disks; + + // creates hyperlinks for "unitialized" disks + setupStatusCellEditor(); + // Listen for disk status change events 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<Disk> disks) { - super(parent, style); - init(parent, site, disks); + + @Override + protected IContentProvider getContentProvider() { + return new ArrayContentProvider(); } - - private void setupPageLayout() { - final GridLayout layout = new GridLayout(1, false); - layout.verticalSpacing = 10; - layout.marginTop = 10; - setLayout(layout); + + @Override + protected List<Disk> getAllEntities() { + return disks; + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener(); } private void createInitializeLink(final TableItem item, final int rowNum, final Disk disk) { @@ -155,7 +103,7 @@ public abstract class AbstractDisksPage extends Composite implements IEntityList 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)); + myLink.addHyperlinkListener(new StatusLinkListener(myLink, myEditor, myItem, tableViewer, disk1)); myEditor.setEditor(myLink, item1, getStatusColumnIndex()); @@ -224,44 +172,18 @@ public abstract class AbstractDisksPage extends Composite implements IEntityList } } - 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) { + Disk disk) { 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) { 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/pages/AbstractTableViewerPage.java index 36f60998..dfa06f85 100644 --- 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/pages/AbstractTableViewerPage.java @@ -16,12 +16,16 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; + +import java.util.List; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -33,50 +37,70 @@ 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.events.HyperlinkAdapter; import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.ClusterListener; -import com.gluster.storage.management.core.model.DefaultClusterListener; -import com.gluster.storage.management.core.model.EntityGroup; -import com.gluster.storage.management.core.model.Event; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.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 CheckboxTableViewer tableViewer; - private GUIHelper guiHelper = GUIHelper.getInstance(); +public abstract class AbstractTableViewerPage<T> extends Composite { - public enum GLUSTER_SERVER_TABLE_COLUMN_INDICES { - NAME, IP_ADDRESSES, NUM_OF_CPUS, TOTAL_MEMORY, TOTAL_DISK_SPACE, AVAILABLE_DISK_SPACE, STATUS // Removed PREFERRED_NETWORK - }; + protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + protected CheckboxTableViewer tableViewer; + protected GUIHelper guiHelper = GUIHelper.getInstance(); + protected Composite parent; + + private Hyperlink linkAll, linkNone; - private static final String[] GLUSTER_SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", - "IP Address(es)", "Number\nof CPUs", "Total\nMemory (GB)", "Space (GB)", "Space\nAvailable (GB)", "Status" }; // Removed "Preferred\nNetwork", - - public GlusterServersPage(IWorkbenchSite site, final Composite parent, int style, EntityGroup<GlusterServer> servers) { + public AbstractTableViewerPage(IWorkbenchSite site, final Composite parent, int style, Object model) { super(parent, style); + this.parent = parent; toolkit.adapt(this); toolkit.paintBordersFor(this); setupPageLayout(); + + createCheckboxSelectionLinks(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupServerTableViewer(site, filterText); - tableViewer.setInput(servers); + tableViewer.setInput(model); parent.layout(); // Important - this actually paints the table createListeners(parent); } + public void createCheckboxSelectionLinks() { + // create the "select all/none" links + toolkit.createLabel(this, "Select"); + linkAll = toolkit.createHyperlink(this, "all", SWT.NONE); + linkAll.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + tableViewer.setAllChecked(true); + tableViewer.setSelection(new StructuredSelection(getAllEntities())); + } + }); + + toolkit.createLabel(this, " / "); + + linkNone = toolkit.createHyperlink(this, "none", SWT.NONE); + linkNone.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + tableViewer.setAllChecked(false); + tableViewer.setSelection(null); + } + }); + } + private void createListeners(final Composite parent) { /** * Ideally not required. However the table viewer is not getting laid out properly on performing @@ -90,23 +114,7 @@ public class GlusterServersPage extends Composite { } }); - final ClusterListener clusterListener = new DefaultClusterListener() { - - @Override - public void serverAdded(GlusterServer server) { - tableViewer.refresh(); - } - - @Override - public void serverRemoved(GlusterServer server) { - tableViewer.refresh(); - } - - @Override - public void serverChanged(GlusterServer server, Event event) { - tableViewer.update(server, null); - } - }; + final ClusterListener clusterListener = createClusterListener(); final GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); modelManager.addClusterListener(clusterListener); @@ -119,12 +127,19 @@ public class GlusterServersPage extends Composite { }); } + protected abstract ClusterListener createClusterListener(); + protected abstract String[] getColumnNames(); + protected abstract void setColumnProperties(Table table); + protected abstract IBaseLabelProvider getLabelProvider(); + protected abstract IContentProvider getContentProvider(); + protected abstract List<T> getAllEntities(); + public void addDoubleClickListener(IDoubleClickListener listener) { tableViewer.addDoubleClickListener(listener); } private void setupPageLayout() { - final GridLayout layout = new GridLayout(1, false); + final GridLayout layout = new GridLayout(5, false); layout.verticalSpacing = 10; layout.marginTop = 10; setLayout(layout); @@ -134,26 +149,17 @@ public class GlusterServersPage extends Composite { table.setHeaderVisible(true); table.setLinesVisible(false); - TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, GLUSTER_SERVER_TABLE_COLUMN_NAMES); + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, getColumnNames()); 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, GLUSTER_SERVER_TABLE_COLUMN_INDICES.AVAILABLE_DISK_SPACE, SWT.CENTER, 90); - //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + setColumnProperties(table); } private CheckboxTableViewer createServerTableViewer(Composite parent) { CheckboxTableViewer 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<GlusterServer>()); + + tableViewer.setLabelProvider(getLabelProvider()); + tableViewer.setContentProvider(getContentProvider()); setupServerTable(parent, tableViewer.getTable()); @@ -164,6 +170,15 @@ public class GlusterServersPage extends Composite { Composite tableViewerComposite = new Composite(this, SWT.NO); tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + GridData layoutData = new GridData(); + layoutData.horizontalSpan=5; + layoutData.grabExcessHorizontalSpace = true; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.verticalAlignment = SWT.FILL; + layoutData.grabExcessVerticalSpace = true; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; } @@ -178,20 +193,4 @@ public class GlusterServersPage extends Composite { // 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/BricksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java index 51425174..b83914eb 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/BricksPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java @@ -16,31 +16,28 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.List; -import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.IWorkbenchSite; -import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.DefaultClusterListener; -import com.gluster.storage.management.core.model.Entity; import com.gluster.storage.management.core.model.Event; -import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.gui.BrickTableLabelProvider; -public class BricksPage extends AbstractBricksPage { - private Composite parent; +public class BricksPage extends AbstractTableViewerPage<Brick> { + private List<Brick> bricks; public enum BRICK_TABLE_COLUMN_INDICES { SERVER, BRICK, FREE_SPACE, TOTAL_SPACE, STATUS @@ -49,13 +46,14 @@ public class BricksPage extends AbstractBricksPage { private static final String[] DISK_TABLE_COLUMN_NAMES = new String[] { "Server", "Brick Directory", "Free Space (GB)", "Total Space (GB)", "Status" }; - public BricksPage(final Composite parent, int style, IWorkbenchSite site, final List<Brick> bricks) { - super(parent, style, site, bricks); - createListeners(); + public BricksPage(Composite parent, int style, IWorkbenchSite site, final List<Brick> bricks) { + super(site, parent, style, bricks); + this.bricks = bricks; } - private void createListeners() { - final ClusterListener clusterListener = new DefaultClusterListener() { + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { @Override public void volumeChanged(Volume volume, Event event) { if (event.getEventType() == EVENT_TYPE.BRICKS_ADDED || event.getEventType() == EVENT_TYPE.BRICKS_REMOVED) { @@ -65,43 +63,33 @@ public class BricksPage extends AbstractBricksPage { } }; - GlusterDataModelManager.getInstance().addClusterListener(clusterListener); - addDisposeListener(new DisposeListener() { - - @Override - public void widgetDisposed(DisposeEvent e) { - GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); - } - }); } @Override - protected void setupDiskTable(Composite parent, Table table) { - this.parent = parent; - table.setHeaderVisible(true); - table.setLinesVisible(false); - - TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, DISK_TABLE_COLUMN_NAMES); - parent.setLayout(tableColumnLayout); - + protected String[] getColumnNames() { + return DISK_TABLE_COLUMN_NAMES; + } + + @Override + protected void setColumnProperties(Table table) { guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.SERVER.ordinal(), SWT.CENTER, 100); guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.BRICK.ordinal(), SWT.CENTER, 100); guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal(), SWT.CENTER, 90); guiHelper.setColumnProperties(table, BRICK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal(), SWT.CENTER, 90); - } - + @Override - protected ITableLabelProvider getTableLabelProvider() { + protected ITableLabelProvider getLabelProvider() { return new BrickTableLabelProvider(); } - + @Override - protected int getStatusColumnIndex() { - return BRICK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + protected IContentProvider getContentProvider() { + return new ArrayContentProvider(); } - + @Override - public void entityChanged(Entity entity, String[] paremeters) { + protected List<Brick> getAllEntities() { + return bricks; } }
\ No newline at end of file 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/pages/DisksPage.java index 9076d498..bd14607e 100644 --- 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/pages/DisksPage.java @@ -16,12 +16,11 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.List; -import org.eclipse.jface.layout.TableColumnLayout; -import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; @@ -44,25 +43,24 @@ public class DisksPage extends AbstractDisksPage { } @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); + protected String[] getColumnNames() { + return DISK_TABLE_COLUMN_NAMES; + } + @Override + protected void setColumnProperties(Table table) { 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.FREE_SPACE.ordinal(), SWT.CENTER, 90); guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal(), SWT.CENTER, 90); // guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal(), SWT.CENTER, 90); } - + @Override - protected ITableLabelProvider getTableLabelProvider() { + protected IBaseLabelProvider getLabelProvider() { return new DiskTableLabelProvider(); } - + @Override protected int getStatusColumnIndex() { return DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java new file mode 100644 index 00000000..efa2eaaa --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * 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 + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.gui.views.pages; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.GlusterServerTableLabelProvider; + +public class GlusterServersPage extends AbstractTableViewerPage<GlusterServer> { + private List<GlusterServer> glusterServers; + + public enum GLUSTER_SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_CPUS, TOTAL_MEMORY, TOTAL_DISK_SPACE, AVAILABLE_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)", "Space (GB)", "Space\nAvailable (GB)", "Status" }; // Removed "Preferred\nNetwork", + + public GlusterServersPage(IWorkbenchSite site, final Composite parent, int style, final EntityGroup<GlusterServer> servers) { + super(site, parent, style, servers); + this.glusterServers = servers.getEntities(); + } + + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + + @Override + public void serverAdded(GlusterServer server) { + tableViewer.refresh(); + } + + @Override + public void serverRemoved(GlusterServer server) { + tableViewer.refresh(); + } + + @Override + public void serverChanged(GlusterServer server, Event event) { + tableViewer.update(server, null); + } + }; + } + + @Override + protected void setColumnProperties(Table table) { + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 100); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS, SWT.CENTER, 70); + // setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.PREFERRED_NETWORK, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.AVAILABLE_DISK_SPACE, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new GlusterServerTableLabelProvider(); + } + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider<GlusterServer>(); + } + + @Override + protected String[] getColumnNames() { + return GLUSTER_SERVER_TABLE_COLUMN_NAMES; + } + + @Override + protected List<GlusterServer> getAllEntities() { + return glusterServers; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, GLUSTER_SERVER_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/OptionKeyEditingSupport.java index 27dc8d4b..87bd1154 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/OptionKeyEditingSupport.java @@ -1,7 +1,7 @@ /** * */ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.ArrayList; import java.util.Iterator; diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/OptionValueEditingSupport.java index ca222dd0..a5edd7cb 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/OptionValueEditingSupport.java @@ -1,7 +1,7 @@ /** * */ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.List; import java.util.Map.Entry; 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/pages/ServerDisksPage.java index bace2af9..c2f76a43 100644 --- 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/pages/ServerDisksPage.java @@ -16,11 +16,11 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.List; -import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; @@ -28,7 +28,6 @@ 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<Disk> disks) { @@ -43,26 +42,25 @@ public class ServerDisksPage extends AbstractDisksPage { "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); - + protected String[] getColumnNames() { + return SERVER_DISK_TABLE_COLUMN_NAMES; + } + + @Override + protected void setColumnProperties(Table table) { 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() { + protected IBaseLabelProvider getLabelProvider() { 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/pages/ServerLogsPage.java index a499caf3..7cde38bb 100644 --- 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/pages/ServerLogsPage.java @@ -16,7 +16,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.ArrayList; import java.util.List; 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 index 20c3cbd4..48b8892c 100644 --- 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 @@ -18,41 +18,28 @@ *******************************************************************************/ package com.gluster.storage.management.gui.views.pages; +import java.util.List; + 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.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; 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.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.EntityGroup; import com.gluster.storage.management.core.model.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 CheckboxTableViewer tableViewer; - private GUIHelper guiHelper = GUIHelper.getInstance(); +public class ServersPage extends AbstractTableViewerPage<Server> { + private List<Server> servers; + public enum SERVER_TABLE_COLUMN_INDICES { NAME, IP_ADDRESSES, NUM_OF_DISKS, TOTAL_DISK_SPACE }; @@ -67,39 +54,14 @@ public class ServersPage extends Composite { // "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<Server> 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 - - createListeners(parent); + public ServersPage(final Composite parent, IWorkbenchSite site, EntityGroup<Server> serversGroup) { + super(site, parent, SWT.NONE, serversGroup); + this.servers = serversGroup.getEntities(); } - private void createListeners(final Composite parent) { - /** - * Ideally not required. However the table viewer is not getting laid out properly on performing - * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window - */ - addPaintListener(new PaintListener() { - - @Override - public void paintControl(PaintEvent e) { - parent.layout(); - } - }); - - final ClusterListener clusterListener = new DefaultClusterListener() { + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { @Override public void discoveredServerRemoved(Server server) { refreshViewer(); @@ -115,16 +77,6 @@ public class ServersPage extends Composite { parent.update(); } }; - - final GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); - modelManager.addClusterListener(clusterListener); - addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - toolkit.dispose(); - modelManager.removeClusterListener(clusterListener); - } - }); } public void setInput(EntityGroup<Server> servers) { @@ -132,24 +84,8 @@ public class ServersPage extends Composite { 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); - + @Override + protected void setColumnProperties(Table table) { setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 70); setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES, SWT.CENTER, 100); setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NUM_OF_DISKS, SWT.CENTER, 70); @@ -160,40 +96,26 @@ public class ServersPage extends Composite { // 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 CheckboxTableViewer createServerTableViewer(Composite parent) { - final CheckboxTableViewer 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<Server>()); - - setupServerTable(parent, tableViewer.getTable()); - - // make sure that table selection is driven by checkbox selection - guiHelper.configureCheckboxTableViewer(tableViewer); - - return tableViewer; + + @Override + protected String[] getColumnNames() { + return SERVER_TABLE_COLUMN_NAMES; } - - 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; + + @Override + protected IBaseLabelProvider getLabelProvider() { + return new ServerTableLabelProvider(); } - - private void setupPage(IWorkbenchSite site, EntityGroup<Server> 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); + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider<Server>(); } + + @Override + protected List<Server> getAllEntities() { + return servers; + } /** * Sets properties for alignment and weight of given column of given table @@ -209,5 +131,5 @@ public class ServersPage extends Composite { 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/VolumeLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumeLogsPage.java index 9eb7357e..ab1b353d 100644 --- 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/pages/VolumeLogsPage.java @@ -16,7 +16,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.Calendar; import java.util.Date; 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/pages/VolumeOptionsPage.java index 22d38e50..bd003f3b 100644 --- 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/pages/VolumeOptionsPage.java @@ -16,7 +16,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ -package com.gluster.storage.management.gui.views.details; +package com.gluster.storage.management.gui.views.pages; import java.util.List; import java.util.Map.Entry; 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 index 680dc391..d0824888 100644 --- 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 @@ -18,128 +18,67 @@ *******************************************************************************/ package com.gluster.storage.management.gui.views.pages; +import java.util.List; + 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.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; 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.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; 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 class VolumesPage extends AbstractTableViewerPage<Volume> { + private List<Volume> volumes; + 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\nBricks", "Transport Type", "Status" }; - - public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup<Volume> volumes) { - super(parent, SWT.NONE); - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - toolkit.dispose(); - } - }); + private static final String[] VOLUME_TABLE_COLUMN_NAMES = new String[] { "Name", "Volume Type", + "Number of\nBricks", "Transport Type", "Status" }; - 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); + public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup<Volume> volumes) { + super(site, parent, SWT.NONE, volumes); } - private void setupPageLayout() { - final GridLayout layout = new GridLayout(1, false); - layout.verticalSpacing = 10; - layout.marginTop = 10; - setLayout(layout); + @Override + protected String[] getColumnNames() { + return VOLUME_TABLE_COLUMN_NAMES; } - - 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); - + + @Override + protected void setColumnProperties(Table table) { setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS, SWT.CENTER, 50); setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.NUM_OF_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<Volume>()); - - setupVolumeTable(parent, tableViewer.getTable()); - - return tableViewer; + @Override + protected IBaseLabelProvider getLabelProvider() { + return new VolumeTableLabelProvider(); } - - 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; + + @Override + protected IContentProvider getContentProvider() { + return new EntityGroupContentProvider<Volume>(); } - - private void setupVolumeTableViewer(IWorkbenchSite site, EntityGroup<Volume> 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); + + @Override + protected ClusterListener createClusterListener() { + // TODO: Override methods to handle volume related events + return new DefaultClusterListener(); } - + /** * Sets properties for alignment and weight of given column of given table * @@ -156,8 +95,8 @@ public class VolumesPage extends Composite { tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); } - public void setInput(EntityGroup<Volume> volumes) { - tableViewer.setInput(volumes); - tableViewer.refresh(); + @Override + protected List<Volume> getAllEntities() { + return volumes; } } diff --git a/src/com.gluster.storage.management.releng/glustermc_build.properties b/src/com.gluster.storage.management.releng/glustermc_build.properties index b808ec9d..d50782d8 100644 --- a/src/com.gluster.storage.management.releng/glustermc_build.properties +++ b/src/com.gluster.storage.management.releng/glustermc_build.properties @@ -1,10 +1,14 @@ +# Buckminster build properties file for Gluster Management Console + # Where all the output should go -buckminster.output.root=/tmp/buckminster/glustermc +#buckminster.output.root=/tmp/buckminster/glustermc # Where the temp files should go -buckminster.temp.root=/tmp/buckminster +#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 +# Do not include source +cbi.include.source=false + +# Sets the Java compiler compliance level +org.eclipse.buckminster.core.jdt.compliancelevel=1.6 diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py b/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py @@ -0,0 +1,438 @@ +# Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com> +# 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 +# <http://www.gnu.org/licenses/>. + +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 = '''<command request="create-volume" id="123" version="3.1"> +<volume> +<name>movies1</name> +<type>cluster mirror</type> +<start>512000</start> +<server>zresearch</server> +<vacl>192.168.20.*</vacl> +<vacl>192.168.30.*</vacl> +<nfs> +<export>no</export> +</nfs> +<cifs> +<export>no</export> +</cifs> +<webdav> +<export>no</export> +</webdav> +</volume> +</command>''' + + 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/WebContent/scripts/Utils.py b/src/com.gluster.storage.management.server/WebContent/scripts/Utils.py new file mode 100644 index 00000000..f9b3254b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Utils.py @@ -0,0 +1,705 @@ +# Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +# 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 +# <http://www.gnu.org/licenses/>. + +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 +from Common import * + +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 record(priority, message=None): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + stack = inspect.stack()[1] + if stack[3] == "<module>": + 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(): + filedesc, filename = tempfile.mkstemp(prefix="GSP_") + os.close(filedesc) + return filename + + +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<key>\S*):\s*(?P<value>\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 <MAJOR>.<MINOR>.<PATCHLEVEL>" % 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/WebContent/scripts/XmlHandler.py b/src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py new file mode 100644 index 00000000..72164ffb --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py @@ -0,0 +1,346 @@ +# Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com>
+# 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
+# <http://www.gnu.org/licenses/>.
+
+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/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 index a2dfe2e3..1cbab5b0 100644 --- 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 @@ -371,16 +371,16 @@ public class VolumesResource { } @SuppressWarnings("rawtypes") - private Status cleanupDirectories(List<String> disks, String volumeName, int maxIndex, boolean deleteFlag) { - String serverName, diskName, diskInfo[]; + private Status cleanupDirectories(List<String> bricks, String volumeName, int maxIndex, boolean deleteFlag) { Status result; for (int i = 0; i < maxIndex; i++) { - diskInfo = disks.get(i).split(":"); - serverName = diskInfo[0]; - diskName = diskInfo[1]; + String[] brickInfo = bricks.get(i).split(":"); + String serverName = brickInfo[0]; + String brickDirectory = brickInfo[1]; + String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " - + diskName + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); + + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); if (response instanceof GenericResponse) { result = ((GenericResponse) response).getStatus(); if (!result.isSuccess()) { @@ -453,6 +453,7 @@ public class VolumesResource { output.write(FileUtil.readFileAsByteArray(archiveFile)); archiveFile.delete(); } catch (Exception e) { + // TODO: Log the exception e.printStackTrace(); throw new GlusterRuntimeException("Exception while downloading/archiving volume log files!", e); } @@ -472,6 +473,13 @@ public class VolumesResource { String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); + + String fetchedLogFile = tempDirPath + File.separator + logFileName; + // append log file name with server name so that log files don't overwrite each other + // in cases where the brick log file names are same on multiple servers + String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; + + FileUtil.renameFile(fetchedLogFile, localLogFile); } String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; |
