diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-06-10 20:13:55 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-06-10 20:13:55 +0530 |
| commit | 84b76fc94d2591af6507da452b7cc1c4d240a1b8 (patch) | |
| tree | 1255477004a3ddf2ecea5c4f23508ce39eada600 /src | |
| parent | 26cdbc3ba32f8963b0ff533b2f19873c6ef11191 (diff) | |
Introduced select all/none links in discovered servers and gluster servers views, removed redundant classes and performed some refactoring.
Diffstat (limited to 'src')
40 files changed, 1782 insertions, 378 deletions
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.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index 56f08793..af065b7d 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -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/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/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..f737ea9d 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(); 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/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/AbstractBricksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractBricksPage.java index 412a1ef2..baa6cbe9 100644 --- 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/pages/AbstractBricksPage.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; 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 105fa824..55283c7a 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,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; 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..a8a98bbd 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,69 @@ 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(); + private Hyperlink linkAll, linkNone; + protected Composite parent; - 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 +113,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 +126,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 +148,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 +169,14 @@ 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; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; } @@ -178,20 +191,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..a6bc6f94 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,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; 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..1df74481 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,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; 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..3621afe1 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,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; 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.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()
|
