diff options
Diffstat (limited to 'src')
24 files changed, 592 insertions, 81 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index 0051d427..f98509f4 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -113,13 +113,13 @@ public class GlusterDataModelManager { servers.add(server); } - public void initializeModel(String securityToken) { + public void initializeModel(String securityToken, String knownServer) { model = new GlusterDataModel("Gluster Data Model"); setSecurityToken(securityToken); Cluster cluster = new Cluster("Home", model); - initializeGlusterServers(cluster); + initializeGlusterServers(cluster, knownServer); initializeVolumes(cluster); initializeAutoDiscoveredServers(cluster); @@ -228,8 +228,8 @@ public class GlusterDataModelManager { volume5.addDisk("server5:sdb"); } - private void initializeGlusterServers(Cluster cluster) { - cluster.setServers(new GlusterServersClient(securityToken).getServers()); + private void initializeGlusterServers(Cluster cluster, String knownServer) { + cluster.setServers(new GlusterServersClient(securityToken).getServers(knownServer)); } private void initializeAutoDiscoveredServers(Cluster cluster) { diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java index d4809daf..98b8878c 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java @@ -44,8 +44,10 @@ public class GlusterServersClient extends AbstractClient { return RESOURCE_NAME; } - public List<GlusterServer> getServers() { - GlusterServerListResponse response = (GlusterServerListResponse) fetchResource(GlusterServerListResponse.class); + public List<GlusterServer> getServers(String knownServer) { + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(RESTConstants.QUERY_PARAM_KNOWN_SERVER, knownServer); + GlusterServerListResponse response = (GlusterServerListResponse) fetchResource(queryParams, GlusterServerListResponse.class); return response.getServers(); } @@ -76,7 +78,7 @@ public class GlusterServersClient extends AbstractClient { if (usersClient.authenticate("gluster", "gluster").isSuccess()) { GlusterServersClient serverResource = new GlusterServersClient(usersClient.getSecurityToken()); - List<GlusterServer> glusterServers = serverResource.getServers(); + List<GlusterServer> glusterServers = serverResource.getServers("127.0.0.1"); for (GlusterServer server : glusterServers) { System.out.println(server.getName()); } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java index 8a1e1f37..b5e25ce7 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java @@ -25,6 +25,7 @@ package com.gluster.storage.management.core.constants; public class CoreConstants { public static final String NEWLINE = System.getProperty("line.separator"); public static final String FILE_SEPARATOR = System.getProperty("file.separator"); + public static final String USER_HOME = System.getProperty("user.home"); public static final String ENCODING_UTF8 = "UTF-8"; public static final String ALL = "ALL"; public static final String DATE_WITH_TIME_FORMAT = "MM/dd/yyyy HH:mm:ss"; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java index d5c1bad3..c25d186a 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -56,6 +56,7 @@ public class RESTConstants { public static final String QUERY_PARAM_TO_TIMESTAMP = "toTimestamp"; public static final String QUERY_PARAM_DOWNLOAD = "download"; public static final String QUERY_PARAM_SERVER_NAME = "serverName"; + public static final String QUERY_PARAM_KNOWN_SERVER = "knownServer"; // Running tasks resource public static final String RESOURCE_PATH_RUNNING_TASKS = "/cluster/runningtasks"; diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/LRUCache.java index 3c805ac8..f3c9c72d 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/LRUCache.java @@ -18,7 +18,7 @@ * along with this program. If not, see * <http://www.gnu.org/licenses/>. */ -package com.gluster.storage.management.gui.utils; +package com.gluster.storage.management.core.utils; import java.util.LinkedHashMap; import java.util.Map; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java index 6c8b857d..9d6ddc93 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java @@ -28,6 +28,7 @@ import javax.xml.bind.annotation.XmlRootElement; public class ProcessResult { public static final int SUCCESS = 0; + public static final int FAILURE = 1; private int exitValue; private String output; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java index 34cbfb3b..556c12de 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java @@ -37,7 +37,7 @@ public class StringUtil { output.append(element).append(delimiter); } String outputStr = output.toString(); - int endIndex = (list.size() > 1) ? outputStr.length() - (delimiter.length() + 1) : outputStr.length() - 1; + int endIndex = (list.size() > 1) ? outputStr.length() - (delimiter.length() + 1) : outputStr.length() - delimiter.length(); return outputStr.substring(0, endIndex); } diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index 0c6fc60e..7a8c07e0 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -385,7 +385,7 @@ definitionId="org.eclipse.ui.window.preferences" icon="icons/preferences.png" id="com.gluster.storage.management.gui.actions.AddServerAction" - label="&Preferences" + label="&Settings" menubarPath="com.gluster.storage.management.gui.menu.edit/edit" mode="FORCE_TEXT" pulldown="false" diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java index 9b2bb8bc..b0645990 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java @@ -102,8 +102,8 @@ public class CreateVolumePage1 extends WizardPage { createTypeLabel(container); createTypeCombo(container); - createTransportTypeLabel(container); - createTransportTypeValueLabel(container); +// createTransportTypeLabel(container); +// createTransportTypeValueLabel(container); createDisksLabel(container); createDisksCustomizeLink(container); @@ -293,7 +293,7 @@ public class CreateVolumePage1 extends WizardPage { IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); volume.setVolumeType((VOLUME_TYPE)selection.getFirstElement()); - volume.setTransportType(TRANSPORT_TYPE.ETHERNET); + volume.setTransportType(TRANSPORT_TYPE.ETHERNET); // Support only for Ethernet Set<NAS_PROTOCOL> nasProtocols = new HashSet<Volume.NAS_PROTOCOL>(); nasProtocols.add(NAS_PROTOCOL.GLUSTERFS); nasProtocols.add(NAS_PROTOCOL.NFS); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java index c6ffa8d5..7705a631 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java @@ -193,7 +193,7 @@ public class LoginDialog extends Dialog { UsersClient usersClient = new UsersClient(); if (usersClient.authenticate(user, password).isSuccess()) { try { - GlusterDataModelManager.getInstance().initializeModel(usersClient.getSecurityToken()); + GlusterDataModelManager.getInstance().initializeModel(usersClient.getSecurityToken(), "127.0.0.1"); super.okPressed(); } catch (Exception e) { setReturnCode(RETURN_CODE_ERROR); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java index efa169de..d5e568b3 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java @@ -24,6 +24,7 @@ import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.plugin.AbstractUIPlugin; +import com.gluster.storage.management.core.utils.LRUCache; import com.gluster.storage.management.gui.Application; /** diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java index 3c633bf4..b8356ed0 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java @@ -1,5 +1,6 @@ package com.gluster.storage.management.gui.views; +import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; @@ -29,14 +30,18 @@ import org.eclipse.ui.part.ViewPart; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.core.utils.StringUtil; import com.gluster.storage.management.core.utils.ValidationUtil; import com.gluster.storage.management.gui.IImageKeys; import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; @@ -56,6 +61,7 @@ public class VolumeSummaryView extends ViewPart { private ControlDecoration errDecoration; private Composite parent; private static final String COURIER_FONT = "Courier"; + private Cluster cluster = GlusterDataModelManager.getInstance().getModel().getCluster(); @Override public void createPartControl(Composite parent) { @@ -139,42 +145,36 @@ public class VolumeSummaryView extends ViewPart { private void createVolumeMountingInfoSection() { String glusterFs = "Gluster:"; String nfs = "NFS:"; - String glusterFsSyntax = "mount -t glusterfs <SERVER-NAME>:/<VOLUME-NAME> <MOUNT-POINT>"; - String nfsSyntax = "mount -t nfs <SERVER-NAME>:/nfs/<VOLUME-NAME> <MOUNT-POINT>"; - String info = "<SERVER-NAME> - Any server name in the storage cloud"; - String volumeName = volume.getName().trim(); - String serverName = volume.getDisks().get(0).split(":")[0].trim(); // disk if the form of: "server:disk" - - Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 2, false); - - Label lbl = toolkit.createLabel(section, "Syntax"); - final int defaultFontSize = lbl.getFont().getFontData()[0].getHeight(); - final String defaultFontName = lbl.getFont().getFontData()[0].name; + String onlineServers = getOnlineServers(10); // Limited to 10 servers + String firstOnlineServer = onlineServers.split(",")[0].trim(); + String glusterFsMountInfo = "mount -t glusterfs " + firstOnlineServer + ":/" + volume.getName() + " <mount-point>"; + String nfsMountInfo = "mount -t nfs " + firstOnlineServer + ":/" + volume.getName() + " <mount-point>"; + String info = "Server can be any server name in the storage cloud eg. <" + onlineServers + ">"; //TODO: if more than 10 servers... - setLabelStyle(lbl, defaultFontName, defaultFontSize, SWT.BOLD); - toolkit.createLabel(section, ""); + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 2, false); - setLabelStyle(toolkit.createLabel(section, glusterFs), defaultFontName, defaultFontSize, SWT.NORMAL); - setLabelStyle(toolkit.createLabel(section, glusterFsSyntax, SWT.NONE), COURIER_FONT, 10, SWT.NONE); + toolkit.createLabel(section, glusterFs, SWT.NORMAL); + setLabelStyle(toolkit.createLabel(section, glusterFsMountInfo, SWT.NONE), COURIER_FONT, 10, SWT.NONE); // TODO: Check required if nfs is optional - setLabelStyle(toolkit.createLabel(section, nfs), defaultFontName, defaultFontSize, SWT.NORMAL); - setLabelStyle(toolkit.createLabel(section, nfsSyntax, SWT.NONE), COURIER_FONT, 10, SWT.NONE); - - toolkit.createLabel(section, ""); - setLabelStyle(toolkit.createLabel(section, info), defaultFontName, (defaultFontSize - 1), SWT.NONE); + toolkit.createLabel(section, nfs, SWT.NORMAL); + setLabelStyle(toolkit.createLabel(section, nfsMountInfo, SWT.NONE), COURIER_FONT, 10, SWT.NONE); - setLabelStyle(toolkit.createLabel(section, "Example"), defaultFontName, defaultFontSize, SWT.BOLD); toolkit.createLabel(section, ""); + toolkit.createLabel(section, info, SWT.NONE); + } - setLabelStyle(toolkit.createLabel(section, glusterFs), defaultFontName, defaultFontSize, SWT.NORMAL); - setLabelStyle(toolkit.createLabel(section, "#mount -t glusterfs " + serverName + ":/" + volumeName + " /mnt"), - COURIER_FONT, 10, SWT.NONE); - - // TODO: Check required if nfs is optional - setLabelStyle(toolkit.createLabel(section, nfs), defaultFontName, defaultFontSize, SWT.NORMAL); - setLabelStyle(toolkit.createLabel(section, "#mount -t nfs " + serverName + ":/" + volumeName + " /mnt"), - COURIER_FONT, 10, SWT.NONE); + private String getOnlineServers(int maxServers) { + List<String> OnlineServers = new ArrayList<String>(); + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == SERVER_STATUS.ONLINE) { + OnlineServers.add(server.getName()); + if (OnlineServers.size() >= maxServers) { + break; + } + } + } + return StringUtil.ListToString(OnlineServers, ", ") + ((OnlineServers.size() > maxServers) ? "..." : ""); } /** @@ -196,7 +196,7 @@ public class VolumeSummaryView extends ViewPart { createNumOfDisksField(section); createDiskSpaceField(section); - createTransportTypeField(section); +// createTransportTypeField(section); createNASProtocolField(section); createAccessControlField(section); createStatusField(section); @@ -398,7 +398,7 @@ public class VolumeSummaryView extends ViewPart { private void updateVolumeStatusLabel() { lblStatusValue.setText(volume.getStatusStr()); - lblStatusValue.setImage(volume.getStatus() == Volume.VOLUME_STATUS.ONLINE ? guiHelper + lblStatusValue.setImage((volume.getStatus() == Volume.VOLUME_STATUS.ONLINE) ? guiHelper .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); lblStatusValue.redraw(); } diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/Disk.py b/src/com.gluster.storage.management.server.scripts/src/nodes/Disk.py index d5d8de31..6a4c2998 100644 --- a/src/com.gluster.storage.management.server.scripts/src/nodes/Disk.py +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/Disk.py @@ -99,7 +99,8 @@ class Disk: 'description': str(parent.GetProperty('storage.model')) + " " + str(parent.GetProperty('storage.vendor')), 'size' : str(int(dev.GetProperty('volume.size')) / 1024**2), 'totalsize' : str(int(parent.GetProperty('storage.size')) / 1024**2), - 'drive_type': str(parent.GetProperty('storage.drive_type')) + 'drive_type': str(parent.GetProperty('storage.drive_type')), + 'mount_point': str(dev.GetProperty('volume.mount_point')) }) def _get_device(self, udi): diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerDetails.py b/src/com.gluster.storage.management.server.scripts/src/nodes/get_server_details.py index 440347a4..67148586 100755 --- a/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerDetails.py +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/get_server_details.py @@ -1,3 +1,4 @@ +#!/usr/bin/python # Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com> # This file is part of Gluster Storage Platform. # @@ -188,6 +189,7 @@ def getServerDetails(): continue partitionTag = responseDom.createTag("disk", None) partitionTag.appendChild(responseDom.createTag("name", os.path.basename(disk['device']))) + partitionTag.appendChild(responseDom.createTag("mountPoint", disk['mount_point'])) partitionTag.appendChild(responseDom.createTag("serverName", serverName)) partitionTag.appendChild(responseDom.createTag("description", disk['description'])) total, used, free = getDiskSizeInfo(disk['device']) @@ -204,5 +206,9 @@ def getServerDetails(): serverTag.appendChild(responseDom.createTag("diskSpaceInUse", str(diskSpaceInUse))) return serverTag -def test(): - print getServerDetails().toxml() +def main(): + print getServerDetails().toprettyxml() + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project index 86d34a3b..259b3726 100644 --- a/src/com.gluster.storage.management.server/.project +++ b/src/com.gluster.storage.management.server/.project @@ -37,6 +37,5 @@ <nature>org.eclipse.wst.common.project.facet.core.nature</nature> <nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.wst.jsdt.core.jsNature</nature> - <nature>org.python.pydev.pythonNature</nature> </natures> </projectDescription> diff --git a/src/com.gluster.storage.management.server/.pydevproject b/src/com.gluster.storage.management.server/.pydevproject deleted file mode 100644 index a9cca037..00000000 --- a/src/com.gluster.storage.management.server/.pydevproject +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<?eclipse-pydev version="1.0"?> - -<pydev_project> -<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> -<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property> -</pydev_project> diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt new file mode 100644 index 00000000..3eddd42f --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt @@ -0,0 +1,87 @@ +Copyright (c) 2006 - 2010 Christian Plattner. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+a.) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+b.) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+c.) Neither the name of Christian Plattner nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+This software includes work that was released under the following license:
+
+Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich),
+ Department of Computer Science (http://www.inf.ethz.ch),
+ Christian Plattner. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+a.) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+b.) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+c.) Neither the name of ETH Zurich nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+The Java implementations of the AES, Blowfish and 3DES ciphers have been
+taken (and slightly modified) from the cryptography package released by
+"The Legion Of The Bouncy Castle".
+
+Their license states the following:
+
+Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
+(http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar Binary files differnew file mode 100644 index 00000000..c0a9ac7b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml index 6d7d1406..7c7d42d3 100644 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -64,6 +64,14 @@ <!-- Spring Security --> <filter> + <filter-name>authFailureFilter</filter-name> + <filter-class>com.gluster.storage.management.server.filters.AuthenticationFailureFilter</filter-class> + </filter> + <filter-mapping> + <filter-name>authFailureFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java new file mode 100644 index 00000000..5f828f65 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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.server.filters; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import javax.ws.rs.core.Response; + +/** + * @author root + * + */ +public class AuthenticationFailureFilter implements Filter { + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#destroy() + */ + @Override + public void destroy() { + // TODO Auto-generated method stub + + } + + public class CharResponseWrapper extends HttpServletResponseWrapper { + private CharArrayWriter output; + + public String toString() { + return output.toString(); + } + + public CharResponseWrapper(HttpServletResponse response) { + super(response); + output = new CharArrayWriter(); + } + + public PrintWriter getWriter() { + return new PrintWriter(output); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, + ServletException { + HttpServletRequest request = (HttpServletRequest) req; + if (request.getRequestURI().contains("download")) { + chain.doFilter(req, res); + return; + } + + CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) res); + chain.doFilter(req, wrapper); + + if(wrapper.getStatus() == Response.Status.UNAUTHORIZED.ordinal()) { + PrintWriter out = res.getWriter(); + out.println("<status><code>1</code><message>Authentication Failed!</message></status>"); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + */ + @Override + public void init(FilterConfig arg0) throws ServletException { + // TODO Auto-generated method stub + + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java index 4f2850ee..3092e80d 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType; import org.springframework.stereotype.Component; +import com.gluster.storage.management.core.constants.RESTConstants; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; import com.gluster.storage.management.core.model.Server; @@ -39,21 +40,32 @@ import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.response.GlusterServerListResponse; import com.gluster.storage.management.core.response.GlusterServerResponse; import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.api.core.InjectParam; import com.sun.jersey.spi.resource.Singleton; @Component @Singleton @Path("/cluster/servers") public class GlusterServersResource extends AbstractServersResource { - private GlusterUtil glusterUtil = new GlusterUtil(); + @InjectParam + private GlusterUtil glusterUtil; + public static final String HOSTNAMETAG = "hostname:"; - private List<GlusterServer> getServerDetails() { - List<GlusterServer> glusterServers = glusterUtil.getGlusterServers(); + public void setGlusterUtil(GlusterUtil glusterUtil) { + this.glusterUtil = glusterUtil; + } + + public GlusterUtil getGlusterUtil() { + return glusterUtil; + } + + private List<GlusterServer> getServerDetails(String knownServer) { + List<GlusterServer> glusterServers = glusterUtil.getGlusterServers(knownServer); for (GlusterServer server : glusterServers) { if (server.getStatus() == SERVER_STATUS.ONLINE) { fetchServerDetails(server); - // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); } } return glusterServers; @@ -61,17 +73,17 @@ public class GlusterServersResource extends AbstractServersResource { @GET @Produces(MediaType.TEXT_XML) - public GlusterServerListResponse getGlusterServers() { - return new GlusterServerListResponse(Status.STATUS_SUCCESS, getServerDetails()); + public GlusterServerListResponse getGlusterServers(@QueryParam(RESTConstants.QUERY_PARAM_KNOWN_SERVER) String knownServer) { + return new GlusterServerListResponse(Status.STATUS_SUCCESS, getServerDetails(knownServer)); } @GET @Path("{serverName}") @Produces(MediaType.TEXT_XML) public GlusterServer getGlusterServer(@PathParam("serverName") String serverName) { + // TODO: Implement logic to fetch details of a single gluster server (peer) GlusterServer server = new GlusterServer(serverName); fetchServerDetails(server); - // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); server.setStatus(SERVER_STATUS.ONLINE); return server; } @@ -93,8 +105,8 @@ public class GlusterServersResource extends AbstractServersResource { @POST @Produces(MediaType.TEXT_XML) - public GlusterServerResponse addServer(@FormParam("serverName") String serverName) { - Status status = glusterUtil.addServer(serverName); + public GlusterServerResponse addServer(@FormParam("serverName") String serverName, @FormParam("existingServer") String existingServer) { + Status status = glusterUtil.addServer(serverName, existingServer); if (!status.isSuccess()) { return new GlusterServerResponse(status, null); @@ -110,10 +122,13 @@ public class GlusterServersResource extends AbstractServersResource { public static void main(String[] args) { GlusterServersResource glusterServersResource = new GlusterServersResource(); - System.out.println(glusterServersResource.getServerDetails()); + GlusterUtil glusterUtil = new GlusterUtil(); + glusterUtil.setSshUtil(new SshUtil()); + glusterServersResource.setGlusterUtil(glusterUtil); + System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); // To add a server - GlusterServerResponse response = glusterServersResource.addServer("my-server"); - System.out.println(response.getData().getName()); +// GlusterServerResponse response = glusterServersResource.addServer("my-server"); +// System.out.println(response.getData().getName()); } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java index 51134317..5e9c1945 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java @@ -69,8 +69,9 @@ public class UsersResource { @Path("{user}") @GET @Produces(MediaType.TEXT_XML) - public Status login(@PathParam("user") String user) { + public Status authenticate(@PathParam("user") String user) { // success only if the user passed in query is same as the one passed in security header + // spring security would have already authenticated the user credentials return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? Status.STATUS_SUCCESS : Status.STATUS_FAILURE); } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index 6db6bffc..91f809b8 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -20,11 +20,13 @@ */ package com.gluster.storage.management.server.utils; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.gluster.storage.management.core.constants.CoreConstants; @@ -56,11 +58,22 @@ public class GlusterUtil { private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; - private static final String VOLUME_OPTION_AUTH_ALLOW = "auth.allow:"; + private static final String VOLUME_OPTION_AUTH_ALLOW_PFX = "auth.allow:"; private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; private static final String VOLUME_TYPE_REPLICATE = "Replicate"; private static final ProcessUtil processUtil = new ProcessUtil(); + + @Autowired + private SshUtil sshUtil; + + public void setSshUtil(SshUtil sshUtil) { + this.sshUtil = sshUtil; + } + + public SshUtil getSshUtil() { + return sshUtil; + } /** * Extract value of given token from given line. It is assumed that the token, if present, will be of the following @@ -79,8 +92,8 @@ public class GlusterUtil { return null; } - public List<GlusterServer> getGlusterServers() { - String output = getPeerStatus(); + public List<GlusterServer> getGlusterServers(String knownServer) { + String output = getPeerStatus(knownServer); if (output == null) { return null; } @@ -127,8 +140,8 @@ public class GlusterUtil { return glusterServers; } - public List<String> getGlusterServerNames() { - String output = getPeerStatus(); + public List<String> getGlusterServerNames(String knownServer) { + String output = getPeerStatus(knownServer); if (output == null) { return null; } @@ -143,9 +156,15 @@ public class GlusterUtil { return glusterServerNames; } - private String getPeerStatus() { + /** + * @param knownServer + * A known server on which the gluster command will be executed to fetch peer status + * @return Outout of the "gluster peer status" command + */ + private String getPeerStatus(String knownServer) { String output; - ProcessResult result = processUtil.executeCommand("gluster", "peer", "status"); + //ProcessResult result = processUtil.executeCommand("gluster", "peer", "status"); + ProcessResult result = getSshUtil().executeRemote(knownServer, "gluster peer status"); if (!result.isSuccess()) { output = null; } @@ -153,8 +172,8 @@ public class GlusterUtil { return output; } - public Status addServer(String serverName) { - return new Status(processUtil.executeCommand("gluster", "peer", "probe", serverName)); + public Status addServer(String serverName, String existingServer) { + return new Status(sshUtil.executeRemote(existingServer, "gluster peer probe " + serverName)); } public Status startVolume(String volumeName) { @@ -460,10 +479,10 @@ public class GlusterUtil { public String getLogFileNameForBrickDir(String brickDir) { String logFileName = brickDir; - if (logFileName.startsWith(CoreConstants.FILE_SEPARATOR)) { - logFileName = logFileName.replaceFirst(CoreConstants.FILE_SEPARATOR, ""); + if (logFileName.startsWith(File.separator)) { + logFileName = logFileName.replaceFirst(File.separator, ""); } - logFileName = logFileName.replaceAll(CoreConstants.FILE_SEPARATOR, "-") + ".log"; + logFileName = logFileName.replaceAll(File.separator, "-") + ".log"; return logFileName; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java new file mode 100644 index 00000000..5816533b --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java @@ -0,0 +1,271 @@ +/******************************************************************************* + * 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.server.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Date; + +import org.springframework.stereotype.Component; + +import ch.ethz.ssh2.ChannelCondition; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.utils.LRUCache; +import com.gluster.storage.management.core.utils.ProcessResult; + +/** + * + */ +@Component +public class SshUtil { + private LRUCache<String, Connection> sshConnCache = new LRUCache<String, Connection>(10); + private static final File PEM_FILE = new File(CoreConstants.USER_HOME + "/" + ".ssh/id_rsa"); + // TODO: Make user name configurable + private static final String USER_NAME = "root"; + // TODO: Make default password configurable + private static final String DEFAULT_PASSWORD = "syst3m"; + + private Connection getConnectionWithPassword(String serverName) { + Connection conn = createConnection(serverName); + authenticateWithPassword(conn); + return conn; + } + + private synchronized Connection getConnection(String serverName) { + Connection conn = sshConnCache.get(serverName); + if (conn != null) { + return conn; + } + + conn = createConnection(serverName); + authenticateWithPublicKey(conn); + sshConnCache.put(serverName, conn); + return conn; + } + + private void authenticateWithPublicKey(Connection conn) { + try { + if (!supportsPublicKeyAuthentication(conn)) { + throw new GlusterRuntimeException("Public key authentication not supported on [" + conn.getHostname() + + "]"); + } + + // TODO: Introduce password for the PEM file (third argument) so that it is more secure + if (!conn.authenticateWithPublicKey(USER_NAME, PEM_FILE, null)) { + throw new GlusterRuntimeException("SSH Authentication (public key) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Exception during SSH authentication (public key) for server [" + + conn.getHostname() + "]", e); + } + } + + private void authenticateWithPassword(Connection conn) { + try { + if (!supportsPasswordAuthentication(conn)) { + throw new GlusterRuntimeException("Password authentication not supported on [" + conn.getHostname() + + "]"); + } + + // TODO: Introduce password for the PEM file (third argument) so that it is more secure + if (!conn.authenticateWithPassword(USER_NAME, DEFAULT_PASSWORD)) { + throw new GlusterRuntimeException("SSH Authentication (password) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Exception during SSH authentication (password) for server [" + + conn.getHostname() + "]", e); + } + } + + private boolean supportsPasswordAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("password"); + } + + private boolean supportsPublicKeyAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("publickey"); + } + + private Connection createConnection(String serverName) { + Connection conn; + conn = new Connection(serverName); + try { + conn.connect(); + } catch (IOException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Exception while creating SSH connection with server [" + serverName + + "]", e); + } + return conn; + } + + private boolean wasTerminated(int condition) { + return ((condition | ChannelCondition.EXIT_SIGNAL) == condition); + } + + private boolean hasErrors(int condition, Session session) { + return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session))); + } + + private boolean exitedWithError(Session session) { + return session.getExitStatus() != ProcessResult.SUCCESS; + } + + private boolean exitedGracefully(int condition) { + return (condition | ChannelCondition.EXIT_STATUS) == condition; + } + + private boolean hasErrorStream(int condition) { + return (condition | ChannelCondition.STDERR_DATA) == condition; + } + + private ProcessResult executeCommand(Connection sshConnection, String command) { + try { + Session session = sshConnection.openSession(); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStdout()))); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStderr()))); + session.execCommand(command); + ProcessResult result = getResultOfExecution(session, stdoutReader, stderrReader); + session.close(); + return result; + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + private ProcessResult getResultOfExecution(Session session, BufferedReader stdoutReader, BufferedReader stderrReader) { + // Wait for program to come out either + // a) gracefully with an exit status, OR + // b) because of a termination signal + int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, 5000); + StringBuilder output = new StringBuilder(); + + try { + readFromStream(stdoutReader, output); + if (hasErrors(condition, session)) { + readFromStream(stderrReader, output); + } + + return prepareProcessResult(session, condition, output); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + private ProcessResult prepareProcessResult(Session session, int condition, StringBuilder output) { + ProcessResult result = null; + if (wasTerminated(condition)) { + result = new ProcessResult(ProcessResult.FAILURE, output.toString()); + } else { + if (hasErrors(condition, session)) { + Integer exitStatus = session.getExitStatus(); + int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus); + result = new ProcessResult(statusCode, output.toString()); + } else { + result = new ProcessResult(ProcessResult.SUCCESS, output.toString()); + } + } + return result; + } + + private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException, + UnsupportedEncodingException { + while (true) { + String line = streamReader.readLine(); + if (line == null) { + break; + } + output.append(line + CoreConstants.NEWLINE); + } + } + + /** + * Executes given command on remote machine using password authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemoteWithPassword(String serverName, String command) { + return executeCommand(getConnectionWithPassword(serverName), command); + } + + /** + * Executes given command on remote machine using public key authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemote(String serverName, String command) { + return executeCommand(getConnection(serverName), command); + } + + /** + * Checks if public key of management gateway is configured on given server + * + * @param serverName + * @return true if public key is configured, else false + */ + public boolean isPublicKeySetup(String serverName) { + try { + getConnection(serverName); + return true; + } catch (Exception e) { + return false; + } + } + + public void cleanup() { + for (Connection conn : sshConnCache.values()) { + conn.close(); + } + } + + public static void main(String[] args) { + SshUtil sshUtil = new SshUtil(); + System.out.println(new Date()); + ProcessResult result = sshUtil.executeRemote("dev.gluster.com", "/bin/pwd"); + System.out.println(result.getOutput()); + result = sshUtil.executeRemote("dev.gluster.com", "/bin/pwd1"); + System.out.println(new Date() + " - " + result.getExitValue() + " - " + result.getOutput()); + result = sshUtil.executeRemote("dev.gluster.com", "/bin/ls -lrt"); + System.out.println(new Date() + " - " + result.getExitValue() + " - " + result.getOutput()); + + sshUtil.cleanup(); + } +} |
