diff options
Diffstat (limited to 'src')
367 files changed, 22578 insertions, 0 deletions
diff --git a/src/com.gluster.storage.management.client/.classpath b/src/com.gluster.storage.management.client/.classpath new file mode 100644 index 00000000..b8f71a37 --- /dev/null +++ b/src/com.gluster.storage.management.client/.classpath @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry exported="true" kind="lib" path="lib/jersey-1.5/jersey-client-1.5.jar" sourcepath="/data/downloads/sun/jersey/sources/jersey-client-1.5-sources.jar"/> + <classpathentry exported="true" kind="lib" path="lib/jersey-1.5/jersey-core-1.5.jar" sourcepath="/data/downloads/sun/jersey/sources/jersey-core-1.5-sources.jar"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry combineaccessrules="false" kind="src" path="/com.gluster.storage.management.core"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/src/com.gluster.storage.management.client/.project b/src/com.gluster.storage.management.client/.project new file mode 100644 index 00000000..647c8a91 --- /dev/null +++ b/src/com.gluster.storage.management.client/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.client</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f8b5cc38 --- /dev/null +++ b/src/com.gluster.storage.management.client/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 29 15:47:13 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.client/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.client/META-INF/MANIFEST.MF new file mode 100644 index 00000000..43ae7c3e --- /dev/null +++ b/src/com.gluster.storage.management.client/META-INF/MANIFEST.MF @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gluster Storage Platform Client +Bundle-SymbolicName: com.gluster.storage.management.client +Bundle-Version: 1.0.0 +Bundle-Vendor: GLUSTER +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: com.gluster.storage.management.core;bundle-version="1.0.0", + org.eclipse.equinox.common;bundle-version="3.6.0" +Export-Package: com.gluster.storage.management.client, + com.gluster.storage.management.client.constants +Bundle-ClassPath: ., + lib/jersey-1.5/jersey-client-1.5.jar, + lib/jersey-1.5/jersey-core-1.5.jar diff --git a/src/com.gluster.storage.management.client/build.properties b/src/com.gluster.storage.management.client/build.properties new file mode 100644 index 00000000..271ce382 --- /dev/null +++ b/src/com.gluster.storage.management.client/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = .,\ + META-INF/,\ + lib/jersey-1.5/jersey-client-1.5.jar,\ + lib/jersey-1.5/jersey-core-1.5.jar +src.includes = lib/jersey-1.4/jersey-client-1.4.jar,\ + lib/jersey-1.4/jersey-core-1.4.jar diff --git a/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar Binary files differnew file mode 100644 index 00000000..62f790fa --- /dev/null +++ b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-client-1.5.jar diff --git a/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar Binary files differnew file mode 100644 index 00000000..92b38466 --- /dev/null +++ b/src/com.gluster.storage.management.client/lib/jersey-1.5/jersey-core-1.5.jar diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java new file mode 100644 index 00000000..12fbd354 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java @@ -0,0 +1,159 @@ +package com.gluster.storage.management.client;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import com.gluster.storage.management.client.utils.ClientUtil;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.representation.Form;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+public abstract class AbstractClient {
+ private static final String HTTP_HEADER_AUTH = "Authorization";
+ protected static final MultivaluedMap<String, String> NO_PARAMS = new MultivaluedMapImpl();
+
+ protected WebResource resource;
+ private String securityToken;
+ private String authHeader;
+
+ public AbstractClient() {
+ URI baseURI = new ClientUtil().getServerBaseURI();
+ resource = Client.create(new DefaultClientConfig()).resource(baseURI).path(getResourceName());
+ }
+
+ public AbstractClient(String securityToken) {
+ this();
+ setSecurityToken(securityToken);
+ }
+
+ /**
+ * Fetches the given resource by dispatching a GET request
+ *
+ * @param res
+ * Resource to be fetched
+ * @param queryParams
+ * Query parameters to be sent for the GET request
+ * @param responseClass
+ * Expected class of the response
+ * @return Object of responseClass received as a result of the GET request
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private Object fetchResource(WebResource res, MultivaluedMap<String, String> queryParams, Class responseClass) {
+ return res.queryParams(queryParams).header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.TEXT_XML)
+ .get(responseClass);
+ }
+
+ /**
+ * Fetches the default resource (the one returned by {@link AbstractClient#getResourceName()}) by dispatching a GET
+ * request on the resource
+ *
+ * @param queryParams
+ * Query parameters to be sent for the GET request
+ * @param responseClass
+ * Expected class of the response
+ * @return Object of responseClass received as a result of the GET request
+ */
+ @SuppressWarnings("rawtypes")
+ protected Object fetchResource(MultivaluedMap<String, String> queryParams, Class responseClass) {
+ return fetchResource(resource, queryParams, responseClass);
+ }
+
+ /**
+ * Fetches the default resource (the one returned by {@link AbstractClient#getResourceName()}) by dispatching a GET
+ * request on the resource
+ *
+ * @param responseClass
+ * Expected class of the response
+ * @return Object of responseClass received as a result of the GET request
+ */
+ @SuppressWarnings("rawtypes")
+ protected Object fetchResource(Class responseClass) {
+ Object response = fetchResource(resource, NO_PARAMS, responseClass);
+ return response;
+ }
+
+ /**
+ * Fetches the resource whose name is arrived at by appending the "subResourceName" parameter to the default
+ * resource (the one returned by {@link AbstractClient#getResourceName()})
+ *
+ * @param subResourceName
+ * Name of the sub-resource
+ * @param responseClass
+ * Expected class of the response
+ * @return Object of responseClass received as a result of the GET request on the sub-resource
+ */
+ @SuppressWarnings("rawtypes")
+ protected Object fetchSubResource(String subResourceName, Class responseClass) {
+ return fetchResource(resource.path(subResourceName), NO_PARAMS, responseClass);
+ }
+
+ /**
+ * Submits given Form using POST method to the resource and returns the object received as response
+ * @param responseClass Class of the object expected as response
+ * @param form Form to be submitted
+ * @return Object of given class received as response
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Object postRequest(Class responseClass, Form form) {
+ return resource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).header("Authorization", authHeader)
+ .accept(MediaType.TEXT_XML).post(responseClass, form);
+ }
+
+ /**
+ * Submits given Form using POST method to the given sub-resource and returns the object received as response
+ * @param subResourceName Name of the sub-resource to which the request is to be posted
+ * @param responseClass Class of the object expected as response
+ * @param form Form to be submitted
+ * @return Object of given class received as response
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected Object postRequest(String subResourceName, Class responseClass, Form form) {
+ return resource.path(subResourceName).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
+ .header("Authorization", authHeader).accept(MediaType.TEXT_XML).post(responseClass, form);
+ }
+
+ /**
+ * Submits given Form using PUT method to the given sub-resource and returns the object received as response
+ * @param subResourceName Name of the sub-resource to which the request is to be posted
+ * @param responseClass Class of the object expected as response
+ * @param form Form to be submitted
+ * @return Object of given class received as response
+ */
+ protected Object putRequest(String subResourceName, Class responseClass, Form form) {
+ return resource.path(subResourceName).type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
+ .header("Authorization", authHeader).accept(MediaType.TEXT_XML).put(responseClass, form);
+ }
+
+ /**
+ * Submits given object to the resource and returns the object received as response
+ * @param responseClass Class of the object expected as response
+ * @param requestObject the Object to be submitted
+ * @return Object of given class received as response
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Object postObject(Class responseClass, Object requestObject) {
+ return resource.type(MediaType.TEXT_XML).header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.TEXT_XML)
+ .post(responseClass, requestObject);
+ }
+
+ public abstract String getResourceName();
+
+ /**
+ * @return the securityToken
+ */
+ protected String getSecurityToken() {
+ return securityToken;
+ }
+
+ /**
+ * @param securityToken the securityToken to set
+ */
+ protected void setSecurityToken(String securityToken) {
+ this.securityToken = securityToken;
+ authHeader = "Basic " + securityToken;
+ }
+}
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java new file mode 100644 index 00000000..0cc18037 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import java.util.List; + +import javax.ws.rs.core.MultivaluedMap; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerListResponse; +import com.gluster.storage.management.core.model.StringListResponse; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class DiscoveredServersClient extends AbstractClient { + private static final String RESOURCE_NAME = "discoveredservers"; + + public DiscoveredServersClient(String serverName, String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + private Object getDiscoveredServers(Boolean getDetails, Class responseClass) { + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.putSingle("details", getDetails.toString()); + + return ((Response) fetchResource(queryParams, responseClass)).getData(); + } + + public List<String> getDiscoveredServerNames() { + return (List<String>) getDiscoveredServers(Boolean.FALSE, StringListResponse.class); + } + + public List<Server> getDiscoveredServerDetails() { + return (List<Server>) getDiscoveredServers(Boolean.TRUE, ServerListResponse.class); + } + + @SuppressWarnings("unchecked") + public Server getServer(String serverName) { + GenericResponse<Server> response = (GenericResponse<Server>) fetchSubResource(serverName, GenericResponse.class); + return response.getData(); + } + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + DiscoveredServersClient serverResource = new DiscoveredServersClient("localhost", + usersClient.getSecurityToken()); + List<String> discoveredServerNames = serverResource.getDiscoveredServerNames(); + System.out.println(discoveredServerNames); + List<Server> discoveredServers = serverResource.getDiscoveredServerDetails(); + System.out.println(discoveredServers); + + // Server serverDetails = ServerResource.getServer("localhost"); + // System.out.println(serverDetails.getName()); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java new file mode 100644 index 00000000..de0112db --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -0,0 +1,344 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.LogMessage; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; + +public class GlusterDataModelManager { + // private Server discoveredServer1, discoveredServer2, discoveredServer3, discoveredServer4, discoveredServer5; + private GlusterServer server1, server2, server3, server4, server5; + private Volume volume1, volume2, volume3, volume4, volume5; + private Disk s1da, s1db, s2da, s2db, s2dc, s2dd, s3da, s4da, s5da, s5db; + private static List<LogMessage> logMessages = new ArrayList<LogMessage>(); + private static GlusterDataModelManager instance = new GlusterDataModelManager(); + private GlusterDataModel model; + private String securityToken; + private String serverName; + private List<ClusterListener> listeners = new ArrayList<ClusterListener>(); + + private GlusterDataModelManager() { + } + + public String getSecurityToken() { + return securityToken; + } + + public void setSecurityToken(String securityToken) { + this.securityToken = securityToken; + } + + public GlusterDataModel getModel() { + return model; + } + + public static GlusterDataModelManager getInstance() { + return instance; + } + + // Renamed preferredInterfaceName to interfaceName + private GlusterServer addGlusterServer(List<GlusterServer> servers, Entity parent, String name, + SERVER_STATUS status, String interfaceName, int numOfCPUs, double cpuUsage, double totalMemory, + double memoryInUse) { + GlusterServer glusterServer = new GlusterServer(name, parent, status, numOfCPUs, cpuUsage, totalMemory, + memoryInUse); + NetworkInterface networkInterface = addNetworkInterface(glusterServer, interfaceName); // Renamed preferredInterfaceName to interfaceName + // glusterServer.setPreferredNetworkInterface(networkInterface); + + servers.add(glusterServer); + return glusterServer; + } + + private NetworkInterface addNetworkInterface(Server server, String interfaceName) { + NetworkInterface networkInterface = new NetworkInterface(interfaceName, server, "192.168.1." + + Math.round(Math.random() * 255), "255.255.255.0", "192.168.1.1"); + server.setNetworkInterfaces(Arrays.asList(new NetworkInterface[] { networkInterface })); + return networkInterface; + } + + private void addDiscoveredServer(List<Server> servers, Entity parent, String name, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, double totalDiskSpace, double diskSpaceInUse) { + Server server = new Server(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + server.addDisk(new Disk(server, "sda", totalDiskSpace, diskSpaceInUse, DISK_STATUS.READY)); + addNetworkInterface(server, "eth0"); + + servers.add(server); + } + + public void initializeModel(String securityToken) { + setSecurityToken(securityToken); + + // Create the dummy data model for demo + model = new GlusterDataModel("Clusters"); + Cluster cluster = new Cluster("Home", model); + + initializeGlusterServers(cluster); + initializeVolumes(cluster); + initializeAutoDiscoveredServers(cluster); + initializeDisks(); + addDisksToVolumes(); + addVolumeOptions(); + + createDummyLogMessages(); + + initializeRunningTasks(cluster); + + model.addCluster(cluster); + } + + private void addVolumeOptions() { + for (Volume vol : new Volume[] { volume1, volume2, volume3, volume4, volume5 }) { + for (int i = 1; i <= 5; i++) { + String key = vol.getName() + "key" + i; + String value = vol.getName() + "value" + i; + vol.setOption(key, value); + } + } + } + + public Volume addVolume(List<Volume> volumes, String name, Cluster cluster, VOLUME_TYPE volumeType, + TRANSPORT_TYPE transportType, VOLUME_STATUS status) { + Volume volume = new Volume(name, cluster, volumeType, transportType, status); + volumes.add(volume); + + return volume; + } + + private void initializeVolumes(Cluster cluster) { + List<Volume> volumes = new ArrayList<Volume>(); + + volume1 = addVolume(volumes, "Volume1", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume2 = addVolume(volumes, "Volume2", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume3 = addVolume(volumes, "Volume3", cluster, VOLUME_TYPE.DISTRIBUTED_MIRROR, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.OFFLINE); + volume3.setReplicaCount(2); + + volume4 = addVolume(volumes, "Volume4", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume5 = addVolume(volumes, "Volume5", cluster, VOLUME_TYPE.DISTRIBUTED_STRIPE, TRANSPORT_TYPE.INFINIBAND, + VOLUME_STATUS.OFFLINE); + volume5.setStripeCount(3); + + cluster.setVolumes(volumes); + } + + private void initializeDisks() { + s1da = new Disk(server1, "sda", 100d, 80d, DISK_STATUS.READY); + s1db = new Disk(server1, "sdb", 100d, 67.83, DISK_STATUS.READY); + + s2da = new Disk(server2, "sda", 200d, 157.12, DISK_STATUS.READY); + s2db = new Disk(server2, "sdb", 200d, 182.27, DISK_STATUS.READY); + s2dc = new Disk(server2, "sdc", 200d, -1d, DISK_STATUS.UNINITIALIZED); + s2dd = new Disk(server2, "sdd", 200d, 124.89, DISK_STATUS.READY); + + s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE); // disk name unavailable since server is offline + + s4da = new Disk(server4, "sda", 100d, 85.39, DISK_STATUS.READY); + + s5da = new Disk(server5, "sda", 100d, 92.83, DISK_STATUS.READY); + s5db = new Disk(server5, "sdb", 200d, 185.69, DISK_STATUS.READY); + } + + private void addDisksToServers() { + server1.addDisk(s1da); + server1.addDisk(s1db); + + server2.addDisk(s2da); + server2.addDisk(s2db); + server2.addDisk(s2dc); + server2.addDisk(s2dd); + + // server3.addDisk(s3da); + + server4.addDisk(s4da); + + server5.addDisk(s5da); + server5.addDisk(s5db); + } + + private void addDisksToVolumes() { + volume1.addDisk(s1da); + + volume2.addDisk(s2da); + volume2.addDisk(s1db); + volume2.addDisk(s3da); + volume2.addDisk(s4da); + + volume3.addDisk(s2db); + volume3.addDisk(s4da); + volume3.addDisk(s5da); + + volume4.addDisk(s1da); + volume4.addDisk(s3da); + volume4.addDisk(s4da); + volume4.addDisk(s5db); + + volume5.addDisk(s2da); + volume5.addDisk(s5db); + } + + private void initializeGlusterServers(Cluster cluster) { + cluster.setServers(new GlusterServersClient(securityToken).getServers()); + } + + private void initializeAutoDiscoveredServers(Cluster cluster) { + cluster.setAutoDiscoveredServers(new DiscoveredServersClient(serverName, securityToken) + .getDiscoveredServerDetails()); + } + + private void addMessages(List<LogMessage> messages, Disk disk, String severity, int count) { + for (int i = 1; i <= count; i++) { + String message = severity + "message" + i; + messages.add(new LogMessage(new Date(), disk, severity, message)); + } + } + + private void addMessagesForDisk(List<LogMessage> logMessages, Disk disk) { + addMessages(logMessages, disk, "SEVERE", 5); + addMessages(logMessages, disk, "WARNING", 5); + addMessages(logMessages, disk, "DEBUG", 5); + addMessages(logMessages, disk, "INFO", 5); + } + + public void initializeRunningTasks(Cluster cluster) { + cluster.setRunningTasks(new RunningTaskClient(securityToken).getRunningTasks()); + } + + public List<LogMessage> createDummyLogMessages() { + addMessagesForDisk(logMessages, s1da); + addMessagesForDisk(logMessages, s1db); + addMessagesForDisk(logMessages, s2da); + addMessagesForDisk(logMessages, s2db); + addMessagesForDisk(logMessages, s2dc); + addMessagesForDisk(logMessages, s2dd); + addMessagesForDisk(logMessages, s4da); + addMessagesForDisk(logMessages, s5da); + addMessagesForDisk(logMessages, s5db); + return logMessages; + } + + public static List<LogMessage> getDummyLogMessages() { + return logMessages; + } + + public List<Disk> getReadyDisksOfVolume(Volume volume) { + List<Disk> disks = new ArrayList<Disk>(); + for (Disk disk : volume.getDisks()) { + if (disk.isReady()) { + disks.add(disk); + } + } + return disks; + } + + public List<Disk> getReadyDisksOfAllVolumes() { + List<Disk> disks = new ArrayList<Disk>(); + for (Volume volume : ((Cluster) model.getChildren().get(0)).getVolumes()) { + disks.addAll(getReadyDisksOfVolume(volume)); + } + return disks; + } + + public List<Disk> getReadyDisksOfAllServers() { + return getReadyDisksOfAllServersExcluding(new ArrayList<Disk>()); + } + + public List<Disk> getReadyDisksOfAllServersExcluding(List<Disk> excludeDisks) { + List<Disk> disks = new ArrayList<Disk>(); + + for (Server server : ((Cluster) model.getChildren().get(0)).getServers()) { + for (Disk disk : server.getDisks()) { + if (disk.isReady() && !excludeDisks.contains(disk)) { + disks.add(disk); + } + } + } + return disks; + } + + public void addClusterListener(ClusterListener listener) { + listeners.add(listener); + } + + public void removeClusterListener(ClusterListener listener) { + listeners.remove(listener); + } + + public void addGlusterServer(GlusterServer server) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.addServer(server); + + for(ClusterListener listener : listeners) { + listener.serverAdded(server); + } + } + + public void removeDiscoveredServer(Server server) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.removeDiscoveredServer(server); + + for(ClusterListener listener : listeners) { + listener.discoveredServerRemoved(server); + } + } + + public void updateVolumeStatus(Volume volume, VOLUME_STATUS newStatus) { + volume.setStatus(newStatus); + for(ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_STATUS_CHANGED, newStatus)); + } + } + + public void addVolume(Volume volume) { + Cluster cluster = (Cluster)model.getChildren().get(0); + cluster.addVolume(volume); + + for(ClusterListener listener : listeners) { + listener.volumeCreated(volume); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java new file mode 100644 index 00000000..25fe3bbc --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import java.util.List; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServerListResponse; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.sun.jersey.api.representation.Form; + +public class GlusterServersClient extends AbstractClient { + private static final String RESOURCE_NAME = "/cluster/servers"; + + public GlusterServersClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + public List<GlusterServer> getServers() { + GlusterServerListResponse response = (GlusterServerListResponse) fetchResource(GlusterServerListResponse.class); + return response.getServers(); + } + + @SuppressWarnings("unchecked") + public Server getServer(String serverName) { + GenericResponse<Server> response = (GenericResponse<Server>) fetchSubResource(serverName, GenericResponse.class); + return response.getData(); + } + + public String getServerXML(String serverName) { + return ((String) fetchSubResource(serverName, String.class)); + } + + public GlusterServerResponse addServer(Server discoveredServer) { + Form form = new Form(); + form.add("serverName", discoveredServer.getName()); + return (GlusterServerResponse)postRequest(GlusterServerResponse.class, form); + } + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + + GlusterServersClient serverResource = new GlusterServersClient(usersClient.getSecurityToken()); + List<GlusterServer> glusterServers = serverResource.getServers(); + for (GlusterServer server : glusterServers) { + System.out.println(server.getName()); + } + + // Add server + Server srv = new Server(); + srv.setName("server3"); + GlusterServerResponse response = serverResource.addServer(srv); + System.out.println(response.getGlusterServer().getName()); + System.out.println(response.getStatus().isSuccess()); + + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java new file mode 100644 index 00000000..05e1e094 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RESTClientTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.DefaultClientConfig; + +public class RESTClientTest { + public static void main(String args[]) { + WebResource service = Client.create(new DefaultClientConfig()).resource(getBaseURI()); + String name = service.path("services").path("name").accept(MediaType.TEXT_PLAIN).get(String.class); + System.out.println(name); + name = service.path("services").path("name/xml").accept(MediaType.TEXT_XML).get(String.class); + System.out.println(name); + } + + private static URI getBaseURI() { + return UriBuilder.fromUri("http://localhost:8080/glustermc").build(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java new file mode 100644 index 00000000..9309cdc8 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/RunningTaskClient.java @@ -0,0 +1,31 @@ +package com.gluster.storage.management.client; + +import java.util.List; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.RunningTaskListResponse; + +public class RunningTaskClient extends AbstractClient { + private static final String RESOURCE_NAME = RESTConstants.RESOURCE_PATH_RUNNING_TASKS; + + public RunningTaskClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + @SuppressWarnings("rawtypes") + private Object fetchRunningTasks(Class responseClass) { + return fetchResource( responseClass ); + } + + public List<RunningTask> getRunningTasks() { + RunningTaskListResponse response = (RunningTaskListResponse) fetchRunningTasks( RunningTaskListResponse.class ); + return response.getRunningTasks(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java new file mode 100644 index 00000000..8d7a52fc --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import com.gluster.storage.management.core.model.Status; +import com.sun.jersey.api.representation.Form; +import com.sun.jersey.core.util.Base64; + +public class UsersClient extends AbstractClient { + private static final String RESOURCE_NAME = "users"; + private static final String FORM_PARAM_OLD_PASSWORD = "oldpassword"; + private static final String FORM_PARAM_NEW_PASSWORD = "newpassword"; + + private String generateSecurityToken(String user, String password) { + return new String(Base64.encode(user + ":" + password)); + } + + public UsersClient() { + super(); + } + + public boolean authenticate(String user, String password) { + setSecurityToken(generateSecurityToken(user, password)); + try { + Status authStatus = (Status) fetchSubResource(user, Status.class); + if (authStatus.isSuccess()) { + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + + // If we reach here, it means authentication failed. Clear security token and return false. + setSecurityToken(null); + return false; + } + + public boolean changePassword(String user, String oldPassword, String newPassword) { + setSecurityToken(generateSecurityToken(user, oldPassword)); + + Form form = new Form(); + form.add(FORM_PARAM_OLD_PASSWORD, oldPassword); + form.add(FORM_PARAM_NEW_PASSWORD, newPassword); + Status status = (Status) putRequest(user, Status.class, form); + + return status.isSuccess(); + } + + public static void main(String[] args) { + UsersClient authClient = new UsersClient(); + + // authenticate user + System.out.println(authClient.authenticate("gluster", "gluster")); + + // change password to gluster1 + System.out.println(authClient.changePassword("gluster", "gluster", "gluster1")); + + // change it back to gluster + System.out.println(authClient.changePassword("gluster", "gluster1", "gluster")); + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.client.AbstractClient#getResourceName() + */ + @Override + public String getResourceName() { + return RESOURCE_NAME; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.client.AbstractClient#getSecurityToken() + */ + @Override + public String getSecurityToken() { + return super.getSecurityToken(); + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java new file mode 100644 index 00000000..03e83a31 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java @@ -0,0 +1,90 @@ +/** + * VolumesClient.java + * + * Copyright (c) 2011 Gluster, Inc. <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.client; + +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.sun.jersey.api.representation.Form; + +public class VolumesClient extends AbstractClient { + + public VolumesClient(String securityToken) { + super(securityToken); + } + + @Override + public String getResourceName() { + return RESTConstants.RESOURCE_PATH_VOLUMES; + } + + @SuppressWarnings("unchecked") + public Status createVolume(Volume volume) { + GenericResponse<String> createVolumeResponse = (GenericResponse<String>) postObject(GenericResponse.class, volume); + + if (!createVolumeResponse.getStatus().isSuccess()) { + return (Status) createVolumeResponse.getStatus(); + } + return (Status) createVolumeResponse.getStatus(); + } + + private Status performOperation(String volumeName, String operation) { + Form form = new Form(); + form.add(RESTConstants.FORM_PARAM_OPERATION, operation); + + return (Status)putRequest(volumeName, Status.class, form); + } + + public Status startVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_START); + } + + public Status stopVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_STOP); + } + + + public static void main(String[] args) { + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate("gluster", "gluster")) { + VolumesClient VC = new VolumesClient(usersClient.getSecurityToken()); + List<Disk> disks = new ArrayList<Disk>(); + Disk diskElement = new Disk(); + diskElement.setName("sda1"); + diskElement.setStatus(DISK_STATUS.READY); + disks.add(diskElement); + diskElement.setName("sda2"); + diskElement.setStatus(DISK_STATUS.READY); + disks.add(diskElement); + + Volume vol = new Volume("vol1", null, Volume.VOLUME_TYPE.PLAIN_DISTRIBUTE, Volume.TRANSPORT_TYPE.ETHERNET, + Volume.VOLUME_STATUS.ONLINE); + // vol.setDisks(disks); + System.out.println(VC.createVolume(vol)); + } + } +} diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java new file mode 100644 index 00000000..853cfe96 --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java @@ -0,0 +1,32 @@ +/** + * ClientConstants.java + * + * Copyright (c) 2011 Gluster, Inc. <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.client.constants; + +/** + * + */ +public class ClientConstants { + public static final String SYS_PROP_SERVER_URL = "gluster.server.url"; + public static final String DEFAULT_SERVER_URL = "http://localhost:8080/glustermc/linux.gtk.x86_64"; + public static final String WEB_CONTEXT = "glustermc"; + public static final String WEB_RESOURCE_BASE_PATH = "resources"; +} + diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java new file mode 100644 index 00000000..23d2f9fd --- /dev/null +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java @@ -0,0 +1,20 @@ +package com.gluster.storage.management.client.utils; + +import java.net.URI; + +import javax.ws.rs.core.UriBuilder; + +import com.gluster.storage.management.client.constants.ClientConstants; + +public class ClientUtil { + + public URI getServerBaseURI() { + return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.WEB_RESOURCE_BASE_PATH).build(); + } + + private String getBaseURL() { + // remove the platform path (e.g. /linux.gtk.x86_64) from the URL + return System.getProperty(ClientConstants.SYS_PROP_SERVER_URL, ClientConstants.DEFAULT_SERVER_URL) + .replaceAll("glustermc\\/.*", "glustermc\\/"); + } +} diff --git a/src/com.gluster.storage.management.core/.classpath b/src/com.gluster.storage.management.core/.classpath new file mode 100644 index 00000000..b41cbcdb --- /dev/null +++ b/src/com.gluster.storage.management.core/.classpath @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="junit"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/src/com.gluster.storage.management.core/.project b/src/com.gluster.storage.management.core/.project new file mode 100644 index 00000000..6c8fbb5c --- /dev/null +++ b/src/com.gluster.storage.management.core/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.core</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f22cedf1 --- /dev/null +++ b/src/com.gluster.storage.management.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 22 11:18:01 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF new file mode 100644 index 00000000..b5a2a830 --- /dev/null +++ b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gluster Storage Platform Core +Bundle-SymbolicName: com.gluster.storage.management.core +Bundle-Version: 1.0.0 +Bundle-Vendor: GLUSTER +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Export-Package: com.gluster.storage.management.core.constants, + com.gluster.storage.management.core.exceptions, + com.gluster.storage.management.core.model, + com.gluster.storage.management.core.utils +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0" diff --git a/src/com.gluster.storage.management.core/build.properties b/src/com.gluster.storage.management.core/build.properties new file mode 100644 index 00000000..34d2e4d2 --- /dev/null +++ b/src/com.gluster.storage.management.core/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java b/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java new file mode 100644 index 00000000..8902ae8f --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/com/gluster/storage/management/core/utils/TestFileUtil.java @@ -0,0 +1,84 @@ +/** + * TestFileUtil.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStreamWriter; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestFileUtil { + private String testFileName; + private String fileContent; + private FileUtil fileUtil; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + testFileName = "testFileUtil.txt"; + fileContent = "Testing FileUtil class."; + fileUtil = new FileUtil(); + + BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(testFileName)); + OutputStreamWriter writer = new OutputStreamWriter(outStream); + writer.write(fileContent); + writer.close(); + outStream.close(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + File testFile = new File(testFileName); + testFile.delete(); + } + + /** + * Test method for {@link com.gluster.storage.management.core.utils.FileUtil#readFileAsString(java.io.File)}. + */ + @Test + public final void testReadFileAsString() { + String readContent = fileUtil.readFileAsString(new File(testFileName)); + assertTrue("File contents expected [" + fileContent + "], actual [" + readContent + "]", + readContent.equals(fileContent)); + } + + /** + * Test method for {@link com.gluster.storage.management.core.utils.FileUtil#loadResource(java.lang.String)}. + */ + @Test + public final void testLoadResource() { + InputStream inputStream = fileUtil.loadResource("test/test.txt"); + Assert.assertNotNull(inputStream); + } +} diff --git a/src/com.gluster.storage.management.core/junit/core.junit.launch b/src/com.gluster.storage.management.core/junit/core.junit.launch new file mode 100644 index 00000000..0bf6dc30 --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/core.junit.launch @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/com.gluster.storage.management.core"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=com.gluster.storage.management.core"/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.gluster.storage.management.core"/> +</launchConfiguration> diff --git a/src/com.gluster.storage.management.core/junit/test/test.txt b/src/com.gluster.storage.management.core/junit/test/test.txt new file mode 100644 index 00000000..267ce144 --- /dev/null +++ b/src/com.gluster.storage.management.core/junit/test/test.txt @@ -0,0 +1 @@ +Test Resource
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java new file mode 100644 index 00000000..177334bd --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.constants; + + +/** + * + */ +public class CoreConstants { + public static final String NEWLINE = System.getProperty("line.separator"); + public static final String FILE_SEPARATOR = System.getProperty("file.separator"); + public static final String ENCODING_UTF8 = "UTF-8"; +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java new file mode 100644 index 00000000..fb40be8a --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -0,0 +1,37 @@ +/** + * RESTConstants.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.constants; + +/** + * All constants related to the Gluster REST server and client + */ +public class RESTConstants { + // Volumes Resource + public static final String RESOURCE_PATH_VOLUMES = "/cluster/volumes"; + public static final String FORM_PARAM_OPERATION = "operation"; + public static final String FORM_PARAM_VALUE_START = "start"; + public static final String FORM_PARAM_VALUE_STOP = "stop"; + public static final String PATH_PARAM_VOLUME_NAME = "volumeName"; + public static final String SUBRESOURCE_DEFAULT_OPTIONS = "defaultoptions"; + + // Running tasks resource + public static final String RESOURCE_PATH_RUNNING_TASKS = "/cluster/runningtasks"; +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java new file mode 100644 index 00000000..e7e604fc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterRuntimeException.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.exceptions; + +public class GlusterRuntimeException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public GlusterRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public GlusterRuntimeException(String message) { + super(message); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java new file mode 100644 index 00000000..be552bdc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/AbstractResponse.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model;
+
+public abstract class AbstractResponse implements Response {
+ private Status status;
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java new file mode 100644 index 00000000..65d5ebea --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="cluster") +public class Cluster extends Entity { + List<GlusterServer> servers = new ArrayList<GlusterServer>(); + List<Server> discoveredServers = new ArrayList<Server>(); + List<Volume> volumes = new ArrayList<Volume>(); + List<RunningTask> runningTasks = new ArrayList<RunningTask>(); + + public Cluster() { + } + + public List<GlusterServer> getServers() { + return servers; + } + + public void addServer(GlusterServer server) { + servers.add(server); + } + + public void removeServer(GlusterServer server) { + servers.remove(server); + } + + public void addDiscoveredServer(Server server) { + discoveredServers.add(server); + } + + public void removeDiscoveredServer(Server server) { + discoveredServers.remove(server); + } + + public void setServers(List<GlusterServer> servers) { + this.servers = servers; + children.add(new EntityGroup<GlusterServer>("Servers", GlusterServer.class, this, servers)); + } + + public List<Server> getAutoDiscoveredServers() { + return discoveredServers; + } + + public void setAutoDiscoveredServers(List<Server> autoDiscoveredServers) { + this.discoveredServers = autoDiscoveredServers; + children.add(new EntityGroup<Server>("Discovered Servers", Server.class, this, autoDiscoveredServers)); + } + + public List<Volume> getVolumes() { + return volumes; + } + + public void setVolumes(List<Volume> volumes) { + this.volumes = volumes; + children.add(new EntityGroup<Volume>("Volumes", Volume.class, this, volumes)); + } + + public void addVolume(Volume volume) { + this.volumes.add(volume); + } + + public Cluster(String name, Entity parent) { + super(name, parent); + } + + public Cluster(String name, Entity parent, List<GlusterServer> servers, List<Volume> volumes) { + super(name, parent); + setServers(servers); + setVolumes(volumes); + } + + public List<RunningTask> getRunningTasks() { + return runningTasks; + } + + public void setRunningTasks(List<RunningTask> runningTasks) { + this.runningTasks = runningTasks; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java new file mode 100644 index 00000000..ce2752a4 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +/** + * Interface for a cluster listener. Every registered listener will be notified + * on various events happening on the cluster. + */ +public interface ClusterListener { + public void discoveredServerAdded(Server server); + + public void discoveredServerRemoved(Server server); + + public void serverAdded(GlusterServer server); + + public void serverRemoved(GlusterServer server); + + public void serverChanged(GlusterServer server, Event event); + + public void volumeAdded(Volume volume); + + public void volumeRemoved(Volume volume); + + public void volumeChanged(Volume volume, Event event); + + public void volumeCreated(Volume volume); +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java new file mode 100644 index 00000000..ccf8fecf --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ConnectionDetails.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +public class ConnectionDetails { + private String userId, password; + + public ConnectionDetails() { + + } + + public ConnectionDetails(String userId, String password) { + this.userId = userId; + this.password = password; + } + + public String getUserId() { + return userId; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java new file mode 100644 index 00000000..1a39a014 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +/** + * Default listener - doesn't do anything. Sub-class and override the method for + * the event you want to handle. + */ +public class DefaultClusterListener implements ClusterListener { + + @Override + public void serverAdded(GlusterServer server) { + clusterChanged(); + } + + @Override + public void serverRemoved(GlusterServer server) { + clusterChanged(); + } + + @Override + public void serverChanged(GlusterServer server, Event event) { + clusterChanged(); + } + + @Override + public void volumeAdded(Volume volume) { + clusterChanged(); + } + + @Override + public void volumeRemoved(Volume volume) { + clusterChanged(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + clusterChanged(); + } + + @Override + public void discoveredServerAdded(Server server) { + clusterChanged(); + } + + @Override + public void discoveredServerRemoved(Server server) { + clusterChanged(); + } + + @Override + public void volumeCreated(Volume volume) { + clusterChanged(); + } + + /** + * This method is called by every other event method. Thus, if a view/listener is interested in performing the same + * task on any change happening in the cluster data model, it can simply override this method and implement the + * logic. e.g. A view may simply refresh its tree/table viewer whenever the cluster data model changes. + */ + public void clusterChanged() { + + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java new file mode 100644 index 00000000..9924d596 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Disk.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name="Disk") +public class Disk extends Entity { + public enum DISK_STATUS { + READY, UNINITIALIZED, INITIALIZING, OFFLINE + }; + + private String[] DISK_STATUS_STR = { "Ready", "Uninitialized", "Initializing", "Offline" }; + + private String serverName; + private Double space; + private Double spaceInUse; + private DISK_STATUS status; + + public Disk() { + + } + + public Double getSpace() { + return space; + } + + public void setSpace(Double space) { + this.space = space; + } + + public boolean isUninitialized() { + return getStatus() == DISK_STATUS.UNINITIALIZED; + } + + public boolean isOffline() { + return getStatus() == DISK_STATUS.OFFLINE; + } + + public boolean isReady() { + return getStatus() == DISK_STATUS.READY; + } + + public DISK_STATUS getStatus() { + return status; + } + + public String getStatusStr() { + return DISK_STATUS_STR[getStatus().ordinal()]; + } + + public void setStatus(DISK_STATUS status) { + this.status = status; + } + + public Double getSpaceInUse() { + return spaceInUse; + } + + public void setSpaceInUse(Double spaceInUse) { + this.spaceInUse = spaceInUse; + } + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public Disk(Server server, String name, Double space, Double spaceInUse, DISK_STATUS status) { + super(name, server); + setServerName(server != null ? server.getName() : ""); + setSpace(space); + setSpaceInUse(spaceInUse); + setStatus(status); + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getServerName() + getName() + getStatusStr(), filterString, caseSensitive); + } + + public String getQualifiedName() { + return getServerName() + ":" + getName(); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java new file mode 100644 index 00000000..e721d052 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Entity.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import org.eclipse.core.runtime.PlatformObject; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement +public class Entity extends PlatformObject implements Filterable { + private static final long serialVersionUID = 1L; + + protected String name; + protected List<Entity> children = new ArrayList<Entity>(); + private Entity parent; + + public Entity() { + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @XmlTransient + public Entity getParent() { + return parent; + } + + public void setParent(Entity parent) { + this.parent = parent; + } + + public List<? extends Entity> getChildren() { + return children; + } + + public void setChildren(List<Entity> children) { + this.children = children; + } + + public Entity(String name, Entity parent) { + this.name = name; + this.parent = parent; + } + + public Entity(String name, Entity parent, List<Entity> children) { + this.name = name; + this.parent = parent; + this.children = children; + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java new file mode 100644 index 00000000..0fc0f507 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/EntityGroup.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.List; + +public class EntityGroup<T> extends Entity { + private Class<? extends Entity> type; + + public EntityGroup(String name, Class<? extends Entity> type, Cluster cluster) { + this(name, type, cluster, null); + } + + public EntityGroup(String name, Class<? extends Entity> type, Cluster cluster, List<T> entities) { + super(name, cluster, (List<Entity>)entities); + this.type = type; + } + + public List<? extends Entity> getEntities() { + return children; + } + + public void setEntities(List<T> entities) { + children = (List<Entity>)entities; + } + + public Class<? extends Entity> getEntityType() { + return type; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java new file mode 100644 index 00000000..65501a2b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +public class Event { + public enum EVENT_TYPE { + DISK_ADDED, + DISK_REMOVED, + NETWORK_INTERFACE_ADDED, + NETWORK_INTERFACE_REMOVED, + VOLUME_STATUS_CHANGED + } + + private EVENT_TYPE eventType; + private Object eventData; + + public Event(EVENT_TYPE eventType, Object eventData) { + this.eventType = eventType; + this.eventData = eventData; + } + + public EVENT_TYPE getEventType() { + return eventType; + } + + public void setEventType(EVENT_TYPE eventType) { + this.eventType = eventType; + } + + public Object getEventData() { + return eventData; + } + + public void setEventData(Object eventData) { + this.eventData = eventData; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java new file mode 100644 index 00000000..9a2ed405 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Filterable.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +/** + * By default, the {@link EntityViewerFilter} filters the objects by parsing the + * output of {@link Object#toString()} with the filter string. Classes that need + * specific filtering logic can implement this interface. The default logic will + * then be overridden by the method {@link Filterable#filter(String)}. + */ +public interface Filterable { + /** + * @param filterString + * String to be used for filtering + * @param caseSensitive + * Flag indicating whether the filtering should be case sensitive + * @return true if the object can be selected using the filter string, else + * false + */ + public boolean filter(String filterString, boolean caseSensitive); +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java new file mode 100644 index 00000000..efeed34b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GenericResponse.java @@ -0,0 +1,56 @@ +/** + * GenericServerResponse.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class GenericResponse<T> extends AbstractResponse { + private T data; + private Status status; + + @Override + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public GenericResponse(Status status, T data) { + setStatus(status); + this.data = data; + } + + public GenericResponse() { + } + + @Override + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java new file mode 100644 index 00000000..612cae31 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDataModel.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +public class GlusterDataModel extends Entity { + public GlusterDataModel(String name, List<Cluster> clusters) { + super(name, null); + children.addAll(clusters); + } + + public GlusterDataModel(String name) { + this(name, new ArrayList<Cluster>()); + } + + public void setClusters(List<Cluster> clusters) { + children.clear(); + children.addAll(clusters); + } + + public void addCluster(Cluster cluster) { + children.add(cluster); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java new file mode 100644 index 00000000..11d31553 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterDummyModel.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; + +public class GlusterDummyModel { + // private Server discoveredServer1, discoveredServer2, discoveredServer3, discoveredServer4, discoveredServer5; + private GlusterServer server1, server2, server3, server4, server5; + private Volume volume1, volume2, volume3, volume4, volume5; + private Disk s1da, s1db, s2da, s2db, s2dc, s2dd, s3da, s4da, s5da, s5db; + private static List<LogMessage> logMessages = new ArrayList<LogMessage>(); + private static GlusterDummyModel instance = new GlusterDummyModel(); + private GlusterDataModel model; + + private GlusterDummyModel() { + model = initializeModel(); + } + + public GlusterDataModel getModel() { + return model; + } + + public static GlusterDummyModel getInstance() { + return instance; + } + + // Renamed preferredInterfaceName to interfaceName + private GlusterServer addGlusterServer(List<GlusterServer> servers, Entity parent, String name, + SERVER_STATUS status, String interfaceName, int numOfCPUs, double cpuUsage, double totalMemory, + double memoryInUse) { + GlusterServer glusterServer = new GlusterServer(name, parent, status, numOfCPUs, cpuUsage, totalMemory, + memoryInUse); + NetworkInterface networkInterface = addNetworkInterface(glusterServer, interfaceName); // Renamed preferredInterfaceName to interfaceName + // glusterServer.setPreferredNetworkInterface(networkInterface); + + servers.add(glusterServer); + return glusterServer; + } + + private NetworkInterface addNetworkInterface(Server server, String interfaceName) { + NetworkInterface networkInterface = new NetworkInterface(interfaceName, server, "192.168.1." + + Math.round(Math.random() * 255), "255.255.255.0", "192.168.1.1"); + server.setNetworkInterfaces(Arrays.asList(new NetworkInterface[] { networkInterface })); + return networkInterface; + } + + private void addDiscoveredServer(List<Server> servers, Entity parent, String name, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, double totalDiskSpace, double diskSpaceInUse) { + Server server = new Server(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + server.addDisk(new Disk(server, "sda", totalDiskSpace, diskSpaceInUse, DISK_STATUS.READY)); + addNetworkInterface(server, "eth0"); + + servers.add(server); + } + + private GlusterDataModel initializeModel() { + // Create the dummy data model for demo + GlusterDataModel model = new GlusterDataModel("Clusters"); + Cluster cluster = new Cluster("Home", model); + + initializeGlusterServers(cluster); + initializeVolumes(cluster); + initializeAutoDiscoveredServers(cluster); + initializeDisks(); + addDisksToServers(); + addDisksToVolumes(); + addVolumeOptions(); + + createDummyLogMessages(); + + model.addCluster(cluster); + return model; + } + + private void addVolumeOptions() { + for (Volume vol : new Volume[] { volume1, volume2, volume3, volume4, volume5 }) { + for (int i = 1; i <= 5; i++) { + String key = vol.getName() + "key" + i; + String value = vol.getName() + "value" + i; + vol.setOption(key, value); + } + } + } + + private Volume addVolume(List<Volume> volumes, String name, Cluster cluster, VOLUME_TYPE volumeType, + TRANSPORT_TYPE transportType, VOLUME_STATUS status) { + Volume volume = new Volume(name, cluster, volumeType, transportType, status); + volumes.add(volume); + + return volume; + } + + private void initializeVolumes(Cluster cluster) { + List<Volume> volumes = new ArrayList<Volume>(); + + volume1 = addVolume(volumes, "Volume1", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume2 = addVolume(volumes, "Volume2", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume3 = addVolume(volumes, "Volume3", cluster, VOLUME_TYPE.DISTRIBUTED_MIRROR, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.OFFLINE); + volume3.setReplicaCount(2); + + volume4 = addVolume(volumes, "Volume4", cluster, VOLUME_TYPE.PLAIN_DISTRIBUTE, TRANSPORT_TYPE.ETHERNET, + VOLUME_STATUS.ONLINE); + + volume5 = addVolume(volumes, "Volume5", cluster, VOLUME_TYPE.DISTRIBUTED_STRIPE, TRANSPORT_TYPE.INFINIBAND, + VOLUME_STATUS.OFFLINE); + volume5.setStripeCount(3); + + cluster.setVolumes(volumes); + } + + private void initializeDisks() { + s1da = new Disk(server1, "sda", 100d, 80d, DISK_STATUS.READY); + s1db = new Disk(server1, "sdb", 100d, 67.83, DISK_STATUS.READY); + + s2da = new Disk(server2, "sda", 200d, 157.12, DISK_STATUS.READY); + s2db = new Disk(server2, "sdb", 200d, 182.27, DISK_STATUS.READY); + s2dc = new Disk(server2, "sdc", 200d, -1d, DISK_STATUS.UNINITIALIZED); + s2dd = new Disk(server2, "sdd", 200d, 124.89, DISK_STATUS.READY); + + s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE); // disk name unavailable since server is offline + + s4da = new Disk(server4, "sda", 100d, 85.39, DISK_STATUS.READY); + + s5da = new Disk(server5, "sda", 100d, 92.83, DISK_STATUS.READY); + s5db = new Disk(server5, "sdb", 200d, 185.69, DISK_STATUS.READY); + } + + private void addDisksToServers() { + server1.addDisk(s1da); + server1.addDisk(s1db); + + server2.addDisk(s2da); + server2.addDisk(s2db); + server2.addDisk(s2dc); + server2.addDisk(s2dd); + + // server3.addDisk(s3da); + + server4.addDisk(s4da); + + server5.addDisk(s5da); + server5.addDisk(s5db); + } + + private void addDisksToVolumes() { + volume1.addDisk(s1da); + + volume2.addDisk(s2da); + volume2.addDisk(s1db); + volume2.addDisk(s3da); + volume2.addDisk(s4da); + + volume3.addDisk(s2db); + volume3.addDisk(s4da); + volume3.addDisk(s5da); + + volume4.addDisk(s1da); + volume4.addDisk(s3da); + volume4.addDisk(s4da); + volume4.addDisk(s5db); + + volume5.addDisk(s2da); + volume5.addDisk(s5db); + } + + private void initializeGlusterServers(Cluster cluster) { + List<GlusterServer> servers = new ArrayList<GlusterServer>(); + server1 = addGlusterServer(servers, cluster, "Server1", SERVER_STATUS.ONLINE, "eth0", 4, 56.3, 16, 8.4); + server2 = addGlusterServer(servers, cluster, "Server2", SERVER_STATUS.ONLINE, "eth1", 8, 41.92, 32, 18.76); + server3 = addGlusterServer(servers, cluster, "Server3", SERVER_STATUS.OFFLINE, "eth0", -1, -1, -1, -1); + server4 = addGlusterServer(servers, cluster, "Server4", SERVER_STATUS.ONLINE, "eth0", 1, 92.83, 4, 3.18); + server5 = addGlusterServer(servers, cluster, "Server5", SERVER_STATUS.ONLINE, "inf0", 2, 87.24, 8, 7.23); + + cluster.setServers(servers); + } + + private void initializeAutoDiscoveredServers(Cluster cluster) { + List<Server> servers = new ArrayList<Server>(); + addDiscoveredServer(servers, cluster, "ADServer1", 4, 56.3, 16, 8.4, 200, 147.83); + addDiscoveredServer(servers, cluster, "ADServer2", 8, 41.92, 32, 18.76, 800, 464.28); + addDiscoveredServer(servers, cluster, "ADServer3", 2, 84.28, 2, 1.41, 120, 69.93); + addDiscoveredServer(servers, cluster, "ADServer4", 1, 92.83, 4, 3.18, 100, 85.39); + addDiscoveredServer(servers, cluster, "ADServer5", 2, 87.24, 8, 7.23, 250, 238.52); + cluster.setAutoDiscoveredServers(servers); + } + + private void addMessages(List<LogMessage> messages, Disk disk, String severity, int count) { + for (int i = 1; i <= count; i++) { + String message = severity + "message" + i; + messages.add(new LogMessage(new Date(), disk, severity, message)); + } + } + + private void addMessagesForDisk(List<LogMessage> logMessages, Disk disk) { + addMessages(logMessages, disk, "SEVERE", 5); + addMessages(logMessages, disk, "WARNING", 5); + addMessages(logMessages, disk, "DEBUG", 5); + addMessages(logMessages, disk, "INFO", 5); + } + + public List<LogMessage> createDummyLogMessages() { + addMessagesForDisk(logMessages, s1da); + addMessagesForDisk(logMessages, s1db); + addMessagesForDisk(logMessages, s2da); + addMessagesForDisk(logMessages, s2db); + addMessagesForDisk(logMessages, s2dc); + addMessagesForDisk(logMessages, s2dd); + addMessagesForDisk(logMessages, s4da); + addMessagesForDisk(logMessages, s5da); + addMessagesForDisk(logMessages, s5db); + return logMessages; + } + + public static List<LogMessage> getDummyLogMessages() { + return logMessages; + } + + public List<Disk> getReadyDisksOfVolume(Volume volume) { + List<Disk> disks = new ArrayList<Disk>(); + for (Disk disk : volume.getDisks()) { + if (disk.isReady()) { + disks.add(disk); + } + } + return disks; + } + + public List<Disk> getReadyDisksOfAllVolumes() { + List<Disk> disks = new ArrayList<Disk>(); + for (Volume volume : ((Cluster) model.getChildren().get(0)).getVolumes()) { + disks.addAll(getReadyDisksOfVolume(volume)); + } + return disks; + } + + public List<Disk> getReadyDisksOfAllServers() { + return getReadyDisksOfAllServersExcluding(new ArrayList<Disk>()); + } + + public List<Disk> getReadyDisksOfAllServersExcluding(List<Disk> excludeDisks) { + List<Disk> disks = new ArrayList<Disk>(); + + for (Server server : ((Cluster) model.getChildren().get(0)).getServers()) { + for (Disk disk : server.getDisks()) { + if (disk.isReady() && !excludeDisks.contains(disk)) { + disks.add(disk); + } + } + } + return disks; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java new file mode 100644 index 00000000..fd4e58c9 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServer.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name = "glusterServer") +public class GlusterServer extends Server { + public enum SERVER_STATUS { + ONLINE, OFFLINE + }; + + private static final String[] STATUS_STR = new String[] { "Online", "Offline" }; + + private String uuid; + private SERVER_STATUS status; + // private NetworkInterface preferredNetworkInterface; + private Cluster cluster; + + public GlusterServer() { + } + + public GlusterServer(String name) { + super(name); + } + + public GlusterServer(String name, Entity parent, SERVER_STATUS status, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse) { + super(name, parent, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + setStatus(status); + } + + public GlusterServer(String name, Entity parent, SERVER_STATUS status, int numOfCPUs, double cpuUsage, + double totalMemory, double memoryInUse, Cluster cluster) { + this(name, parent, status, numOfCPUs, cpuUsage, totalMemory, memoryInUse); + setCluster(cluster); + } + + public String getStatusStr() { + return STATUS_STR[getStatus().ordinal()]; + } + + public SERVER_STATUS getStatus() { + return status; + } + + public void setStatus(SERVER_STATUS status) { + this.status = status; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + +// public NetworkInterface getPreferredNetworkInterface() { +// return preferredNetworkInterface; +// } +// +// public void setPreferredNetworkInterface(NetworkInterface preferredNetworkInterface) { +// this.preferredNetworkInterface = preferredNetworkInterface; +// preferredNetworkInterface.setPreferred(true); +// } + + + @XmlTransient + public Cluster getCluster() { + return cluster; + } + + public void setCluster(Cluster cluster) { + this.cluster = cluster; + } + + /** + * Filter matches if any of the properties name, status and primary/secondary/third + * DNS contains the filter string + */ + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getStatusStr(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java new file mode 100644 index 00000000..479dcc09 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerListResponse.java @@ -0,0 +1,71 @@ +/** + * GlusterServerListResponse.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * + */ +@XmlRootElement(name = "response") +public class GlusterServerListResponse extends AbstractResponse { + private List<GlusterServer> servers = new ArrayList<GlusterServer>(); + + public GlusterServerListResponse() { + } + + public GlusterServerListResponse(Status status, List<GlusterServer> servers) { + setStatus(status); + setServers(servers); + } + + @XmlElementWrapper(name = "servers") + @XmlElement(name = "server", type=GlusterServer.class) + public List<GlusterServer> getServers() { + return servers; + } + + /** + * @param servers + * the servers to set + */ + public void setServers(List<GlusterServer> servers) { + this.servers = servers; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.core.model.Response#getData() + */ + @Override + @XmlTransient + public List<GlusterServer> getData() { + return getServers(); + } +} + diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java new file mode 100644 index 00000000..e00b8288 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/GlusterServerResponse.java @@ -0,0 +1,32 @@ +package com.gluster.storage.management.core.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +@XmlRootElement(name = "response") +public class GlusterServerResponse extends AbstractResponse { + private GlusterServer glusterServer; + + public GlusterServerResponse() { + } + + public GlusterServerResponse(Status status, GlusterServer server) { + setStatus(status); + setGlusterServer(server); + } + + public GlusterServer getGlusterServer() { + return glusterServer; + } + + public void setGlusterServer(GlusterServer glusterServer) { + this.glusterServer = glusterServer; + } + + @XmlTransient + @Override + public GlusterServer getData() { + return getGlusterServer(); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java new file mode 100644 index 00000000..cc3aa043 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.Date; + +import com.gluster.storage.management.core.utils.StringUtil; + +public class LogMessage implements Filterable { + private Date timestamp; + private Disk disk; + private String severity; + private String message; + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } + + public Disk getDisk() { + return disk; + } + + public void setDisk(Disk disk) { + this.disk = disk; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public LogMessage(Date timestamp, Disk disk, String severity, String message) { + setTimestamp(timestamp); + setDisk(disk); + setSeverity(severity); + setMessage(message); + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getSeverity() + getTimestamp() + getDisk().getServerName() + + getDisk().getQualifiedName() + getMessage(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java new file mode 100644 index 00000000..882dfe09 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/NetworkInterface.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="networkInterface") +public class NetworkInterface extends Entity { + private String ipAddress; + private String netMask; + private String defaultGateway; +// private boolean isPreferred; + + public NetworkInterface() { + + } + +// public boolean isPreferred() { +// return isPreferred; +// } +// +// public void setPreferred(boolean isPreferred) { +// this.isPreferred = isPreferred; +// } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getNetMask() { + return netMask; + } + + public void setNetMask(String netMask) { + this.netMask = netMask; + } + + public String getDefaultGateway() { + return defaultGateway; + } + + public void setDefaultGateway(String defaultGateway) { + this.defaultGateway = defaultGateway; + } + + public NetworkInterface(String name, Entity parent, String ipAddress, String netMask, String defaultGateway) { + super(name, parent); + setIpAddress(ipAddress); + setNetMask(netMask); + setDefaultGateway(defaultGateway); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java new file mode 100644 index 00000000..96ea8497 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Response.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model;
+
+/**
+ * Interface for server response. Any request handled by the Gluster Management
+ * Server will result in a response that must be an instance of a class
+ * implementing this interface.
+ */
+public interface Response<T> { + /**
+ * @return Status of request processing
+ */
+ public Status getStatus();
+
+ /**
+ * @return Data associated with the response. e.g. A "discover servers"
+ * request will return the list of discovered servers.
+ */
+ public T getData();
+}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java new file mode 100644 index 00000000..1a9d63f6 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTask.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class RunningTask { + + protected String id; + protected String type; // FormatDisk, MigrateDisk, VolumeRebalance + protected Object reference; + protected String description; + protected RunningTaskStatus status; // TODO redefine + + public RunningTask() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Object getReference() { + return reference; + } + + public void setReference(Object reference) { + this.reference = reference; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public RunningTaskStatus getStatus() { + return status; + } + + public void setStatus(RunningTaskStatus status) { + this.status = status; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java new file mode 100644 index 00000000..79949c90 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskListResponse.java @@ -0,0 +1,43 @@ +package com.gluster.storage.management.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class RunningTaskListResponse extends AbstractResponse { + private List<RunningTask> runningTasks = new ArrayList<RunningTask>(); + + public RunningTaskListResponse() { + + } + + + public RunningTaskListResponse(Status status, List<RunningTask> runningTasks) { + setStatus(status); + setRunningTasks(runningTasks); + } + + @XmlElementWrapper(name = "runningTasks") + @XmlElement(name = "runningTask", type=RunningTask.class) + public List<RunningTask> getRunningTasks() { + return runningTasks; + } + + /** + * @param runningTasks + * the runningTasks to set + */ + public void setRunningTasks(List<RunningTask> runningTasks) { + this.runningTasks = runningTasks; + } + + @Override + public Object getData() { + return getRunningTasks(); + } + +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java new file mode 100644 index 00000000..7ffeb4b8 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/RunningTaskStatus.java @@ -0,0 +1,41 @@ +package com.gluster.storage.management.core.model; + +public class RunningTaskStatus extends Status { + + private String status; + private boolean isPercentageSupported; + private float percentCompleted; + private String description; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public boolean isPercentageSupported() { + return isPercentageSupported; + } + + public void setPercentageSupported(boolean isPercentageSupported) { + this.isPercentageSupported = isPercentageSupported; + } + + public float getPercentCompleted() { + return percentCompleted; + } + + public void getPercentCompleted(float percentCompleted) { + this.percentCompleted = percentCompleted; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java new file mode 100644 index 00000000..bc0c42bc --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Server.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement(name = "server") +public class Server extends Entity { + private List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>(); + private int numOfCPUs; + private double cpuUsage; + private double totalMemory; + private double memoryInUse; + private double totalDiskSpace = 0; + private double diskSpaceInUse = 0; + private List<Disk> disks = new ArrayList<Disk>(); + + public Server() { + + } + + public Server(String name) { + super(name, null); + } + + public Server(String name, Entity parent, int numOfCPUs, double cpuUsage, double totalMemory, double memoryInUse) { + super(name, parent); + setNumOfCPUs(numOfCPUs); + setCpuUsage(cpuUsage); + setTotalMemory(totalMemory); + setMemoryInUse(memoryInUse); + } + + public int getNumOfCPUs() { + return numOfCPUs; + } + + public void setNumOfCPUs(int numOfCPUs) { + this.numOfCPUs = numOfCPUs; + } + + public double getCpuUsage() { + return cpuUsage; + } + + public void setCpuUsage(double cpuUsage) { + this.cpuUsage = cpuUsage; + } + + public double getTotalMemory() { + return totalMemory; + } + + public void setTotalMemory(double totalMemory) { + this.totalMemory = totalMemory; + } + + public double getMemoryInUse() { + return memoryInUse; + } + + public void setMemoryInUse(double memoryInUse) { + this.memoryInUse = memoryInUse; + } + + public double getTotalDiskSpace() { + return totalDiskSpace; + } + + /** + * Total disk space is automatically calculated, and hence this method should never be called. It is required only + * to make sure that the element "totalDiskSpace" gets added to the XML tag when jersey converts the server object + * to XML for sending to client. + */ + public void setTotalDiskSpace(double totalDiskSpace) { + this.totalDiskSpace = totalDiskSpace; + } + + public double getDiskSpaceInUse() { + return diskSpaceInUse; + } + + @XmlElementWrapper(name = "networkInterfaces") + @XmlElement(name = "networkInterface", type = NetworkInterface.class) + public List<NetworkInterface> getNetworkInterfaces() { + return networkInterfaces; + } + + public void setNetworkInterfaces(List<NetworkInterface> networkInterfaces) { + this.networkInterfaces = networkInterfaces; + } + + @XmlElementWrapper(name = "disks") + @XmlElement(name = "disk", type = Disk.class) + public List<Disk> getDisks() { + return disks; + } + + public void addNetworkInterface(NetworkInterface networkInterface) { + networkInterfaces.add(networkInterface); + } + + public void addDisk(Disk disk) { + if (disks.add(disk)) { + totalDiskSpace += disk.getSpace(); + diskSpaceInUse += disk.getSpaceInUse(); + } + } + + public void addDisks(List<Disk> disks) { + for (Disk disk : disks) { + addDisk(disk); + } + } + + public void removeDisk(Disk disk) { + if (disks.remove(disk)) { + totalDiskSpace -= disk.getSpace(); + diskSpaceInUse -= disk.getSpaceInUse(); + } + } + + public void removeAllDisks() { + disks.clear(); + totalDiskSpace = 0; + diskSpaceInUse = 0; + } + + public void setDisks(List<Disk> disks) { + removeAllDisks(); + addDisks(disks); + } + + public int getNumOfDisks() { + return disks.size(); + } + + public String getIpAddressesAsString() { + String ipAddresses = ""; + for (NetworkInterface networkInterface : getNetworkInterfaces()) { + String ipAddr = networkInterface.getIpAddress(); + ipAddresses += (ipAddresses.isEmpty() ? ipAddr : ", " + ipAddr); + } + return ipAddresses; + } + + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getIpAddressesAsString(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java new file mode 100644 index 00000000..56f33992 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ServerListResponse.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +@XmlRootElement(name = "response") +public class ServerListResponse extends AbstractResponse { + private List<Server> servers = new ArrayList<Server>(); + + public ServerListResponse() { + } + + public ServerListResponse(Status status, List<Server> servers) { + setStatus(status); + setServers(servers); + } + + @XmlElementWrapper(name = "servers") + @XmlElement(name = "server", type=Server.class) + public List<Server> getServers() { + return servers; + } + + /** + * @param servers + * the servers to set + */ + public void setServers(List<Server> servers) { + this.servers = servers; + } + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.core.model.Response#getData() + */ + @Override + @XmlTransient + public List<Server> getData() { + return getServers(); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java new file mode 100644 index 00000000..06d6efe1 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import com.gluster.storage.management.core.utils.ProcessResult; + +@XmlRootElement(name = "status") +public class Status { + public static final int STATUS_CODE_SUCCESS = 0; + public static final int STATUS_CODE_FAILURE = 1; + public static final int STATUS_CODE_RUNNING = 2; + public static final Status STATUS_SUCCESS = new Status(STATUS_CODE_SUCCESS, "Success"); + public static final Status STATUS_FAILURE = new Status(STATUS_CODE_FAILURE, "Failure"); + + // public static final Status + + private Integer code; + private String message; + + public Status() { + } + + public boolean isSuccess() { + return code == STATUS_CODE_SUCCESS; + } + + public Status(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Status(ProcessResult result) { + this.code = result.getExitValue(); + this.message = result.getOutput(); + } + + @XmlElement(name = "code", type = Integer.class) + public Integer getCode() { + return code; + } + + public void setCode(Integer executionStatus) { + this.code = executionStatus; + } + + @XmlElement + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return (isSuccess() ? "Success" : "Failure [" + getCode() + "]") + ": " + getMessage(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java new file mode 100644 index 00000000..3304692d --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/StringListResponse.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "response") +public class StringListResponse extends AbstractResponse { + private List<String> data = new ArrayList<String>(); + + public StringListResponse() { + } + + public StringListResponse(List<String> data) { + this.data = data; + } + + @Override + @XmlElementWrapper(name = "list") + @XmlElement(name = "value", type = String.class) + public List<String> getData() { + return data; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java new file mode 100644 index 00000000..da92ca14 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class User { + private String userId; + private String password; + + public String getUserId() { + return userId; + } + public void setUserId(String userId) { + this.userId = userId; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java new file mode 100644 index 00000000..a7e498c4 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java @@ -0,0 +1,252 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement +public class Volume extends Entity { + public enum VOLUME_STATUS { + ONLINE, OFFLINE + }; + + public enum VOLUME_TYPE { + PLAIN_DISTRIBUTE, DISTRIBUTED_MIRROR, DISTRIBUTED_STRIPE + }; + + public enum TRANSPORT_TYPE { + ETHERNET, INFINIBAND + }; + + public enum NAS_PROTOCOL { + GLUSTERFS, NFS + }; + + private static final String[] VOLUME_TYPE_STR = new String[] { "Plain Distribute", "Distributed Mirror", + "Distributed Stripe" }; + private static final String[] TRANSPORT_TYPE_STR = new String[] { "Ethernet", "Infiniband" }; + private static final String[] STATUS_STR = new String[] { "Online", "Offline" }; + private static final String[] NAS_PROTOCOL_STR = new String[] { "Gluster", "NFS" }; + + private Cluster cluster; + private VOLUME_TYPE volumeType; + private TRANSPORT_TYPE transportType; + private VOLUME_STATUS status; + private int replicaCount; + private int stripeCount; + private Map<String, String> options = new LinkedHashMap<String, String>(); + + private double totalDiskSpace = 0; + private List<Disk> disks = new ArrayList<Disk>(); + + public Volume() { + } + + // GlusterFS export is always enabled + private Set<NAS_PROTOCOL> nasProtocols = new LinkedHashSet<NAS_PROTOCOL>( + Arrays.asList(new NAS_PROTOCOL[] { NAS_PROTOCOL.GLUSTERFS })); + + private String accessControlList = "*"; + + public String getVolumeTypeStr() { + return getVolumeTypeStr(getVolumeType()); + } + + public static String getVolumeTypeStr(VOLUME_TYPE volumeType) { + return VOLUME_TYPE_STR[volumeType.ordinal()]; + } + + public String getTransportTypeStr() { + return TRANSPORT_TYPE_STR[getTransportType().ordinal()]; + } + + public String getStatusStr() { + return STATUS_STR[getStatus().ordinal()]; + } + + public int getNumOfDisks() { + return disks.size(); + } + + public VOLUME_TYPE getVolumeType() { + return volumeType; + } + + public void setVolumeType(VOLUME_TYPE volumeType) { + this.volumeType = volumeType; + } + + public TRANSPORT_TYPE getTransportType() { + return transportType; + } + + public void setTransportType(TRANSPORT_TYPE transportType) { + this.transportType = transportType; + } + + public VOLUME_STATUS getStatus() { + return status; + } + + public int getReplicaCount() { + return replicaCount; + } + + public void setReplicaCount(int replicaCount) { + this.replicaCount = replicaCount; + } + + public int getStripeCount() { + return stripeCount; + } + + public void setStripeCount(int stripeCount) { + this.stripeCount = stripeCount; + } + + public void setStatus(VOLUME_STATUS status) { + this.status = status; + } + + @XmlTransient + public Cluster getCluster() { + return cluster; + } + + public void setCluster(Cluster cluster) { + this.cluster = cluster; + } + + public Set<NAS_PROTOCOL> getNASProtocols() { + return nasProtocols; + } + + public void setNASProtocols(Set<NAS_PROTOCOL> nasProtocols) { + this.nasProtocols = nasProtocols; + } + + public String getNASProtocolsStr() { + String protocolsStr = ""; + for (NAS_PROTOCOL protocol : nasProtocols) { + String protocolStr = NAS_PROTOCOL_STR[protocol.ordinal()]; + protocolsStr += (protocolsStr.isEmpty() ? protocolStr : ", " + protocolStr); + } + return protocolsStr; + } + + public String getAccessControlList() { + return accessControlList; + } + + public void setAccessControlList(String accessControlList) { + this.accessControlList = accessControlList; + } + + public Map<String, String> getOptions() { + return options; + } + + public void setOption(String key, String value) { + options.put(key, value); + } + + public void setOptions(Map<String, String> options) { + this.options = options; + } + + public double getTotalDiskSpace() { + return totalDiskSpace; + } + + public List<Disk> getDisks() { + return disks; + } + + public void addDisk(Disk disk) { + if (disks.add(disk) && disk.getStatus() != DISK_STATUS.OFFLINE) { + totalDiskSpace += disk.getSpace(); + } + } + + public void addDisks(List<Disk> disks) { + for (Disk disk : disks) { + addDisk(disk); + } + } + + public void removeDisk(Disk disk) { + if (disks.remove(disk)) { + totalDiskSpace -= disk.getSpace(); + } + } + + public void removeAllDisks() { + disks.clear(); + totalDiskSpace = 0; + } + + public void setDisks(List<Disk> disks) { + removeAllDisks(); + addDisks(disks); + } + + public void enableNFS() { + nasProtocols.add(NAS_PROTOCOL.NFS); + } + + public void disableNFS() { + nasProtocols.remove(NAS_PROTOCOL.NFS); + } + + public Volume(String name, Entity parent, VOLUME_TYPE volumeType, TRANSPORT_TYPE transportType, VOLUME_STATUS status) { + super(name, parent); + setVolumeType(volumeType); + setTransportType(transportType); + setStatus(status); + } + + public Volume(String name, Entity parent, Cluster cluster, VOLUME_TYPE volumeType, TRANSPORT_TYPE transportType, + VOLUME_STATUS status) { + this(name, parent, volumeType, transportType, status); + + setCluster(cluster); + } + + /** + * Filter matches if any of the properties name, volume type, transport type, status and number of disks contains + * the filter string + */ + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getName() + getVolumeTypeStr() + getTransportTypeStr() + getStatusStr() + + getNumOfDisks(), filterString, caseSensitive); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java new file mode 100644 index 00000000..44e45df5 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptionInfo.java @@ -0,0 +1,66 @@ +/** + * VolumeOptionInfo.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.model; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Class to hold information about a volume option + */ +@XmlRootElement(name = "volumeOption") +public class VolumeOptionInfo { + private String name; + private String description; + private String defaultValue; + + public VolumeOptionInfo() { + } + + public VolumeOptionInfo(String name, String description, String defaultValue) { + setName(name); + setDescription(description); + setDefaultValue(defaultValue); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java new file mode 100644 index 00000000..1b284cb8 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateUtil { + public static final String formatDate(Date inputDate) { + DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + return formatter.format(inputDate); + } + + public static final String formatTime(Date inputDate) { + DateFormat formatter = new SimpleDateFormat("HH:mm:ss z"); + return formatter.format(inputDate); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java new file mode 100644 index 00000000..c650d632 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; + +public class FileUtil { + public String readFileAsString(File file) { + try { + FileInputStream fileInputStream = new FileInputStream(file); + byte[] data = new byte[fileInputStream.available()]; + fileInputStream.read(data); + fileInputStream.close(); + + return new String(data); + } catch (Exception e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Could not read file [" + file + "]", e); + } + } + + public InputStream loadResource(String resourcePath) { + return this.getClass().getClassLoader().getResourceAsStream(resourcePath); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java new file mode 100644 index 00000000..ad5b4c2b --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java @@ -0,0 +1,218 @@ +/** + * GlusterUtil.java + * + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; + +/** + * + */ +public class GlusterUtil { + private static final String HOSTNAME_PFX = "Hostname:"; + private static final String UUID_PFX = "Uuid:"; + private static final String STATE_PFX = "State:"; + private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; + private static final ProcessUtil processUtil = new ProcessUtil(); + + /** + * Extract value of given token from given line. It is assumed that the token, if present, will be of the following + * form: <code>token: value</code> + * + * @param line + * Line to be analyzed + * @param token + * Token whose value is to be extracted + * @return Value of the token, if present in the line + */ + private final String extractToken(String line, String token) { + if (line.contains(token)) { + return line.split(token)[1].trim(); + } + return null; + } + + public List<GlusterServer> getGlusterServers() { + String output = getPeerStatus(); + if (output == null) { + return null; + } + + List<GlusterServer> glusterServers = new ArrayList<GlusterServer>(); + GlusterServer server = null; + boolean foundHost = false; + boolean foundUuid = false; + for (String line : output.split(CoreConstants.NEWLINE)) { + if (foundHost && foundUuid) { + // Host and UUID is found, we should look for state + String state = extractToken(line, STATE_PFX); + if (state != null) { + server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE + : SERVER_STATUS.OFFLINE); + // Completed populating current server. Add it to the list and reset all related variables. + glusterServers.add(server); + + foundHost = false; + foundUuid = false; + server = null; + } + } else if (foundHost) { + // Host is found, look for UUID + String uuid = extractToken(line, UUID_PFX); + if (uuid != null) { + server.setUuid(uuid); + foundUuid = true; + } + } else { + // Look for the next host + if (server == null) { + server = new GlusterServer(); + } + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + server.setName(hostName); + foundHost = true; + } + } + + } + return glusterServers; + } + + public List<String> getGlusterServerNames() { + String output = getPeerStatus(); + if(output == null) { + return null; + } + + List<String> glusterServerNames = new ArrayList<String>(); + for (String line : output.split(CoreConstants.NEWLINE)) { + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + glusterServerNames.add(hostName); + } + } + return glusterServerNames; + } + + private String getPeerStatus() { + String output; + ProcessResult result = processUtil.executeCommand("gluster", "peer", "status"); + if (!result.isSuccess()) { + output = null; + } + output = result.getOutput(); + return output; + } + + public ProcessResult addServer(String serverName) { + return processUtil.executeCommand("gluster", "peer", "probe", serverName); + } + + + public ProcessResult startVolume(String volumeName) { + return processUtil.executeCommand("gluster", "volume", "start", volumeName); + } + + public ProcessResult stopVolume(String volumeName) { + return processUtil.executeCommand("gluster", "--mode=script", "volume", "stop", volumeName); + } + + public ProcessResult createVolume(Volume volume) { + int count=1; // replica or stripe count + String volumeType = null; + VOLUME_TYPE volType = volume.getVolumeType(); + if(volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volumeType = "replica"; + count = 2; + } else if(volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volumeType = "stripe"; + count = 4; + } + + String transportTypeStr = null; + TRANSPORT_TYPE transportType = volume.getTransportType(); + transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + + List<String> command = new ArrayList<String>(); + command.add("gluster"); + command.add("volume"); + command.add("create"); + command.add(volume.getName()); + if(volumeType != null) { + command.add(volumeType); + command.add("" + count); + } + command.add("transport"); + command.add(transportTypeStr); + for(Disk disk : volume.getDisks()) { + command.add(getBrickNotation(volume, disk)); + } + return processUtil.executeCommand(command); + } + + public ProcessResult setOption(List<String> command) { + return processUtil.executeCommand(command); + } + + public ProcessResult setVolumeAccessControl(Volume volume) { + List<String> command = new ArrayList<String>(); + command.add("gluster"); + command.add("volume"); + command.add("set"); + command.add(volume.getName()); + command.add("auth.allow"); + command.add(volume.getAccessControlList()); + return setOption(command); + } + + /** + * @param disk + * @return + */ + private String getBrickNotation(Volume vol, Disk disk) { + // TODO: Figure out an appropriate directory INSIDE the DISK having given NAME (e.g. sda, sdb, etc) + // String dirName = "/export/" + vol.getName() + "/" + disk.getName(); + + // if /export directory is not exist then create the directory + boolean exists = (new File("/export")).exists(); + + if (!exists) { + processUtil.executeCommand("mkdir", "/export"); + } + String dirName = "/export/" + vol.getName() ; + return disk.getServerName() + ":" + dirName; + } + + public static void main(String args[]) { + List<String> names = new GlusterUtil().getGlusterServerNames(); + System.out.println(names); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java new file mode 100644 index 00000000..e0daaf81 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5.java @@ -0,0 +1,504 @@ +/* + * MD5 in Java JDK Beta-2 + * written Santeri Paavolainen, Helsinki Finland 1996 + * (c) Santeri Paavolainen, Helsinki Finland 1996 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * See http://www.cs.hut.fi/~santtu/java/ for more information on this + * class. + * + * This is rather straight re-implementation of the reference implementation + * given in RFC1321 by RSA. + * + * Passes MD5 test suite as defined in RFC1321. + * + * + * This Java class has been derivedfrom the RSA Data Security, Inc. MD5 + * Message-Digest Algorithm and its reference implementation. + * + * + * $Log: MD5.java,v $ + * Revision 1.1 2004/07/12 13:35:20 aubryp + * initial commit + * + * Revision 1.3 2002/03/16 01:46:39 broccol + * Moved the MD5 classes into the md5 package to make 1.4 javac happy + * + * Revision 1.2 1999/11/04 21:38:00 broccol + * Got MD5Crypt calculating the same hash as the OpenBSD md5crypt.c routine. + * + * Revision 1.1 1999/08/05 22:07:03 broccol + * Added support for the MD5 classes. + * + * Revision 1.3 1996/04/15 07:28:09 santtu + * Added GPL statements, and RSA derivate statements. + * + * Revision 1.2 1996/03/04 08:05:48 santtu + * Added offsets to Update method + * + * Revision 1.1 1996/01/07 20:51:59 santtu + * Initial revision + * + */ +package com.gluster.storage.management.core.utils; + +/** + * Contains internal state of the MD5 class + * + * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi> + */ + +class MD5State { + /** + * 128-byte state + */ + int state[]; + + /** + * 64-bit character count (could be true Java long?) + */ + int count[]; + + /** + * 64-byte buffer (512 bits) for storing to-be-hashed characters + */ + byte buffer[]; + + public MD5State() { + buffer = new byte[64]; + count = new int[2]; + state = new int[4]; + + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + count[0] = count[1] = 0; + } + + /** Create this State as a copy of another state */ + public MD5State(MD5State from) { + this (); + + int i; + + for (i = 0; i < buffer.length; i++) + this .buffer[i] = from.buffer[i]; + + for (i = 0; i < state.length; i++) + this .state[i] = from.state[i]; + + for (i = 0; i < count.length; i++) + this .count[i] = from.count[i]; + } +}; + +/** + * Implementation of RSA's MD5 hash generator + * + * @version $Revision: 1.1 $ + * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi> + */ + +public class MD5 { + /** + * MD5 state + */ + MD5State state; + + /** + * If Final() has been called, finals is set to the current finals + * state. Any Update() causes this to be set to null. + */ + MD5State finals; + + /** + * Padding for Final() + */ + static byte padding[] = { (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + /** + * Initialize MD5 internal state (object can be reused just by + * calling Init() after every Final() + */ + public synchronized void Init() { + state = new MD5State(); + finals = null; + } + + /** + * Class constructor + */ + public MD5() { + this .Init(); + } + + /** + * Initialize class, and update hash with ob.toString() + * + * @param ob Object, ob.toString() is used to update hash + * after initialization + */ + public MD5(Object ob) { + this (); + Update(ob.toString()); + } + + public String debugDump() { + return asHex(); + } + + private int rotate_left(int x, int n) { + return (x << n) | (x >>> (32 - n)); + } + + /* I wonder how many loops and hoops you'll have to go through to + get unsigned add for longs in java */ + + private int uadd(int a, int b) { + long aa, bb; + aa = ((long) a) & 0xffffffffL; + bb = ((long) b) & 0xffffffffL; + + aa += bb; + + return (int) (aa & 0xffffffffL); + } + + private int uadd(int a, int b, int c) { + return uadd(uadd(a, b), c); + } + + private int uadd(int a, int b, int c, int d) { + return uadd(uadd(a, b, c), d); + } + + private int FF(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & c) | (~b & d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int GG(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & d) | (c & ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int HH(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (b ^ c ^ d), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int II(int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (c ^ (b | ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int[] Decode(byte buffer[], int len, int shift) { + int out[]; + int i, j; + + out = new int[16]; + + for (i = j = 0; j < len; i++, j += 4) { + out[i] = ((int) (buffer[j + shift] & 0xff)) + | (((int) (buffer[j + 1 + shift] & 0xff)) << 8) + | (((int) (buffer[j + 2 + shift] & 0xff)) << 16) + | (((int) (buffer[j + 3 + shift] & 0xff)) << 24); + } + + return out; + } + + private void Transform(MD5State state, byte buffer[], int shift) { + int a = state.state[0], b = state.state[1], c = state.state[2], d = state.state[3], x[]; + + x = Decode(buffer, 64, shift); + + /* Round 1 */ + a = FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */ + d = FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */ + c = FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */ + b = FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */ + a = FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */ + d = FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */ + c = FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */ + b = FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */ + a = FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */ + d = FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */ + c = FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + b = FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + a = FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + d = FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + c = FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + b = FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */ + d = GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */ + c = GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + b = GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */ + a = GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */ + d = GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ + c = GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + b = GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */ + a = GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */ + d = GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + c = GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */ + b = GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */ + a = GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + d = GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */ + c = GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */ + b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */ + d = HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */ + c = HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + b = HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + a = HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */ + d = HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */ + c = HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */ + b = HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + a = HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + d = HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */ + c = HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */ + b = HH(b, c, d, a, x[6], 23, 0x4881d05); /* 44 */ + a = HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */ + d = HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + b = HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */ + d = II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */ + c = II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + b = II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */ + a = II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + d = II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */ + c = II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + b = II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */ + a = II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */ + d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + c = II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */ + b = II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + a = II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */ + d = II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + c = II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */ + b = II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */ + + state.state[0] += a; + state.state[1] += b; + state.state[2] += c; + state.state[3] += d; + } + + /** + * Updates hash with the bytebuffer given (using at maximum length bytes from + * that buffer) + * + * @param stat Which state is updated + * @param buffer Array of bytes to be hashed + * @param offset Offset to buffer array + * @param length Use at maximum `length' bytes (absolute + * maximum is buffer.length) + */ + public void Update(MD5State stat, byte buffer[], int offset, + int length) { + int index, partlen, i, start; + + finals = null; + + /* Length can be told to be shorter, but not inter */ + if ((length - offset) > buffer.length) + length = buffer.length - offset; + + /* compute number of bytes mod 64 */ + index = (int) (stat.count[0] >>> 3) & 0x3f; + + if ((stat.count[0] += (length << 3)) < (length << 3)) + stat.count[1]++; + + stat.count[1] += length >>> 29; + + partlen = 64 - index; + + if (length >= partlen) { + for (i = 0; i < partlen; i++) + stat.buffer[i + index] = buffer[i + offset]; + + Transform(stat, stat.buffer, 0); + + for (i = partlen; (i + 63) < length; i += 64) + Transform(stat, buffer, i); + + index = 0; + } else + i = 0; + + /* buffer remaining input */ + if (i < length) { + start = i; + for (; i < length; i++) + stat.buffer[index + i - start] = buffer[i + offset]; + } + } + + /* + * Update()s for other datatypes than byte[] also. Update(byte[], int) + * is only the main driver. + */ + + /** + * Plain update, updates this object + */ + + public void Update(byte buffer[], int offset, int length) { + Update(this .state, buffer, offset, length); + } + + public void Update(byte buffer[], int length) { + Update(this .state, buffer, 0, length); + } + + /** + * Updates hash with given array of bytes + * + * @param buffer Array of bytes to use for updating the hash + */ + public void Update(byte buffer[]) { + Update(buffer, 0, buffer.length); + } + + /** + * Updates hash with a single byte + * + * @param b Single byte to update the hash + */ + public void Update(byte b) { + byte buffer[] = new byte[1]; + buffer[0] = b; + + Update(buffer, 1); + } + + /** + * Update buffer with given string. + * + * @param s String to be update to hash (is used as + * s.getBytes()) + */ + public void Update(String s) { + byte chars[]; + + chars = s.getBytes(); + + Update(chars, chars.length); + } + + private byte[] Encode(int input[], int len) { + int i, j; + byte out[]; + + out = new byte[len]; + + for (i = j = 0; j < len; i++, j += 4) { + out[j] = (byte) (input[i] & 0xff); + out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); + out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); + out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); + } + + return out; + } + + /** + * Returns array of bytes (16 bytes) representing hash as of the + * current state of this object. Note: getting a hash does not + * invalidate the hash object, it only creates a copy of the real + * state which is finalized. + * + * @return Array of 16 bytes, the hash of all updated bytes + */ + public synchronized byte[] Final() { + byte bits[]; + int index, padlen; + MD5State fin; + + if (finals == null) { + fin = new MD5State(state); + + bits = Encode(fin.count, 8); + + index = (int) ((fin.count[0] >>> 3) & 0x3f); + padlen = (index < 56) ? (56 - index) : (120 - index); + + Update(fin, padding, 0, padlen); + /**/ + Update(fin, bits, 0, 8); + + /* Update() sets finalds to null */ + finals = fin; + } + + return Encode(finals.state, 16); + } + + /** + * Turns array of bytes into string representing each byte as + * unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + */ + public static String asHex(byte hash[]) { + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) { + if (((int) hash[i] & 0xff) < 0x10) + buf.append("0"); + + buf.append(Long.toString((int) hash[i] & 0xff, 16)); + } + + return buf.toString(); + } + + /** + * Returns 32-character hex representation of this objects hash + * + * @return String of this object's hash + */ + public String asHex() { + return asHex(this .Final()); + } + + /** + * One-stop md5 string encrypting. + */ + + public static String md5crypt(String input) { + MD5 md5 = new MD5(); + md5.Init(); + md5.Update(input); + return md5.asHex(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java new file mode 100644 index 00000000..25c757a2 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/MD5Crypt.java @@ -0,0 +1,339 @@ +/*------------------------------------------------------------------------------ + class + MD5Crypt + ------------------------------------------------------------------------------*/ + +package com.gluster.storage.management.core.utils; + + +/** + * <p>This class defines a method, + * {@link MD5Crypt#crypt(java.lang.String, java.lang.String) crypt()}, which + * takes a password and a salt string and generates an OpenBSD/FreeBSD/Linux-compatible + * md5-encoded password entry.</p> + * + * <p>Created: 3 November 1999</p> + * <p>Release: $Name: $</p> + * <p>Version: $Revision: 1.1 $</p> + * <p>Last Mod Date: $Date: 2004/07/12 13:35:20 $</p> + * <p>Java Code By: Jonathan Abbey, jonabbey@arlut.utexas.edu</p> + * <p>Original C Version:<pre> + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * </pre></p> + * + * @author Jonathan Abbey <jonabbey at arlut.utexas.edu> + */ +public final class MD5Crypt { + + /** + * + * Command line test rig. + * + */ + + static public void main(String argv[]) { + if ((argv.length < 1) || (argv.length > 3)) { + System.err + .println("Usage: MD5Crypt [-apache] password salt"); + System.exit(1); + } + + if (argv.length == 3) { + System.err.println(MD5Crypt.apacheCrypt(argv[1], argv[2])); + } else if (argv.length == 2) { + System.err.println(MD5Crypt.crypt(argv[0], argv[1])); + } else { + System.err.println(MD5Crypt.crypt(argv[0])); + } + + System.exit(0); + } + + static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + + static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + static private final String to64(long v, int size) { + StringBuffer result = new StringBuffer(); + + while (--size >= 0) { + result.append(itoa64.charAt((int) (v & 0x3f))); + v >>>= 6; + } + + return result.toString(); + } + + static private final void clearbits(byte bits[]) { + for (int i = 0; i < bits.length; i++) { + bits[i] = 0; + } + } + + /** + * convert an encoded unsigned byte value into a int + * with the unsigned value. + */ + + static private final int bytes2u(byte inp) { + return (int) inp & 0xff; + } + + /** + * <p>This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible + * md5-encoded password hash from a plaintext password and a + * salt.</p> + * + * <p>The resulting string will be in the form '$1$<salt>$<hashed mess></p> + * + * @param password Plaintext password + * + * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. + */ + + static public final String crypt(String password) { + StringBuffer salt = new StringBuffer(); + java.util.Random randgen = new java.util.Random(); + + /* -- */ + + while (salt.length() < 8) { + int index = (int) (randgen.nextFloat() * SALTCHARS.length()); + salt.append(SALTCHARS.substring(index, index + 1)); + } + + return MD5Crypt.crypt(password, salt.toString()); + } + + /** + * <p>This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible + * md5-encoded password hash from a plaintext password and a + * salt.</p> + * + * <p>The resulting string will be in the form '$1$<salt>$<hashed mess></p> + * + * @param password Plaintext password + * @param salt A short string to use to randomize md5. May start with $1$, which + * will be ignored. It is explicitly permitted to pass a pre-existing + * MD5Crypt'ed password entry as the salt. crypt() will strip the salt + * chars out properly. + * + * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. + */ + + static public final String crypt(String password, String salt) { + return MD5Crypt.crypt(password, salt, "$1$"); + } + + /** + * <p>This method generates an Apache MD5 compatible + * md5-encoded password hash from a plaintext password and a + * salt.</p> + * + * <p>The resulting string will be in the form '$apr1$<salt>$<hashed mess></p> + * + * @param password Plaintext password + * + * @return An Apache-compatible md5-hashed password string. + */ + + static public final String apacheCrypt(String password) { + StringBuffer salt = new StringBuffer(); + java.util.Random randgen = new java.util.Random(); + + /* -- */ + + while (salt.length() < 8) { + int index = (int) (randgen.nextFloat() * SALTCHARS.length()); + salt.append(SALTCHARS.substring(index, index + 1)); + } + + return MD5Crypt.apacheCrypt(password, salt.toString()); + } + + /** + * <p>This method actually generates an Apache MD5 compatible + * md5-encoded password hash from a plaintext password and a + * salt.</p> + * + * <p>The resulting string will be in the form '$apr1$<salt>$<hashed mess></p> + * + * @param password Plaintext password + * @param salt A short string to use to randomize md5. May start with $apr1$, which + * will be ignored. It is explicitly permitted to pass a pre-existing + * MD5Crypt'ed password entry as the salt. crypt() will strip the salt + * chars out properly. + * + * @return An Apache-compatible md5-hashed password string. + */ + + static public final String apacheCrypt(String password, String salt) { + return MD5Crypt.crypt(password, salt, "$apr1$"); + } + + /** + * <p>This method actually generates md5-encoded password hash from + * a plaintext password, a salt, and a magic string.</p> + * + * <p>There are two magic strings that make sense to use here.. '$1$' is the + * magic string used by the FreeBSD/Linux/OpenBSD MD5Crypt algorithm, and + * '$apr1$' is the magic string used by the Apache MD5Crypt algorithm.</p> + * + * <p>The resulting string will be in the form '<magic><salt>$<hashed mess></p> + * + * @param password Plaintext password @param salt A short string to + * use to randomize md5. May start with the magic string, which + * will be ignored. It is explicitly permitted to pass a + * pre-existing MD5Crypt'ed password entry as the salt. crypt() + * will strip the salt chars out properly. + * + * @return An md5-hashed password string. + */ + + static public final String crypt(String password, String salt, + String magic) { + /* This string is magic for this algorithm. Having it this way, + * we can get get better later on */ + + byte finalState[]; + MD5 ctx, ctx1; + long l; + + /* -- */ + + /* Refine the Salt first */ + + /* If it starts with the magic string, then skip that */ + + if (salt.startsWith(magic)) { + salt = salt.substring(magic.length()); + } + + /* It stops at the first '$', max 8 chars */ + + if (salt.indexOf('$') != -1) { + salt = salt.substring(0, salt.indexOf('$')); + } + + if (salt.length() > 8) { + salt = salt.substring(0, 8); + } + + ctx = new MD5(); + + ctx.Update(password); // The password first, since that is what is most unknown + ctx.Update(magic); // Then our magic string + ctx.Update(salt); // Then the raw salt + + /* Then just as many characters of the MD5(pw,salt,pw) */ + + ctx1 = new MD5(); + ctx1.Update(password); + ctx1.Update(salt); + ctx1.Update(password); + finalState = ctx1.Final(); + + for (int pl = password.length(); pl > 0; pl -= 16) { + ctx.Update(finalState, pl > 16 ? 16 : pl); + } + + /* the original code claimed that finalState was being cleared + to keep dangerous bits out of memory, but doing this is also + required in order to get the right output. */ + + clearbits(finalState); + + /* Then something really weird... */ + + for (int i = password.length(); i != 0; i >>>= 1) { + if ((i & 1) != 0) { + ctx.Update(finalState, 1); + } else { + ctx.Update(password.getBytes(), 1); + } + } + + finalState = ctx.Final(); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + * + * (The above timings from the C version) + */ + + for (int i = 0; i < 1000; i++) { + ctx1 = new MD5(); + + if ((i & 1) != 0) { + ctx1.Update(password); + } else { + ctx1.Update(finalState, 16); + } + + if ((i % 3) != 0) { + ctx1.Update(salt); + } + + if ((i % 7) != 0) { + ctx1.Update(password); + } + + if ((i & 1) != 0) { + ctx1.Update(finalState, 16); + } else { + ctx1.Update(password); + } + + finalState = ctx1.Final(); + } + + /* Now make the output string */ + + StringBuffer result = new StringBuffer(); + + result.append(magic); + result.append(salt); + result.append("$"); + + l = (bytes2u(finalState[0]) << 16) + | (bytes2u(finalState[6]) << 8) + | bytes2u(finalState[12]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[1]) << 16) + | (bytes2u(finalState[7]) << 8) + | bytes2u(finalState[13]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[2]) << 16) + | (bytes2u(finalState[8]) << 8) + | bytes2u(finalState[14]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[3]) << 16) + | (bytes2u(finalState[9]) << 8) + | bytes2u(finalState[15]); + result.append(to64(l, 4)); + + l = (bytes2u(finalState[4]) << 16) + | (bytes2u(finalState[10]) << 8) + | bytes2u(finalState[5]); + result.append(to64(l, 4)); + + l = bytes2u(finalState[11]); + result.append(to64(l, 2)); + + /* Don't leave anything around in vm they could use. */ + clearbits(finalState); + + return result.toString(); + } +} + diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java new file mode 100644 index 00000000..9b1cd5e2 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/NumberUtil.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import java.text.NumberFormat; + +public class NumberUtil { + public static final String formatNumber(double num) { + NumberFormat formatter = NumberFormat.getNumberInstance(); + formatter.setMinimumFractionDigits(2); + formatter.setMaximumFractionDigits(2); + return formatter.format(num); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java new file mode 100644 index 00000000..6c8b857d --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessResult.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the result of a command execution in a separate process. Consists of the "exit status" of the process and + * output from the process. The output includes stdout as well as stderr streams + */ +@XmlRootElement +public class ProcessResult { + + public static final int SUCCESS = 0; + private int exitValue; + private String output; + + // Required for JAXB de-serialization + public ProcessResult() { + + } + + public ProcessResult(int exitValue, String output) { + this.exitValue = exitValue; + this.output = output; + } + + public int getExitValue() { + return exitValue; + } + + public void setExitValue(int exitValue) { + this.exitValue = exitValue; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + public boolean isSuccess() { + return exitValue == SUCCESS; + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java new file mode 100644 index 00000000..507c6d95 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/ProcessUtil.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +import static com.gluster.storage.management.core.constants.CoreConstants.NEWLINE; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; + +/** + * Utility class for creating processes (foreground/background) with given + * command and checking the output/exit status + */ +public class ProcessUtil { + + private static final ProcessUtil instance = new ProcessUtil(); + + public ProcessResult executeCommand(List<String> command) { + return executeCommand(true, command); + } + + /** + * Executes given command in a separate process in FOREGROUND + * @param command + * @return {@link ProcessResult} object + */ + public ProcessResult executeCommand(String... command) { + ArrayList<String> commandList = new ArrayList<String>(); + for (String part : command) { + commandList.add(part); + } + return executeCommand(commandList); + } + + /** + * Executes given command in foreground/background + * @param runInForeground Boolean flag indicating whether the command should + * be executed in foreground + * @param command + * @return {@link ProcessResult} object + */ + public ProcessResult executeCommand(boolean runInForeground, List<String> command) { + StringBuilder output = new StringBuilder(); + try { + Process process = new ProcessBuilder(command).redirectErrorStream(true).start(); + + if (runInForeground) { + process.waitFor(); // Wait for process to finish + + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + + while ((line = br.readLine()) != null) { + output.append(line); + output.append(NEWLINE); + } + } else { + output.append("Command ["); + output.append(command); + output.append("] triggerred in background."); + } + + return new ProcessResult(process.exitValue(), output.toString()); + } catch (Throwable e) { + throw new GlusterRuntimeException("Exception while executing command [" + command + "]", e); + } + } + + public static void main(String args[]) { + ProcessResult result = new ProcessUtil().executeCommand("ls", "-lrt", "/"); + System.out.println(result.getExitValue()); + System.out.println(result.getOutput()); + } +} diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java new file mode 100644 index 00000000..1c4e6893 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.core.utils; + +public class StringUtil { + public static boolean filterString(String sourceString, + String filterString, boolean caseSensitive) { + return caseSensitive ? sourceString.contains(filterString) + : sourceString.toLowerCase().contains( + filterString.toLowerCase()); + } +} diff --git a/src/com.gluster.storage.management.gui.feature.webstart/.project b/src/com.gluster.storage.management.gui.feature.webstart/.project new file mode 100644 index 00000000..03adbe4c --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.gui.feature.webstart</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.pde.FeatureBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.FeatureNature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex b/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex new file mode 100644 index 00000000..252a5e15 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/buckminster.cspex @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cspecExtension xmlns:com="http://www.eclipse.org/buckminster/Common-1.0" + xmlns="http://www.eclipse.org/buckminster/CSpec-1.0"> + <actions> + <public name="create.eclipse.jnlp.product" actor="ant"> + <actorProperties> + <property key="buildFileId" value="buckminster.pdetasks" /> + <property key="targets" value="create.eclipse.jnlp.product" /> + </actorProperties> + <properties> + <!--property key="buckminster.eclipse.productFile" value="buckminster.jnlp.p2.product"/ --> + <property key="buckminster.eclipse.deleteuilauncher" value="false" /> + </properties> + <prerequisites alias="action.requirements"> + <attribute name="feature.exports" /> + </prerequisites> + <products alias="action.output" base="${buckminster.output}" + upToDatePolicy="NOT_EMPTY"> + <path path="glustermc/" /> + </products> + </public> + <public name="unsign.jars" actor="ant"> + <actorProperties> + <property key="buildFile" value="build/glustermc.ant" /> + <property key="targets" value="unsign" /> + </actorProperties> + </public> + <public name="sign.jars" actor="ant"> + <actorProperties> + <property key="buildFile" value="build/glustermc.ant" /> + <property key="targets" value="sign" /> + </actorProperties> + </public> + <public name="copy.root.files" actor="ant"> + <actorProperties> + <property key="buildFile" value="build/glustermc.ant" /> + <property key="targets" value="copy.root.files" /> + </actorProperties> + </public> + </actions> +</cspecExtension> diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build.properties b/src/com.gluster.storage.management.gui.feature.webstart/build.properties new file mode 100644 index 00000000..322a3114 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/build.properties @@ -0,0 +1,2 @@ +#bin.includes = feature.xml +root=rootfiles diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore b/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore Binary files differnew file mode 100644 index 00000000..ee3bc3a9 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/build/gluster.keystore diff --git a/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant b/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant new file mode 100644 index 00000000..e7baaa03 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/build/glustermc.ant @@ -0,0 +1,30 @@ +<project> + <property name="export.dir" value="${buckminster.output}/glustermc/" /> + <target name='unsign'> + <buckminster.signatureCleaner> + <fileset dir='${export.dir}/plugins'> + <include name='*.jar' /> + </fileset> + <fileset dir='${export.dir}/features'> + <include name='*.jar' /> + </fileset> + </buckminster.signatureCleaner> + </target> + + <target name="sign"> + <signjar alias="gluster" storepass="gluster" keypass="gluster" keystore="build/gluster.keystore"> + <fileset dir="${export.dir}/plugins"> + <include name="*.jar" /> + </fileset> + <fileset dir="${export.dir}/features"> + <include name="*.jar" /> + </fileset> + </signjar> + </target> + + <target name='copy.root.files'> + <copy todir="${export.dir}"> + <fileset dir="${basedir}/rootfiles" /> + </copy> + </target> +</project> diff --git a/src/com.gluster.storage.management.gui.feature.webstart/feature.xml b/src/com.gluster.storage.management.gui.feature.webstart/feature.xml new file mode 100644 index 00000000..0c7142fe --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/feature.xml @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="UTF-8"?> +<feature + id="com.gluster.storage.management.gui.feature.webstart" + label="Gluster Management Console - GUI Feature for Webstart" + version="1.0.0" + provider-name="Gluster Inc." + os="linux,macosx,win32" + ws="cocoa,gtk,win32" + arch="x86,x86_64,amd64"> + + <description url="http://www.example.com/description"> + [Enter Feature Description here.] + </description> + + <copyright url="http://www.example.com/copyright"> + [Enter Copyright Description here.] + </copyright> + + <license url="http://www.example.com/license"> + [Enter License Description here.] + </license> + + <includes + id="com.gluster.storage.management.gui.feature" + version="0.0.0"/> + + <requires> + <import plugin="org.eclipse.core.runtime" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.4.200" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.jface" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.observable" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.property" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.core.commands" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.core.runtime" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.core.runtime" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.jface" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.ui.workbench" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.equinox.preferences" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.5.0" match="equivalent"/> + <import plugin="org.eclipse.help" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.jface.databinding" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.property" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.observable" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.osgi" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.jobs" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.preferences" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.core.contenttype" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.equinox.app" version="1.0.0" match="compatible"/> + </requires> + + <plugin + id="org.eclipse.help" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.osgi.services" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.jface.databinding" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.jface" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.registry" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.app" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.expressions" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding.observable" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime.compatibility.auth" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.contenttype" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.swt" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime.compatibility.registry" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.equinox.preferences" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.commands" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.osgi" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui.workbench" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="javax.servlet" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.jobs" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="com.ibm.icu" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.common" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding.property" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + +</feature> diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp new file mode 100644 index 00000000..8828736c --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/gluster-management-console.jnlp @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jnlp spec="1.0+" codebase="$$codebase" href="gluster-management-console.jnlp"> + <information> + <title>Gluster Management Console</title> + <vendor>Gluster Inc.</vendor> + <homepage href="$$codebase" /> + <description>Gluster Management Console</description> + <icon kind="splash" href="splash.bmp"/> + </information> + <security> + <all-permissions/> + </security> + <resources> + <j2se java-vm-args="-XstartOnFirstThread" version="1.5+" /> + <jar href="plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar" main="true"/> + <extension + name="Gluster Management Console" + href="com.gluster.storage.management.gui.feature_1.0.0.jnlp"/> + <property + name="osgi.instance.area" + value="@user.home/Application Data/glustermc"/> + <property + name="osgi.configuration.area" + value="@user.home/Application Data/glustermc"/> + <property + name="eclipse.product" + value="com.gluster.storage.management.gui.product"/> + <property + name="gluster.server.url" + value="$$codebase"/> + </resources> + <resources os="Linux"> + <property name="osgi.ws" value="gtk"/> + </resources> + <application-desc main-class="org.eclipse.equinox.launcher.WebStartMain"> + <argument>-nosplash</argument> + </application-desc> +</jnlp>
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html new file mode 100644 index 00000000..70f47279 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/index.html @@ -0,0 +1,8 @@ +<html> +<head> +<title>Gluster Storage Platform</title> +</head> +<body> +<a href="http://192.168.1.123:8080/glustersp-webstart/linux.gtk.x86_64/gluster-management-console.jnlp">Gluster Storage Platform</a> +</body> +</html> diff --git a/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp Binary files differnew file mode 100644 index 00000000..059c28f9 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature.webstart/rootfiles/splash.bmp diff --git a/src/com.gluster.storage.management.gui.feature/.project b/src/com.gluster.storage.management.gui.feature/.project new file mode 100644 index 00000000..c93780b5 --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.gui.feature</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.pde.FeatureBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.FeatureNature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.gui.feature/build.properties b/src/com.gluster.storage.management.gui.feature/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/src/com.gluster.storage.management.gui.feature/feature.xml b/src/com.gluster.storage.management.gui.feature/feature.xml new file mode 100644 index 00000000..2448b3cc --- /dev/null +++ b/src/com.gluster.storage.management.gui.feature/feature.xml @@ -0,0 +1,775 @@ +<?xml version="1.0" encoding="UTF-8"?> +<feature + id="com.gluster.storage.management.gui.feature" + label="Gluster Storage Platform - GUI Feature" + version="1.0.0" + provider-name="GLUSTER" + os="linux,macosx,win32" + ws="cocoa,gtk,win32" + arch="x86,x86_64,amd64"> + + <description url="http://www.example.com/description"> + [Enter Feature Description here.] + </description> + + <copyright url="http://www.example.com/copyright"> + [Enter Copyright Description here.] + </copyright> + + <license url="http://www.example.com/license"> + [Enter License Description here.] + </license> + + <requires> + <import plugin="org.eclipse.core.runtime" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.jface" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.4.200" match="compatible"/> + <import plugin="org.eclipse.equinox.p2.core" version="2.0.0" match="compatible"/> + <import plugin="org.eclipse.core.net" version="1.1.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.swt" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.core.commands" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.observable" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.property" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.core.runtime" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.core.runtime" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.ui.ide" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.ui" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.jface.text" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.ui.workbench.texteditor" version="3.6.0" match="compatible"/> + <import plugin="org.eclipse.core.filebuffers" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.resources" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.filesystem" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.core.runtime" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.jface" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.ui.workbench" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.equinox.preferences" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.5.0" match="equivalent"/> + <import plugin="org.eclipse.ui" version="3.6.1" match="greaterOrEqual"/> + <import plugin="org.eclipse.core.runtime" version="3.6.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.ui.editors" version="3.6.1" match="greaterOrEqual"/> + <import plugin="org.eclipse.ui.forms" version="3.5.2" match="greaterOrEqual"/> + <import plugin="org.eclipse.rcp" version="3.6.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.equinox.concurrent"/> + <import plugin="org.eclipse.text" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.variables" version="3.1.0" match="compatible"/> + <import plugin="org.eclipse.osgi" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.jobs" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.preferences" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.core.contenttype" version="3.3.0" match="compatible"/> + <import plugin="org.eclipse.equinox.app" version="1.0.0" match="compatible"/> + <import plugin="org.eclipse.core.commands" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.core.filesystem" version="1.1.0" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.jface" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.compare.core" version="3.5.0" match="compatible"/> + <import plugin="org.eclipse.core.expressions" version="3.4.100" match="compatible"/> + <import plugin="org.eclipse.ecf.provider.filetransfer" version="2.0.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.core.filesystem" version="1.0.0" match="compatible"/> + <import plugin="org.eclipse.help" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.jface.text" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.p2.engine" version="2.0.0" match="compatible"/> + <import plugin="org.eclipse.equinox.p2.metadata" version="2.0.0" match="compatible"/> + <import plugin="org.eclipse.jface.databinding" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.property" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.core.databinding.observable" version="1.2.0" match="compatible"/> + <import plugin="org.eclipse.equinox.registry" version="3.3.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.ecf.provider.filetransfer" version="3.0.1" match="greaterOrEqual"/> + <import plugin="org.eclipse.equinox.p2.metadata.repository" version="1.0.100" match="greaterOrEqual"/> + <import plugin="org.eclipse.core.jobs" version="3.4.0" match="compatible"/> + <import plugin="org.eclipse.equinox.p2.repository" version="2.0.0" match="equivalent"/> + <import plugin="org.eclipse.equinox.p2.metadata" version="2.0.0" match="equivalent"/> + <import plugin="org.eclipse.equinox.p2.core" version="2.0.0" match="equivalent"/> + <import plugin="org.eclipse.ecf.filetransfer" version="2.0.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.equinox.security" version="1.0.0" match="compatible"/> + <import plugin="org.eclipse.equinox.common" version="3.4.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.equinox.preferences" version="3.2.200" match="greaterOrEqual"/> + <import plugin="org.eclipse.osgi" version="3.4.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.equinox.registry" version="3.4.0" match="greaterOrEqual"/> + <import plugin="org.eclipse.osgi" version="3.2.0" match="compatible"/> + <import plugin="org.eclipse.core.filesystem" version="1.3.0" match="compatible"/> + <import plugin="org.eclipse.swt" version="3.0.0" match="compatible"/> + <import plugin="org.eclipse.equinox.launcher" version="1.0.0"/> + </requires> + + <plugin + id="org.eclipse.ui.forms" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.help" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.p2.metadata" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.net.linux.x86_64" + os="linux" + ws="gtk" + arch="x86_64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.jface" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.app" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.expressions" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding.observable" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.swt" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.contenttype" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime.compatibility.registry" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.ecf.ssl" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.compare.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ecf.provider.filetransfer" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.osgi" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="com.gluster.storage.management.gui" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="javax.servlet" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ecf" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.filebuffers" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ant.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="com.ibm.icu" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.jobs" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding.property" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.text" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.resources" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.osgi.services" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.jface.databinding" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.variables" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.registry" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ecf.identity" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.runtime.compatibility.auth" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ecf.filetransfer" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui.workbench.texteditor" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ecf.provider.filetransfer.ssl" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.security" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.preferences" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.commands" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui.views" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.ui.workbench" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.jface.text" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.p2.repository" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.p2.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.p2.engine" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.common" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.p2.metadata.repository" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.net" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.rcp" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.launcher" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem.linux.x86" + os="linux" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem.linux.x86_64" + os="linux" + arch="x86_64, amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem.win32.x86" + os="win32" + ws="win32" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem.win32.x86_64" + os="win32" + ws="win32" + arch="x86_64, amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.net.linux.x86" + os="linux" + ws="gtk" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.net.win32.x86" + os="win32" + ws="win32" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.core.net.win32.x86_64" + os="win32" + ws="win32" + arch="x86_64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.swt.gtk.linux.x86" + os="linux" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.swt.gtk.linux.x86_64" + os="linux" + arch="x86_64, amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.swt.win32.win32.x86" + os="win32" + ws="win32" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.swt.win32.win32.x86_64" + os="win32" + ws="win32" + arch="x86_64,amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.launcher.gtk.linux.x86" + os="linux" + ws="gtk" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.equinox.launcher.gtk.linux.x86_64" + os="linux" + ws="gtk" + arch="x86_64, amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.equinox.launcher.win32.win32.x86" + os="win32" + ws="win32" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.equinox.launcher.win32.win32.x86_64" + os="win32" + ws="win32" + arch="x86_64, amd64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="com.gluster.storage.management.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.birt.chart.device.extension" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.birt.chart.engine" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.birt.chart.engine.extension" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.birt.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.emf.common" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.emf.ecore" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.emf.ecore.xmi" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.mozilla.javascript" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.apache.commons.codec" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="com.gluster.storage.management.client" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.databinding.beans" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.birt.chart.device.swt" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="com.richclientgui.rcptoolbox" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.core.filesystem.macosx" + os="macosx" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.equinox.launcher.cocoa.macosx" + os="macosx" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.equinox.launcher.cocoa.macosx.x86_64" + os="macosx" + arch="x86_64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true"/> + + <plugin + id="org.eclipse.swt.cocoa.macosx" + os="macosx" + arch="x86" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + + <plugin + id="org.eclipse.swt.cocoa.macosx.x86_64" + os="macosx" + arch="x86_64" + download-size="0" + install-size="0" + version="0.0.0" + fragment="true" + unpack="false"/> + +</feature> diff --git a/src/com.gluster.storage.management.gui/.classpath b/src/com.gluster.storage.management.gui/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/src/com.gluster.storage.management.gui/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/src/com.gluster.storage.management.gui/.project b/src/com.gluster.storage.management.gui/.project new file mode 100644 index 00000000..84ab78e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.gui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.gui/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.gui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..abf7cf5a --- /dev/null +++ b/src/com.gluster.storage.management.gui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Thu Nov 11 15:40:30 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..2e59c854 --- /dev/null +++ b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF @@ -0,0 +1,27 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: glustersp-gui +Bundle-SymbolicName: com.gluster.storage.management.gui;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: com.gluster.storage.management.gui.Activator +Bundle-Vendor: Gluster +Require-Bundle: org.eclipse.ui;bundle-version="3.6.1", + org.eclipse.core.runtime;bundle-version="3.6.0", + org.eclipse.ui.forms;bundle-version="3.5.2", + org.eclipse.rcp;bundle-version="3.6.0", + com.gluster.storage.management.core;bundle-version="1.0.0", + com.gluster.storage.management.client;bundle-version="1.0.0", + org.eclipse.core.databinding;bundle-version="1.3.100", + org.eclipse.jface.databinding;bundle-version="1.4.0", + org.eclipse.core.databinding.property;bundle-version="1.3.0", + org.eclipse.core.databinding.beans;bundle-version="1.2.100", + org.eclipse.birt.chart.engine;bundle-version="2.6.1", + org.eclipse.birt.chart.engine.extension;bundle-version="2.6.1", + org.eclipse.birt.chart.device.extension;bundle-version="2.6.1", + org.eclipse.birt.chart.device.swt;bundle-version="2.6.1", + com.ibm.icu;bundle-version="4.2.1", + com.richclientgui.rcptoolbox;bundle-version="1.0.5", + org.eclipse.core.resources +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: . diff --git a/src/com.gluster.storage.management.gui/build.properties b/src/com.gluster.storage.management.gui/build.properties new file mode 100644 index 00000000..47ced62b --- /dev/null +++ b/src/com.gluster.storage.management.gui/build.properties @@ -0,0 +1,15 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + icons/,\ + product_lg.gif,\ + splash.bmp,\ + splash/,\ + images/,\ + plugin.xml,\ + preferences.ini +src.includes = icons/,\ + splash.bmp,\ + images/,\ + preferences.ini diff --git a/src/com.gluster.storage.management.gui/icons/arrow-down.png b/src/com.gluster.storage.management.gui/icons/arrow-down.png Binary files differnew file mode 100644 index 00000000..7f23e3f4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/arrow-down.png diff --git a/src/com.gluster.storage.management.gui/icons/arrow-up.png b/src/com.gluster.storage.management.gui/icons/arrow-up.png Binary files differnew file mode 100644 index 00000000..b8ad3050 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/arrow-up.png diff --git a/src/com.gluster.storage.management.gui/icons/cluster.png b/src/com.gluster.storage.management.gui/icons/cluster.png Binary files differnew file mode 100644 index 00000000..c9348a21 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/cluster.png diff --git a/src/com.gluster.storage.management.gui/icons/disk-migrate.png b/src/com.gluster.storage.management.gui/icons/disk-migrate.png Binary files differnew file mode 100644 index 00000000..2de348dc --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/disk-migrate.png diff --git a/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png b/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png Binary files differnew file mode 100644 index 00000000..b982d118 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/disk-uninitialized.png diff --git a/src/com.gluster.storage.management.gui/icons/disk.png b/src/com.gluster.storage.management.gui/icons/disk.png Binary files differnew file mode 100644 index 00000000..99d532e8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/disk.png diff --git a/src/com.gluster.storage.management.gui/icons/disks.png b/src/com.gluster.storage.management.gui/icons/disks.png Binary files differnew file mode 100644 index 00000000..fc5a52f5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/disks.png diff --git a/src/com.gluster.storage.management.gui/icons/folder.png b/src/com.gluster.storage.management.gui/icons/folder.png Binary files differnew file mode 100644 index 00000000..784e8fa4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/folder.png diff --git a/src/com.gluster.storage.management.gui/icons/gluster_icon.png b/src/com.gluster.storage.management.gui/icons/gluster_icon.png Binary files differnew file mode 100644 index 00000000..f92e472d --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/gluster_icon.png diff --git a/src/com.gluster.storage.management.gui/icons/group.png b/src/com.gluster.storage.management.gui/icons/group.png Binary files differnew file mode 100644 index 00000000..7fb4e1f1 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/group.png diff --git a/src/com.gluster.storage.management.gui/icons/gsn.png b/src/com.gluster.storage.management.gui/icons/gsn.png Binary files differnew file mode 100644 index 00000000..68f21d30 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/gsn.png diff --git a/src/com.gluster.storage.management.gui/icons/logs.png b/src/com.gluster.storage.management.gui/icons/logs.png Binary files differnew file mode 100644 index 00000000..c8449f98 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/logs.png diff --git a/src/com.gluster.storage.management.gui/icons/mail.ico b/src/com.gluster.storage.management.gui/icons/mail.ico Binary files differnew file mode 100644 index 00000000..b0000611 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/mail.ico diff --git a/src/com.gluster.storage.management.gui/icons/minus-white.png b/src/com.gluster.storage.management.gui/icons/minus-white.png Binary files differnew file mode 100644 index 00000000..8efd5d33 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/minus-white.png diff --git a/src/com.gluster.storage.management.gui/icons/network-interface.png b/src/com.gluster.storage.management.gui/icons/network-interface.png Binary files differnew file mode 100644 index 00000000..24ca7370 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/network-interface.png diff --git a/src/com.gluster.storage.management.gui/icons/network-interfaces.png b/src/com.gluster.storage.management.gui/icons/network-interfaces.png Binary files differnew file mode 100644 index 00000000..752968bb --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/network-interfaces.png diff --git a/src/com.gluster.storage.management.gui/icons/network-interfaces1.png b/src/com.gluster.storage.management.gui/icons/network-interfaces1.png Binary files differnew file mode 100644 index 00000000..af438028 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/network-interfaces1.png diff --git a/src/com.gluster.storage.management.gui/icons/plus-white.png b/src/com.gluster.storage.management.gui/icons/plus-white.png Binary files differnew file mode 100644 index 00000000..c765946e --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/plus-white.png diff --git a/src/com.gluster.storage.management.gui/icons/preferences.png b/src/com.gluster.storage.management.gui/icons/preferences.png Binary files differnew file mode 100644 index 00000000..7b93eb05 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/preferences.png diff --git a/src/com.gluster.storage.management.gui/icons/progress-bar.png b/src/com.gluster.storage.management.gui/icons/progress-bar.png Binary files differnew file mode 100644 index 00000000..c7db00ae --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/progress-bar.png diff --git a/src/com.gluster.storage.management.gui/icons/question.png b/src/com.gluster.storage.management.gui/icons/question.png Binary files differnew file mode 100644 index 00000000..30a47032 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/question.png diff --git a/src/com.gluster.storage.management.gui/icons/sample.gif b/src/com.gluster.storage.management.gui/icons/sample.gif Binary files differnew file mode 100644 index 00000000..34fb3c9d --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/sample.gif diff --git a/src/com.gluster.storage.management.gui/icons/sample.icns b/src/com.gluster.storage.management.gui/icons/sample.icns Binary files differnew file mode 100644 index 00000000..1e92ccce --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/sample.icns diff --git a/src/com.gluster.storage.management.gui/icons/sample2.gif b/src/com.gluster.storage.management.gui/icons/sample2.gif Binary files differnew file mode 100644 index 00000000..252d7ebc --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/sample2.gif diff --git a/src/com.gluster.storage.management.gui/icons/sample3.gif b/src/com.gluster.storage.management.gui/icons/sample3.gif Binary files differnew file mode 100644 index 00000000..b949ac94 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/sample3.gif diff --git a/src/com.gluster.storage.management.gui/icons/search.png b/src/com.gluster.storage.management.gui/icons/search.png Binary files differnew file mode 100644 index 00000000..b4b23129 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/search.png diff --git a/src/com.gluster.storage.management.gui/icons/server-add-big.png b/src/com.gluster.storage.management.gui/icons/server-add-big.png Binary files differnew file mode 100644 index 00000000..d96b8175 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/server-add-big.png diff --git a/src/com.gluster.storage.management.gui/icons/server-add.png b/src/com.gluster.storage.management.gui/icons/server-add.png Binary files differnew file mode 100644 index 00000000..db604ee3 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/server-add.png diff --git a/src/com.gluster.storage.management.gui/icons/server-remove.png b/src/com.gluster.storage.management.gui/icons/server-remove.png Binary files differnew file mode 100644 index 00000000..5e9b2683 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/server-remove.png diff --git a/src/com.gluster.storage.management.gui/icons/server.png b/src/com.gluster.storage.management.gui/icons/server.png Binary files differnew file mode 100644 index 00000000..9bc37dce --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/server.png diff --git a/src/com.gluster.storage.management.gui/icons/servers.png b/src/com.gluster.storage.management.gui/icons/servers.png Binary files differnew file mode 100644 index 00000000..b18a74d9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/servers.png diff --git a/src/com.gluster.storage.management.gui/icons/star-small.png b/src/com.gluster.storage.management.gui/icons/star-small.png Binary files differnew file mode 100644 index 00000000..fef14263 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/star-small.png diff --git a/src/com.gluster.storage.management.gui/icons/status-offline-circle.png b/src/com.gluster.storage.management.gui/icons/status-offline-circle.png Binary files differnew file mode 100644 index 00000000..20d6f5ea --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-offline-circle.png diff --git a/src/com.gluster.storage.management.gui/icons/status-offline-small.png b/src/com.gluster.storage.management.gui/icons/status-offline-small.png Binary files differnew file mode 100644 index 00000000..39d47690 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-offline-small.png diff --git a/src/com.gluster.storage.management.gui/icons/status-offline.png b/src/com.gluster.storage.management.gui/icons/status-offline.png Binary files differnew file mode 100644 index 00000000..6b9fa6dd --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-offline.png diff --git a/src/com.gluster.storage.management.gui/icons/status-online-circle.png b/src/com.gluster.storage.management.gui/icons/status-online-circle.png Binary files differnew file mode 100644 index 00000000..210b1a6c --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-online-circle.png diff --git a/src/com.gluster.storage.management.gui/icons/status-online-small.png b/src/com.gluster.storage.management.gui/icons/status-online-small.png Binary files differnew file mode 100644 index 00000000..8e87f2e5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-online-small.png diff --git a/src/com.gluster.storage.management.gui/icons/status-online.png b/src/com.gluster.storage.management.gui/icons/status-online.png Binary files differnew file mode 100644 index 00000000..2414885b --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/status-online.png diff --git a/src/com.gluster.storage.management.gui/icons/stop.png b/src/com.gluster.storage.management.gui/icons/stop.png Binary files differnew file mode 100644 index 00000000..0cfd5859 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/stop.png diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png b/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png Binary files differnew file mode 100644 index 00000000..3c961711 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/ui-check-box-mix.png diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png b/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png Binary files differnew file mode 100644 index 00000000..ba447358 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/ui-check-box-uncheck.png diff --git a/src/com.gluster.storage.management.gui/icons/ui-check-box.png b/src/com.gluster.storage.management.gui/icons/ui-check-box.png Binary files differnew file mode 100644 index 00000000..07f3522a --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/ui-check-box.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-create-big.png b/src/com.gluster.storage.management.gui/icons/volume-create-big.png Binary files differnew file mode 100644 index 00000000..231bae5b --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-create-big.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-create.png b/src/com.gluster.storage.management.gui/icons/volume-create.png Binary files differnew file mode 100644 index 00000000..9c8a9da4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-create.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-delete.png b/src/com.gluster.storage.management.gui/icons/volume-delete.png Binary files differnew file mode 100644 index 00000000..86f7fbc2 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-delete.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-edit.png b/src/com.gluster.storage.management.gui/icons/volume-edit.png Binary files differnew file mode 100644 index 00000000..291bfc76 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-edit.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-rebalance.png b/src/com.gluster.storage.management.gui/icons/volume-rebalance.png Binary files differnew file mode 100644 index 00000000..e213cd5b --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-rebalance.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-start.png b/src/com.gluster.storage.management.gui/icons/volume-start.png Binary files differnew file mode 100644 index 00000000..aace63ad --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-start.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-stop-1.png b/src/com.gluster.storage.management.gui/icons/volume-stop-1.png Binary files differnew file mode 100644 index 00000000..0cfd5859 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-stop-1.png diff --git a/src/com.gluster.storage.management.gui/icons/volume-stop.png b/src/com.gluster.storage.management.gui/icons/volume-stop.png Binary files differnew file mode 100644 index 00000000..7af3a518 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume-stop.png diff --git a/src/com.gluster.storage.management.gui/icons/volume.png b/src/com.gluster.storage.management.gui/icons/volume.png Binary files differnew file mode 100644 index 00000000..46b7564a --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume.png diff --git a/src/com.gluster.storage.management.gui/icons/volume1.png b/src/com.gluster.storage.management.gui/icons/volume1.png Binary files differnew file mode 100644 index 00000000..5e23dbc8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volume1.png diff --git a/src/com.gluster.storage.management.gui/icons/volumes.png b/src/com.gluster.storage.management.gui/icons/volumes.png Binary files differnew file mode 100644 index 00000000..80dfa195 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volumes.png diff --git a/src/com.gluster.storage.management.gui/icons/volumes1.png b/src/com.gluster.storage.management.gui/icons/volumes1.png Binary files differnew file mode 100644 index 00000000..448e46fd --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volumes1.png diff --git a/src/com.gluster.storage.management.gui/icons/volumes2.png b/src/com.gluster.storage.management.gui/icons/volumes2.png Binary files differnew file mode 100644 index 00000000..0905f933 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volumes2.png diff --git a/src/com.gluster.storage.management.gui/icons/volumes3.png b/src/com.gluster.storage.management.gui/icons/volumes3.png Binary files differnew file mode 100644 index 00000000..7e90d397 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/volumes3.png diff --git a/src/com.gluster.storage.management.gui/icons/world.png b/src/com.gluster.storage.management.gui/icons/world.png Binary files differnew file mode 100644 index 00000000..68f21d30 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/world.png diff --git a/src/com.gluster.storage.management.gui/images/gauge.png b/src/com.gluster.storage.management.gui/images/gauge.png Binary files differnew file mode 100644 index 00000000..6f5764ea --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/gauge.png diff --git a/src/com.gluster.storage.management.gui/images/gauge_small.png b/src/com.gluster.storage.management.gui/images/gauge_small.png Binary files differnew file mode 100644 index 00000000..71e424fe --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/gauge_small.png diff --git a/src/com.gluster.storage.management.gui/images/progress_image_empty.png b/src/com.gluster.storage.management.gui/images/progress_image_empty.png Binary files differnew file mode 100644 index 00000000..590097ad --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/progress_image_empty.png diff --git a/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png b/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png Binary files differnew file mode 100644 index 00000000..97704230 --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/progress_image_filled_danger.png diff --git a/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png b/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png Binary files differnew file mode 100644 index 00000000..ae4e3c69 --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/progress_image_filled_safe.png diff --git a/src/com.gluster.storage.management.gui/images/progress_image_left.png b/src/com.gluster.storage.management.gui/images/progress_image_left.png Binary files differnew file mode 100644 index 00000000..97704230 --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/progress_image_left.png diff --git a/src/com.gluster.storage.management.gui/images/progress_image_right.png b/src/com.gluster.storage.management.gui/images/progress_image_right.png Binary files differnew file mode 100644 index 00000000..97704230 --- /dev/null +++ b/src/com.gluster.storage.management.gui/images/progress_image_right.png diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml new file mode 100644 index 00000000..f5ab3db7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -0,0 +1,1175 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + + <extension + id="application" + point="org.eclipse.core.runtime.applications"> + <application> + <run + class="com.gluster.storage.management.gui.Application"> + </run> + </application> + </extension> + <extension + point="org.eclipse.ui.perspectives"> + <perspective + name="Gluster Perspective" + class="com.gluster.storage.management.gui.Perspective" + id="com.gluster.storage.management.gui.perspective"> + </perspective> + </extension> + <extension + point="org.eclipse.ui.views"> + <view + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.NavigationView" + icon="icons/world.png" + id="com.gluster.storage.management.gui.views.NavigationView" + name="Cluster Navigation Tree" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.DetailsView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.details.DetailsView" + name="Details" + restorable="true"> + </view> + <view + category="org.eclipse.ui" + class="org.eclipse.ui.ExtensionFactory:progressView" + icon="icons/progress-bar.png" + id="org.eclipse.ui.views.ProgressView" + name="Tasks in Progress" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.DiscoveredServersView" + icon="icons/servers.png" + id="com.gluster.storage.management.gui.views.DiscoveredServersView" + name="Discovered Servers" + restorable="true"> + </view> + <view + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.DiscoveredServerView" + icon="icons/server.png" + id="com.gluster.storage.management.gui.views.DiscoveredServerView" + name="Discovered Server" + restorable="true"> + </view> + <category + id="com.gluster.storage.management.gui.category" + name="Gluster Managament Console"> + </category> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumesView" + icon="icons/volumes.png" + id="com.gluster.storage.management.gui.views.VolumesView" + name="Volumes" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumesSummaryView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.VolumesSummaryView" + name="Summary (Volumes)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.ClusterSummaryView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.ClusterSummaryView" + name="Summary (Cluster)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumeSummaryView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.VolumeSummaryView" + name="Summary (Volume)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumeDisksView" + icon="icons/disks.png" + id="com.gluster.storage.management.gui.views.VolumeDisksView" + name="Disks (Volume)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumeOptionsView" + icon="icons/preferences.png" + id="com.gluster.storage.management.gui.views.VolumeOptionsView" + name="Volume Options" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.VolumeLogsView" + icon="icons/logs.png" + id="com.gluster.storage.management.gui.views.VolumeLogsView" + name="Volume Logs" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.GlusterServersSummaryView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.GlusterServersSummaryView" + name="Summary (Servers)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.GlusterServersView" + icon="icons/servers.png" + id="com.gluster.storage.management.gui.views.GlusterServersView" + name="Servers" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.DisksView" + icon="icons/disks.png" + id="com.gluster.storage.management.gui.views.DisksView" + name="Disks" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.GlusterServerSummaryView" + icon="icons/gluster_icon.png" + id="com.gluster.storage.management.gui.views.GlusterServerSummaryView" + name="Summary (Server)" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.GlusterServerDisksView" + icon="icons/disks.png" + id="com.gluster.storage.management.gui.views.GlusterServerDisksView" + name="Server Disks" + restorable="true"> + </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.GlusterServerLogsView" + icon="icons/logs.png" + id="com.gluster.storage.management.gui.views.GlusterServerLogsView" + name="Server Logs" + restorable="true"> + </view> + </extension> + <extension + point="org.eclipse.ui.commands"> + <category + name="Gluster Commands" + id="com.gluster.storage.management.gui.category"> + </category> + <command + name="Create Volume" + description="Create a new Volume" + categoryId="com.gluster.storage.management.gui.category" + id="com.gluster.storage.management.gui.commands.CreateVolume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Delete Volume" + id="com.gluster.storage.management.gui.commands.DeleteVolume" + name="Delete Volume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Start Volume" + id="com.gluster.storage.management.gui.commands.StartVolume" + name="Start Volume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Stop Volume" + id="com.gluster.storage.management.gui.commands.StopVolume" + name="Stop Volume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Edit Volume" + id="com.gluster.storage.management.gui.commands.EditVolume" + name="Edit Volume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Rebalance Volume" + id="com.gluster.storage.management.gui.commands.RebalanceVolume" + name="Rebalance Volume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Add Server(s) to Cluster" + id="com.gluster.storage.management.gui.commands.AddServer" + name="Add Server(s)"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Remove Server(s) from Cluster" + id="com.gluster.storage.management.gui.commands.RemoveServer" + name="Remove Server(s)"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Migrate Disk" + id="com.gluster.storage.management.gui.commands.MigrateDisk" + name="Migrate Disk"> + </command> + </extension> + <extension + point="org.eclipse.ui.bindings"> + <key + commandId="com.gluster.storage.management.gui.commands.CreateVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+C"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.DeleteVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+D"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.StartVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+S"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.StopVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+T"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.EditVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+E"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.RebalanceVolume" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+B"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.AddServer" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+A"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.RemoveServer" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+R"> + </key> + <key + commandId="com.gluster.storage.management.gui.commands.MigrateDisk" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+M"> + </key> + <key + commandId="org.eclipse.ui.window.preferences" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+P"> + </key> + <key + commandId="org.eclipse.ui.window.showKeyAssist" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="CTRL+SHIFT+L"> + </key> + <key + commandId="org.eclipse.ui.navigate.nextTab" + contextId="org.eclipse.ui.contexts.window" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="ALT+ARROW_RIGHT"> + </key> + <key + commandId="org.eclipse.ui.navigate.previousTab" + contextId="org.eclipse.ui.contexts.window" + schemeId="com.gluster.storage.management.gui.KeyConfig" + sequence="ALT+ARROW_LEFT"> + </key> + <scheme + description="Default Key Bindings Scheme for Gluster Management Console" + id="com.gluster.storage.management.gui.KeyConfig" + name="Gluster"> + </scheme> + </extension> + <extension + id="product" + name="Gluster Management Console" + point="org.eclipse.core.runtime.products"> + <product + application="com.gluster.storage.management.gui.application" + name="Gluster Management Console"> + <property + name="aboutText" + value="GlusterFS is an open source clustered storage solution. The software is a powerful and flexible solution that simplifies the task of managing unstructured file data whether you have a few terabytes of storage or multiple petabytes. Gluster Management Console is a powerful GUI management interface for the GlusterFS."> + </property> + <property + name="windowImages" + value="icons/gluster_icon.png"> + </property> + <property + name="aboutImage" + value="splash/gluster_about.jpg"> + </property> + <property + name="appName" + value="about"> + </property> + <property + name="preferenceCustomization" + value="preferences.ini"> + </property> + </product> + </extension> + <extension + point="org.eclipse.ui.actionSets"> + <actionSet + description="Set of Actions in "Edit" menu" + id="com.gluster.storage.management.gui.actionsets.edit" + label="Edit Action Set" + visible="true"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.PreferencesAction" + definitionId="org.eclipse.ui.window.preferences" + icon="icons/preferences.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Preferences" + menubarPath="com.gluster.storage.management.gui.menu.edit/edit" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Preferences"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.edit" + label="&Edit" + path="additions"> + <groupMarker + name="edit"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed on multiple Volumes" + id="com.gluster.storage.management.gui.actionsets.volumes" + label="Volumes Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.DeleteVolume" + icon="icons/volume-delete.png" + id="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + label="&Delete Volume(s)" + menubarPath="com.gluster.storage.management.gui.menu.volumes/volumes" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Delete Volume(s)"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StopVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StopVolume" + icon="icons/volume-stop.png" + id="com.gluster.storage.management.gui.actions.StopVolumeAction" + label="S&top Volume(s)" + menubarPath="com.gluster.storage.management.gui.menu.volumes/volumes" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Stop Volume(s)"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StartVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StartVolume" + icon="icons/volume-start.png" + id="com.gluster.storage.management.gui.actions.StartVolumeAction" + label="&Start Volume(s)" + menubarPath="com.gluster.storage.management.gui.menu.volumes/volumes" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Start Volume(s)"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.CreateVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.CreateVolume" + icon="icons/volume-create.png" + id="com.gluster.storage.management.gui.actions.CreateVolumeAction" + label="&Create Volume" + menubarPath="com.gluster.storage.management.gui.menu.volumes/volumes" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Create a new Volume"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.volumes" + label="&Gluster" + path="additions"> + <groupMarker + name="volumes"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed on a single volume" + id="com.gluster.storage.management.gui.actionsets.volume" + label="Volume Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.MigrateDiskAction" + definitionId="com.gluster.storage.management.gui.commands.MigrateDisk" + icon="icons/disk-migrate.png" + id="com.gluster.storage.management.gui.actions.MigrateDiskAction" + label="&Migrate Disk" + menubarPath="com.gluster.storage.management.gui.menu.glusterserver/glusterserver" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Migrate Disk"> + <enablement> + <objectClass + name="com.gluster.storage.management.core.model.Disk"> + </objectClass> + </enablement> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.DeleteVolume" + icon="icons/volume-delete.png" + id="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + label="&Delete Volume" + menubarPath="com.gluster.storage.management.gui.menu.volume/volume" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Delete Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.RebalanceVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.RebalanceVolume" + icon="icons/volume-rebalance.png" + id="com.gluster.storage.management.gui.actions.RebalanceVolumeAction" + label="&Rebalance Volume" + menubarPath="com.gluster.storage.management.gui.menu.volume/volume" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Rebalance Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StopVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StopVolume" + icon="icons/volume-stop.png" + id="com.gluster.storage.management.gui.actions.StopVolumeAction" + label="S&top Volume" + menubarPath="com.gluster.storage.management.gui.menu.volume/volume" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Stop Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StartVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StartVolume" + icon="icons/volume-start.png" + id="com.gluster.storage.management.gui.actions.StartVolumeAction" + label="&Start Volume" + menubarPath="com.gluster.storage.management.gui.menu.volume/volume" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Start Volume"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.volume" + label="&Gluster" + path="additions"> + <groupMarker + name="volume"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed from "Cluster" context" + id="com.gluster.storage.management.gui.actionsets.gluster" + label="Cluster Action Set" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.CreateVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.CreateVolume" + icon="icons/volume-create.png" + id="com.gluster.storage.management.gui.actions.CreateVolumeAction" + label="Create &Volume" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Create a new Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="Add &Server(s)" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.cluster" + label="&Gluster"> + <groupMarker + name="cluster"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed on multiple Gluster Servers" + id="com.gluster.storage.management.gui.actionsets.glusterservers" + label="Gluster Servers Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.RemoveServerAction" + definitionId="com.gluster.storage.management.gui.commands.RemoveServer" + icon="icons/server-remove.png" + id="com.gluster.storage.management.gui.actions.RemoveServerAction" + label="&Remove Server(s)" + menubarPath="com.gluster.storage.management.gui.menu.servers/servers" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Remove Server(s)"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Add Server(s)" + menubarPath="com.gluster.storage.management.gui.menu.servers/servers" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.servers" + label="&Gluster" + path="additions"> + <groupMarker + name="servers"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed in the "Gluster Server" contextt; context" + id="com.gluster.storage.management.gui.actionsets.glusterserver" + label="Gluster Server Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.RemoveServerAction" + definitionId="com.gluster.storage.management.gui.commands.RemoveServer" + icon="icons/server-remove.png" + id="com.gluster.storage.management.gui.actions.RemoveServerAction" + label="&Remove Server" + menubarPath="com.gluster.storage.management.gui.menu.glusterserver/glusterserver" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Remove Server"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.glusterserver" + label="&Gluster" + path="additions"> + <groupMarker + name="glusterserver"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed on multiple Discovered Servers" + id="com.gluster.storage.management.gui.actionsets.serversdiscovered" + label="Discovered Servers Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Add Server(s)" + menubarPath="com.gluster.storage.management.gui.menu.discoveredservers/discoveredservers" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.discoveredservers" + label="&Gluster" + path="additions"> + <groupMarker + name="discoveredservers"> + </groupMarker> + </menu> + </actionSet> + <actionSet + description="Set of actions that can be performed on single Discovered Server" + id="com.gluster.storage.management.gui.actionsets.serverdiscovered" + label="Discovered Server Actions" + visible="false"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Add Server" + menubarPath="com.gluster.storage.management.gui.menu.discoveredserver/discoveredserver" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + <menu + id="com.gluster.storage.management.gui.menu.discoveredserver" + label="&Gluster" + path="additions"> + <groupMarker + name="discoveredserver"> + </groupMarker> + </menu> + </actionSet> + </extension> + <extension + point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension + targetID="*"> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.NavigationView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="left" + relative="org.eclipse.ui.editorss" + showTitle="false" + standalone="true" + visible="true"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.ClusterSummaryView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="right" + relative="com.gluster.storage.management.gui.views.navigator.NavigationView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.details.DetailsView" + minimized="false" + moveable="false" + ratio="0.70f" + relationship="right" + relative="com.gluster.storage.management.gui.views.navigator.NavigationView" + showTitle="false" + standalone="false" + visible="false"> + </view> + <view + closeable="true" + id="org.eclipse.ui.views.ProgressView" + minimized="false" + moveable="false" + ratio="0.80f" + relationship="bottom" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="true" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.DiscoveredServersView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.DiscoveredServerView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="right" + relative="com.gluster.storage.management.gui.views.navigator.NavigationView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumesSummaryView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumesView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.VolumesSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumeSummaryView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumeDisksView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumeOptionsView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.VolumeLogsView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.GlusterServersSummaryView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.GlusterServersView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.DisksView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.GlusterServerSummaryView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.GlusterServerDisksView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.GlusterServerLogsView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> + </perspectiveExtension> + </extension> + <extension + point="org.eclipse.ui.decorators"> + <decorator + adaptable="false" + class="com.gluster.storage.management.gui.views.navigator.NavigationTreeLabelDecorator" + id="com.gluster.storage.management.gui.views.navigator.decorator" + label="Navigation Tree Decorator" + lightweight="true" + location="BOTTOM_LEFT" + state="true"> + </decorator> + </extension> + <extension + point="org.eclipse.ui.preferencePages"> + <page + class="com.gluster.storage.management.gui.preferences.GlusterPreferencePage" + id="com.gluster.storage.management.gui.preferences.GlusterPreferencePage" + name="Gluster"> + </page> + <page + category="com.gluster.storage.management.gui.preferences.GlusterPreferencePage" + class="com.gluster.storage.management.gui.preferences.ClusterPreferencePage" + id="com.gluster.storage.management.gui.preferences.ClusterPreferencePage" + name="Cluster"> + </page> + <page + category="com.gluster.storage.management.gui.preferences.GlusterPreferencePage" + class="com.gluster.storage.management.gui.preferences.ConsolePreferencePage" + id="com.gluster.storage.management.gui.preferences.ConsolePreferencePage" + name="Console"> + </page> + <page + category="com.gluster.storage.management.gui.preferences.GlusterPreferencePage" + class="org.eclipse.ui.ExtensionFactory:newKeysPreferencePage" + id="org.eclipse.ui.NewKeysPreferencePage" + name="Keys"> + </page> + </extension> + <extension + point="org.eclipse.core.runtime.preferences"> + <initializer + class="com.gluster.storage.management.gui.preferences.PreferenceInitializer"> + </initializer> + </extension> + <extension + point="org.eclipse.ui.popupMenus"> + <objectContribution + id="gluster.context.menu.glusterserver" + objectClass="com.gluster.storage.management.core.model.GlusterServer"> + <action + class="com.gluster.storage.management.gui.actions.RemoveServerAction" + definitionId="com.gluster.storage.management.gui.commands.RemoveServer" + enablesFor="1" + icon="icons/server-remove.png" + id="com.gluster.storage.management.gui.actions.RemoveServerAction" + label="&Remove Server" + menubarPath="additions"> + </action> + </objectContribution> + <objectContribution + id="gluster.context.menu.volume" + objectClass="com.gluster.storage.management.core.model.Volume"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.MigrateDiskAction" + definitionId="com.gluster.storage.management.gui.commands.MigrateDisk" + icon="icons/disk-migrate.png" + id="com.gluster.storage.management.gui.actions.MigrateDiskAction" + label="&Migrate Disk" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Migrate Disk"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.DeleteVolume" + icon="icons/volume-delete.png" + id="com.gluster.storage.management.gui.actions.DeleteVolumeAction" + label="&Delete Volume" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Delete Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.RebalanceVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.RebalanceVolume" + icon="icons/volume-rebalance.png" + id="com.gluster.storage.management.gui.actions.RebalanceVolumeAction" + label="&Rebalance Volume" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Rebalance Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StopVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StopVolume" + icon="icons/volume-stop.png" + id="com.gluster.storage.management.gui.actions.StopVolumeAction" + label="S&top Volume" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Stop Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StartVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.StartVolume" + icon="icons/volume-start.png" + id="com.gluster.storage.management.gui.actions.StartVolumeAction" + label="&Start Volume" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Start Volume"> + </action> + </objectContribution> + <objectContribution + id="gluster.context.menu.server" + objectClass="com.gluster.storage.management.core.model.Server"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + enablesFor="+" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Add Server(s)" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + <visibility> + <not> + <objectClass + name="com.gluster.storage.management.core.model.GlusterServer"> + </objectClass> + </not> + </visibility> + </objectContribution> + <objectContribution + id="gluster.context.menu.entityGroup" + objectClass="com.gluster.storage.management.core.model.EntityGroup"> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.CreateVolumeAction" + definitionId="com.gluster.storage.management.gui.commands.CreateVolume" + icon="icons/volume-create.png" + id="com.gluster.storage.management.gui.actions.CreateVolumeAction" + label="&Create Volume" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Create a new Volume"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddServerAction" + definitionId="com.gluster.storage.management.gui.commands.AddServer" + icon="icons/server-add.png" + id="com.gluster.storage.management.gui.actions.AddServerAction" + label="&Add Server(s)" + menubarPath="additions" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add Server(s) to Cluster"> + </action> + </objectContribution> + </extension> + +</plugin> diff --git a/src/com.gluster.storage.management.gui/preferences.ini b/src/com.gluster.storage.management.gui/preferences.ini new file mode 100644 index 00000000..91228592 --- /dev/null +++ b/src/com.gluster.storage.management.gui/preferences.ini @@ -0,0 +1 @@ +org.eclipse.ui/KEY_CONFIGURATION_ID = com.gluster.storage.management.gui.KeyConfig
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/splash.bmp b/src/com.gluster.storage.management.gui/splash.bmp Binary files differnew file mode 100644 index 00000000..059c28f9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/splash.bmp diff --git a/src/com.gluster.storage.management.gui/splash/gluster_about.jpg b/src/com.gluster.storage.management.gui/splash/gluster_about.jpg Binary files differnew file mode 100644 index 00000000..242fa560 --- /dev/null +++ b/src/com.gluster.storage.management.gui/splash/gluster_about.jpg diff --git a/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp b/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp Binary files differnew file mode 100644 index 00000000..2de2897f --- /dev/null +++ b/src/com.gluster.storage.management.gui/splash/splash-dialog.bmp diff --git a/src/com.gluster.storage.management.gui/splash/splash-dialog.png b/src/com.gluster.storage.management.gui/splash/splash-dialog.png Binary files differnew file mode 100644 index 00000000..789eafb0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/splash/splash-dialog.png diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java new file mode 100644 index 00000000..3fa5bcf0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Activator.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "com.gluster.storage.management.gui"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + public void editorOpened() { + System.err.println("Editor opened!"); + } + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.java new file mode 100644 index 00000000..50dbd314 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Application.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.gui.login.LoginDialog; + +/** + * This class controls all aspects of the application's execution + */ +public class Application implements IApplication { + + public static final String PLUGIN_ID = "com.gluster.storage.management.gui"; + private static Application instance; + private List<IEntityListener> entityListeners = Collections.synchronizedList(new ArrayList<IEntityListener>()); + + public Application() { + instance = this; + } + + public static Application getApplication() { + return instance; + } + + private boolean login() { + LoginDialog loginDialog = new LoginDialog(new Shell(Display.getDefault())); + return (loginDialog.open() == Window.OK); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext) + */ + public Object start(IApplicationContext context) { + Display display = PlatformUI.createDisplay(); + + final boolean[] loginSuccess = new boolean[1]; + Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() { + public void run() { + loginSuccess[0] = login(); + } + }); + + if (!loginSuccess[0]) { + return IApplication.EXIT_OK; + } + try { + int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()); + if (returnCode == PlatformUI.RETURN_RESTART) { + return IApplication.EXIT_RESTART; + } + return IApplication.EXIT_OK; + } finally { + display.dispose(); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.equinox.app.IApplication#stop() + */ + public void stop() { + if (!PlatformUI.isWorkbenchRunning()) + return; + final IWorkbench workbench = PlatformUI.getWorkbench(); + final Display display = workbench.getDisplay(); + display.syncExec(new Runnable() { + public void run() { + if (!display.isDisposed()) + workbench.close(); + } + }); + } + + public void addEntityListener(IEntityListener listener) { + entityListeners.add(listener); + } + + public void entityChanged(Entity entity, String[] paremeters) { + for (IEntityListener listener : entityListeners) { + listener.entityChanged(entity, paremeters); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java new file mode 100644 index 00000000..3f6cb7d5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationActionBarAdvisor.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.ICoolBarManager; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.gui.utils.GUIHelper; + +/** + * An action bar advisor is responsible for creating, adding, and disposing of the actions added to a workbench window. + * Each window will be populated with new actions. + */ +public class ApplicationActionBarAdvisor extends ActionBarAdvisor { + private IWorkbenchWindow window; + /* + * Actions - important to allocate these only in makeActions, and then use them in the fill methods. This ensures + * that the actions aren't recreated when fillActionBars is called with FILL_PROXY. + */ + private IWorkbenchAction exitAction; + private IWorkbenchAction aboutAction; + + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { + super(configurer); + } + + protected void makeActions(final IWorkbenchWindow window) { + this.window = window; + /* + * Creates the actions and registers them. Registering is needed to ensure that key bindings work. The + * corresponding commands keybindings are defined in the plugin.xml file. Registering also provides automatic + * disposal of the actions when the window is closed. + */ + exitAction = ActionFactory.QUIT.create(window); + register(exitAction); + + aboutAction = ActionFactory.ABOUT.create(window); + aboutAction.setText("&About"); + aboutAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.HELP)); + register(aboutAction); + } + + protected void fillMenuBar(IMenuManager menuBar) { + // File + MenuManager fileMenu = new MenuManager("&File", IWorkbenchActionConstants.M_FILE); + fileMenu.add(new Separator()); + fileMenu.add(exitAction); + + // Help + MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP); + helpMenu.add(aboutAction); + + menuBar.add(fileMenu); + // Add a group marker indicating where action set menus will appear. + // All action sets from plugin.xml will get added here + menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + menuBar.add(helpMenu); + } + + protected void fillCoolBar(ICoolBarManager coolBar) { + // All our actions are added to toolbar through the extension point org.eclipse.ui.actionSets + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java new file mode 100644 index 00000000..07e20466 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchAdvisor.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.ui.application.IWorkbenchConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchAdvisor; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +/** + * This workbench advisor creates the window advisor, and specifies + * the perspective id for the initial window. + */ +public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { + + public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + return new ApplicationWorkbenchWindowAdvisor(configurer); + } + + public String getInitialWindowPerspectiveId() { + return Perspective.ID; + } + + @Override + public void initialize(IWorkbenchConfigurer configurer) { + super.initialize(configurer); + configurer.setSaveAndRestore(false); // we don't need save/restore as of now + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java new file mode 100644 index 00000000..722821f7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ApplicationWorkbenchWindowAdvisor.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.application.ActionBarAdvisor; +import org.eclipse.ui.application.IActionBarConfigurer; +import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.application.WorkbenchWindowAdvisor; + +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { + private final static int DEFAULT_WIDTH = 1024; + private final static int DEFAULT_HEIGHT = 768; + private final GUIHelper guiHelper = GUIHelper.getInstance(); + + public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { + super(configurer); + } + + @Override + public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) { + return new ApplicationActionBarAdvisor(configurer); + } + + @Override + public void preWindowOpen() { + super.preWindowOpen(); + + IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); + configurer.setInitialSize(new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT)); + configurer.setShowCoolBar(true); + configurer.setShowStatusLine(true); + configurer.setShowMenuBar(true); + configurer.setShowProgressIndicator(true); // shows progress indicator in status bar + } + + @Override + public void postWindowCreate() { + super.postWindowCreate(); + guiHelper.centerShellInScreen(getWindowConfigurer().getWindow().getShell()); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java new file mode 100644 index 00000000..92553797 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/DiskTableLabelProvider.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage.DISK_TABLE_COLUMN_INDICES; + +public class DiskTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + if (columnIndex == DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + DISK_STATUS status = disk.getStatus(); + switch (status) { + case READY: + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + case OFFLINE: + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.WORK_IN_PROGRESS); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + private String getDiskSpaceInUse(Disk disk) { + if (disk.isReady()) { + return NumberUtil.formatNumber(disk.getSpaceInUse()); + } else { + return "NA"; + } + } + + private String getDiskSpace(Disk disk) { + if (disk.isOffline()) { + return "NA"; + } else { + return NumberUtil.formatNumber(disk.getSpace()); + } + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? getDiskSpace(disk) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? getDiskSpaceInUse(disk) + : columnIndex == DISK_TABLE_COLUMN_INDICES.STATUS.ordinal() ? disk.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java new file mode 100644 index 00000000..26848eef --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/EntityGroupContentProvider.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import com.gluster.storage.management.core.model.EntityGroup; + +public class EntityGroupContentProvider<T> implements + IStructuredContentProvider { + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + + @SuppressWarnings("rawtypes") + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof EntityGroup) { + return ((EntityGroup) inputElement).getChildren().toArray(); + } + return null; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java new file mode 100644 index 00000000..3fc2dfa0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterServerTableLabelProvider.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.GlusterServersPage.GLUSTER_SERVER_TABLE_COLUMN_INDICES; + +public class GlusterServerTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof GlusterServer)) { + return null; + } + + GlusterServer server = (GlusterServer) element; + if(columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + SERVER_STATUS status = server.getStatus(); + if(status == SERVER_STATUS.ONLINE) { + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof GlusterServer)) { + return null; + } + + GlusterServer server = (GlusterServer) element; + + if (server.getStatus() == SERVER_STATUS.OFFLINE + && columnIndex != GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() + && columnIndex != GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + return "NA"; + } + + return (columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() ? server.getName() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS.ordinal() ? server.getStatusStr() + // : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.PREFERRED_NETWORK.ordinal() ? server.getPreferredNetworkInterface().getName() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS.ordinal() ? "" + server.getNumOfCPUs() + //: columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE.ordinal() ? "" + server.getCpuUsage() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY.ordinal() ? "" + server.getTotalMemory() + //: columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE.ordinal() ? "" + server.getMemoryInUse() + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE.ordinal() ? NumberUtil.formatNumber(server.getTotalDiskSpace()) + : columnIndex == GLUSTER_SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES.ordinal() ? server.getIpAddressesAsString() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java new file mode 100644 index 00000000..d9cb434c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ICommandIds.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +/** + * Interface defining the application's command IDs. + * Key bindings can be defined for specific commands. + * To associate an action with a command, use IAction.setActionDefinitionId(commandId). + * + * @see org.eclipse.jface.action.IAction#setActionDefinitionId(String) + */ +public interface ICommandIds { + + public static final String CMD_OPEN = "com.gluster.storage.management.gui.open"; + public static final String CMD_OPEN_MESSAGE = "com.gluster.storage.management.gui.openMessage"; + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java new file mode 100644 index 00000000..98dfbe9a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IEntityListener.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Any class that is interested in changes to entities in application scope should implement this interface and register + * with the application using {@link Application#addEntityListener(IEntityListener)} + * + * @author root + * + */ +public interface IEntityListener { + /** + * This method is called whenever any attribute of an entity in application scope changes + * @param entity Entity that has changed + * @param paremeters List of attribute names that have changed. This can be null. + */ + public void entityChanged(Entity entity, String[] paremeters); +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java new file mode 100644 index 00000000..fd5972c5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +public interface IImageKeys { + public static final String CLUSTER = "icons/cluster.png"; + public static final String VOLUMES = "icons/volumes.png"; + public static final String SERVERS = "icons/servers.png"; + public static final String VOLUME = "icons/volume.png"; + public static final String SERVER = "icons/server.png"; + public static final String GSN = "icons/gsn.png"; + public static final String SETTINGS = "icons/settings.png"; + public static final String ADD = "icons/plus-white.png"; + public static final String REMOVE = "icons/minus-white.png"; + public static final String CREATE_VOLUME = "icons/volume-create.png"; + public static final String CREATE_VOLUME_BIG = "icons/volume-create-big.png"; + public static final String REMOVE_VOLUME = "icons/volume-delete.png"; + public static final String ADD_SERVER = "icons/server-add.png"; + public static final String ADD_SERVER_BIG = "icons/server-add-big.png"; + public static final String REMOVE_SERVER = "icons/server-remove.png"; + public static final String HELP = "icons/question.png"; + public static final String STATUS_OFFLINE = "icons/status-offline.png"; + public static final String STATUS_ONLINE = "icons/status-online.png"; + public static final String STATUS_CANCELLED = "icons/status-offline.png"; + public static final String STATUS_SUCCESS = "icons/status-online.png"; + public static final String WORK_IN_PROGRESS = "icons/progress-bar.png"; + public static final String CHECKBOX_UNCHECKED = "icons/ui-check-box-uncheck.png"; + public static final String CHECKBOX_CHECKED = "icons/ui-check-box.png"; + public static final String DISK_UNINITIALIZED = "icons/disk-uninitialized.png"; + public static final String SEARCH = "icons/search.png"; + public static final String ARROW_UP = "icons/arrow-up.png"; + public static final String ARROW_DOWN = "icons/arrow-down.png"; + + public static final String OVERLAY_OFFLINE = "icons/status-offline-small.png"; + public static final String OVERLAY_ONLINE = "icons/status-online-small.png"; + public static final String OVERLAY_STAR = "icons/star-small.png"; + + public static final String SPLASH_IMAGE = "splash.bmp"; + public static final String DIALOG_SPLASH_IMAGE = "splash/splash-dialog.bmp"; + + public static final String PROGRESS_BAR_LEFT = "images/progress_image_left.png"; + public static final String PROGRESS_BAR_RIGHT = "images/progress_image_right.png"; + public static final String PROGRESS_BAR_FILLED = "images/progress_image_filled_safe.png"; + public static final String PROGRESS_BAR_EMPTY = "images/progress_image_empty.png"; + public static final String GAUGE_SMALL = "images/gauge_small.png"; +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java new file mode 100644 index 00000000..d7b700d4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/NetworkInterfaceTableLabelProvider.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + + +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.gui.views.details.tabcreators.GlusterServerTabCreator.NETWORK_INTERFACE_TABLE_COLUMN_INDICES; + +public class NetworkInterfaceTableLabelProvider extends TableLabelProviderAdapter { + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof NetworkInterface)) { + return null; + } + + NetworkInterface networkInterface = (NetworkInterface) element; + return (columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE.ordinal() ? networkInterface.getName() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.IP_ADDRESS.ordinal() ? networkInterface.getIpAddress() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.NETMASK.ordinal() ? networkInterface.getNetMask() + : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.GATEWAY.ordinal() ? networkInterface.getDefaultGateway() + // : columnIndex == NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED.ordinal() ? (networkInterface.isPreferred() ? "Yes" : "No") + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java new file mode 100644 index 00000000..3f8702ce --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/Perspective.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +import com.gluster.storage.management.gui.views.DetailsView; +import com.gluster.storage.management.gui.views.NavigationView; + +public class Perspective implements IPerspectiveFactory { + + /** + * The ID of the perspective as specified in the extension. + */ + public static final String ID = "com.gluster.storage.management.gui.perspective"; + + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(false); + //layout.addStandaloneView(ClusterView.ID, false, IPageLayout.LEFT, 0.30f, layout.getEditorArea()); + //layout.addStandaloneView(DetailsView.ID, false, IPageLayout.RIGHT, 0.70f, layout.getEditorArea()); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java new file mode 100644 index 00000000..cd5fab62 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerDiskTableLabelProvider.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage.SERVER_DISK_TABLE_COLUMN_INDICES; + +public class ServerDiskTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + if (columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal()) { + DISK_STATUS status = disk.getStatus(); + switch (status) { + case READY: + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + case OFFLINE: + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + case UNINITIALIZED: + return guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED); + case INITIALIZING: + return guiHelper.getImage(IImageKeys.WORK_IN_PROGRESS); + default: + throw new GlusterRuntimeException("Invalid disk status [" + status + "]"); + } + } + + return null; + } + + private String getDiskSpaceInUse(Disk disk) { + if(disk.isReady()) { + return NumberUtil.formatNumber(disk.getSpaceInUse()); + } else { + return "NA"; + } + } + + private String getDiskSpace(Disk disk) { + if(disk.isOffline()) { + return "NA"; + } else { + return NumberUtil.formatNumber(disk.getSpace()); + } + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + + Disk disk = (Disk) element; + return (columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? getDiskSpace(disk) + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? getDiskSpaceInUse(disk) + : columnIndex == SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal() ? disk.getStatusStr() + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java new file mode 100644 index 00000000..6ec446cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/ServerTableLabelProvider.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage.SERVER_TABLE_COLUMN_INDICES; + +public class ServerTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Server)) { + return null; + } + + Server server = (Server) element; + return (columnIndex == SERVER_TABLE_COLUMN_INDICES.NAME.ordinal() ? server.getName() + : columnIndex == SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES.ordinal() ? server.getIpAddressesAsString() + : columnIndex == SERVER_TABLE_COLUMN_INDICES.NUM_OF_DISKS.ordinal() ? "" + server.getNumOfDisks() + : columnIndex == SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE.ordinal() ? NumberUtil.formatNumber(server.getTotalDiskSpace()) +// : columnIndex == SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS.ordinal() ? "" + server.getNumOfCPUs() +// : columnIndex == SERVER_TABLE_COLUMN_INDICES.CPU_USAGE.ordinal() ? "" + server.getCpuUsage() +// : columnIndex == SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY.ordinal() ? "" + server.getTotalMemory() +// : columnIndex == SERVER_TABLE_COLUMN_INDICES.MEMORY_IN_USE.ordinal() ? "" + server.getMemoryInUse() +// : columnIndex == SERVER_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE.ordinal() ? "" + server.getDiskSpaceInUse() + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java new file mode 100644 index 00000000..95d6fde4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TableLabelProviderAdapter.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Image; + +public class TableLabelProviderAdapter implements ITableLabelProvider { + + @Override + public void addListener(ILabelProviderListener listener) { + // do nothing + + } + + @Override + public void dispose() { + // do nothing + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return true; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + // do nothing + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + return null; + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java new file mode 100644 index 00000000..399cdc65 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeLogTableLabelProvider.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.LogMessage; +import com.gluster.storage.management.core.utils.DateUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage.LOG_TABLE_COLUMN_INDICES; + +public class VolumeLogTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + private String getFormattedDiskName(Disk disk) { + return disk.getServerName() + ":" + disk.getName(); + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof LogMessage)) { + return null; + } + + LogMessage logMessage = (LogMessage) element; + return (columnIndex == LOG_TABLE_COLUMN_INDICES.DATE.ordinal() ? DateUtil.formatDate(logMessage.getTimestamp()) + : columnIndex == LOG_TABLE_COLUMN_INDICES.TIME.ordinal() ? DateUtil.formatTime(logMessage.getTimestamp()) + : columnIndex == LOG_TABLE_COLUMN_INDICES.DISK.ordinal() ? getFormattedDiskName(logMessage.getDisk()) + : columnIndex == LOG_TABLE_COLUMN_INDICES.SEVERITY.ordinal() ? "" + logMessage.getSeverity() + : columnIndex == LOG_TABLE_COLUMN_INDICES.MESSAGE.ordinal() ? logMessage.getMessage() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java new file mode 100644 index 00000000..cf1ceaf7 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import java.util.Map.Entry; + +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage.OPTIONS_TABLE_COLUMN_INDICES; + +public class VolumeOptionsTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Entry)) { + return null; + } + + Entry<String, String> entry = (Entry) element; + String key = entry.getKey(); + String value = entry.getValue(); + return (columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal() ? key + : columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE.ordinal() ? value + : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java new file mode 100644 index 00000000..b0f0c8d0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeTableLabelProvider.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.VolumesPage.VOLUME_TABLE_COLUMN_INDICES; + +public class VolumeTableLabelProvider implements ITableLabelProvider { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void addListener(ILabelProviderListener listener) { + } + + @Override + public void dispose() { + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + if (!(element instanceof Volume)) { + return null; + } + + Volume volume = (Volume) element; + if(columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS.ordinal()) { + VOLUME_STATUS status = volume.getStatus(); + if(status == VOLUME_STATUS.ONLINE) { + return guiHelper.getImage(IImageKeys.STATUS_ONLINE); + } else { + return guiHelper.getImage(IImageKeys.STATUS_OFFLINE); + } + } + + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Volume)) { + return null; + } + + Volume volume = (Volume) element; + return (columnIndex == VOLUME_TABLE_COLUMN_INDICES.NAME.ordinal() ? volume.getName() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_TYPE.ordinal() ? volume.getVolumeTypeStr() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.TRANSPORT_TYPE.ordinal() ? volume.getTransportTypeStr() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.NUM_OF_DISKS.ordinal() ? "" + volume.getNumOfDisks() + : columnIndex == VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS.ordinal() ? volume.getStatusStr() : "Invalid"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java new file mode 100644 index 00000000..4aa387bc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AbstractActionDelegate.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +import com.gluster.storage.management.core.model.Entity; + +/** + * All action delegates in the application should extend from this class. It provides common functionality of grabbing + * the Window object on initialization and extracting the selected entity in case of selection change on the navigation + * tree. + */ +public abstract class AbstractActionDelegate implements IWorkbenchWindowActionDelegate { + protected IWorkbenchWindow window; + protected Entity selectedEntity; + + @Override + public void selectionChanged(IAction action, ISelection selection) { + if (selection instanceof StructuredSelection) { + Entity selectedEntity = (Entity) ((StructuredSelection) selection).getFirstElement(); + + if (this.selectedEntity == selectedEntity) { + // entity selection has not changed. do nothing. + return; + } + + if(selectedEntity != null) { + this.selectedEntity = selectedEntity; + } + } + } + + @Override + public void init(IWorkbenchWindow window) { + this.window = window; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java new file mode 100644 index 00000000..7957b6f0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.GlusterServersClient; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +public class AddServerAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + GlusterServersClient glusterServersClient = new GlusterServersClient(modelManager.getSecurityToken()); + Server server = (Server) selectedEntity; + GlusterServerResponse response = glusterServersClient.addServer(server); + if (response.getStatus().isSuccess()) { + modelManager.removeDiscoveredServer(server); + modelManager.addGlusterServer(response.getGlusterServer()); + new MessageDialog(Display.getDefault().getActiveShell(), "Add Server", null, "Server [" + server.getName() + + "] added successfully!", MessageDialog.INFORMATION, new String[] { "OK" }, 0).open(); + } else { + new MessageDialog(Display.getDefault().getActiveShell(), "Add Server", null, "Server [" + server.getName() + + " could not be added to cluster! Error: [" + response.getStatus().getMessage() + "]", + MessageDialog.ERROR, new String[] { "OK" }, 0).open(); + } + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } + + @SuppressWarnings("rawtypes") + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity != null && selectedEntity instanceof Entity) { + action.setEnabled(true); + if (selectedEntity instanceof EntityGroup && ((EntityGroup) selectedEntity).getEntityType() == Volume.class) { + action.setEnabled(false); + } + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java new file mode 100644 index 00000000..266db0af --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CreateVolumeAction.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.CreateVolumeWizard; + +public class CreateVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + CreateVolumeWizard wizard = new CreateVolumeWizard(); + + WizardDialog dialog = new WizardDialog(window.getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(500, 550); + dialog.open(); + } + }); + } + + @Override + public void dispose() { + window = null; + } + + @SuppressWarnings("rawtypes") + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + action.setEnabled(true); + if(selectedEntity instanceof EntityGroup && ((EntityGroup)selectedEntity).getEntityType() != Volume.class) { + // selected entity is either "servers" or "discovered servers". + action.setEnabled(false); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java new file mode 100644 index 00000000..b4b92c31 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DeleteVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; + +public class DeleteVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java new file mode 100644 index 00000000..6f3fdf24 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/EditVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; + +public class EditVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java new file mode 100644 index 00000000..6c54bae8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/IActionSetIDs.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +public interface IActionSetIDs { + public static final String ACTION_SET_CLUSTER = "com.gluster.storage.management.gui.actionsets.gluster"; + public static final String ACTION_SET_VOLUMES = "com.gluster.storage.management.gui.actionsets.volumes"; + public static final String ACTION_SET_VOLUME = "com.gluster.storage.management.gui.actionsets.volume"; + public static final String ACTION_SET_DISKS = "com.gluster.storage.management.gui.actionsets.disks"; + public static final String ACTION_SET_DISK = "com.gluster.storage.management.gui.actionsets.disk"; + public static final String ACTION_SET_GLUSTER_SERVERS = "com.gluster.storage.management.gui.actionsets.glusterservers"; + public static final String ACTION_SET_GLUSTER_SERVER = "com.gluster.storage.management.gui.actionsets.glusterserver"; + public static final String ACTION_SET_DISCOVERED_SERVERS = "com.gluster.storage.management.gui.actionsets.serversdiscovered"; + public static final String ACTION_SET_DISCOVERED_SERVER = "com.gluster.storage.management.gui.actionsets.serverdiscovered"; + + public static final String ACTION_SET_EDIT = "com.gluster.storage.management.gui.actionsets.edit"; +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java new file mode 100644 index 00000000..75be4e6b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.MigrateDiskWizard; + +public class MigrateDiskAction extends AbstractActionDelegate { + private Volume volume; + private Disk disk; + + @Override + public void run(IAction action) { +// MigrateDiskDialog dialog = new MigrateDiskDialog(window.getShell(), volume, disk); +// dialog.create(); +// dialog.open(); + MigrateDiskWizard wizard = new MigrateDiskWizard(volume, disk); + + WizardDialog dialog = new WizardDialog(window.getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(1024, 600); + dialog.open(); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + } + + action.setEnabled(false); + if (selectedEntity instanceof Disk) { + disk = (Disk) selectedEntity; + action.setEnabled(((StructuredSelection) selection).size() == 1); + } + } + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java new file mode 100644 index 00000000..97f1c79b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; + +public class MigrateVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java new file mode 100644 index 00000000..f6fd88e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PreferencesAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.actions.ActionFactory; + +public class PreferencesAction extends AbstractActionDelegate { + + @Override + public void dispose() { + + } + + @Override + public void run(IAction action) { + ActionFactory.PREFERENCES.create(window).run(); + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java new file mode 100644 index 00000000..65227b0b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RebalanceVolumeAction.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; + +public class RebalanceVolumeAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java new file mode 100644 index 00000000..d5d42363 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +public class RemoveServerAction extends AbstractActionDelegate { + @Override + public void run(IAction action) { + System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + } + + @Override + public void dispose() { + System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java new file mode 100644 index 00000000..cc0fbe94 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class StartVolumeAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void run(final IAction action) { + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { + return; // Volume already online. Don't do anything. + } + + VolumesClient client = new VolumesClient(modelManager.getSecurityToken()); + final Status status = client.startVolume(volume.getName()); + final String actionDesc = action.getDescription(); + final Display display = Display.getDefault(); + display.asyncExec(new Runnable() { + + @Override + public void run() { + if (status.isSuccess()) { + new MessageDialog(display.getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] started successfully!", MessageDialog.INFORMATION, + new String[] { "OK" }, 0).open(); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.ONLINE); + } else { + new MessageDialog(display.getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] could not be started! Error: [" + status + "]", + MessageDialog.ERROR, new String[] { "OK" }, 0).open(); + } + } + }); + } + + @Override + public void dispose() { + + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.gui.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction + * , org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + action.setEnabled(volume.getStatus() == VOLUME_STATUS.OFFLINE); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java new file mode 100644 index 00000000..a89782f9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopVolumeAction.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class StopVolumeAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void run(IAction action) { + if(volume.getStatus() == VOLUME_STATUS.OFFLINE) { + return; // Volume already offline. Don't do anything. + } + + VolumesClient client = new VolumesClient(modelManager.getSecurityToken()); + final Status status = client.stopVolume(volume.getName()); + final String actionDesc = action.getDescription(); + final Display display = Display.getDefault(); + + display.asyncExec(new Runnable() { + + @Override + public void run() { + if (status.isSuccess()) { + new MessageDialog(Display.getCurrent().getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] stopped successfully!", MessageDialog.INFORMATION, new String[] { "OK" }, 0) + .open(); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + } else { + new MessageDialog(Display.getCurrent().getActiveShell(), actionDesc, null, "Volume [" + + volume.getName() + "] could not be stopped! Error: [" + status + "]", MessageDialog.ERROR, + new String[] { "OK" }, 0).open(); + } + } + }); + } + + @Override + public void dispose() { + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + action.setEnabled(volume.getStatus() == VOLUME_STATUS.ONLINE); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java new file mode 100644 index 00000000..e1fe0f14 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/TestPopupMenuAction.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +public class TestPopupMenuAction implements IObjectActionDelegate { + + private Shell shell; + + /** + * Constructor for Action1. + */ + public TestPopupMenuAction() { + super(); + } + + /** + * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + shell = targetPart.getSite().getShell(); + } + + /** + * @see IActionDelegate#run(IAction) + */ + public void run(IAction action) { + MessageDialog.openInformation( + shell, + "glustersp-gui", + "New Action was executed."); + } + + /** + * @see IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java new file mode 100644 index 00000000..80811226 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeDisksPage.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; +import com.gluster.storage.management.gui.utils.EntityViewerFilter; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.richclientgui.toolbox.duallists.CustomTableDualListComposite; +import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; +import com.richclientgui.toolbox.duallists.IRemovableContentProvider; +import com.richclientgui.toolbox.duallists.RemovableContentProvider; +import com.richclientgui.toolbox.duallists.TableColumnData; + +public class CreateVolumeDisksPage extends Composite { + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_USED + } + + private static final String[] DISK_TABLE_COLUMNS_NAMES = { "Server", "Disk", "Space (GB)", "Used Space (GB)" }; + + private GUIHelper guiHelper = GUIHelper.getInstance(); + private CustomTableDualListComposite<Disk> dualTableViewer; + private Text filterText; + // This list keeps track of the order of the disks as user changes the same by clicking on up/down arrow buttons + private List<Disk> chosenDisks = new ArrayList<Disk>(); + + private IRemovableContentProvider<Disk> chosenDisksContentProvider; + + private Button btnUp; + + private Button btnDown; + + public CreateVolumeDisksPage(final Composite parent, int style, List<Disk> allDisks, List<Disk> selectedDisks) { + super(parent, style); + + createPage(allDisks, selectedDisks); + + parent.layout(); + } + + private TableLabelProviderAdapter getDiskLabelProvider() { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? NumberUtil + .formatNumber(disk.getSpace()) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_USED.ordinal() ? NumberUtil + .formatNumber(disk.getSpaceInUse()) : "Invalid"); + } + }; + } + + private int indexOf(List<Disk> disks, Disk searchDisk) { + for(Disk disk : disks) { + if(disk.getQualifiedName().equals(searchDisk.getQualifiedName())) { + return disks.indexOf(disk); + } + } + return -1; + } + + private void createPage(List<Disk> allDisks, List<Disk> selectedDisks) { + setupPageLayout(); + + filterText = guiHelper.createFilterText(this); + new Label(this, SWT.NONE); + + createDualTableViewer(allDisks, selectedDisks); + createFilter(filterText, false); // attach filter text to the dual table viewer for auto-filtering + + Composite buttonContainer = new Composite(this, SWT.NONE); + buttonContainer.setLayout(new GridLayout(1, false)); + GridData buttonContainerData = new GridData(SWT.FILL, SWT.CENTER, true, true); + buttonContainerData.minimumWidth = 40; + buttonContainer.setLayoutData(buttonContainerData); + + btnUp = new Button(buttonContainer, SWT.TOGGLE); + GridData btnUpData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); + btnUpData.minimumWidth = 30; + btnUp.setLayoutData(btnUpData); + btnUp.setImage(guiHelper.getImage(IImageKeys.ARROW_UP)); + btnUp.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + chosenDisks = getChosenDisks(); + List<Disk> selectedDisks = getSelectedChosenDisks(); + + chosenDisksContentProvider.removeElements(chosenDisks); + for(Disk disk : selectedDisks) { + int index = chosenDisks.indexOf(disk); + Disk diskAbove = chosenDisks.get(index - 1); + chosenDisks.set(index - 1, disk); + chosenDisks.set(index, diskAbove); + } + chosenDisksContentProvider.addElements(chosenDisks); + dualTableViewer.refreshChosenViewer(); + updateButtons(); + } + }); + + btnDown = new Button(buttonContainer, SWT.TOGGLE); + btnDown.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false)); + btnDown.setImage(guiHelper.getImage(IImageKeys.ARROW_DOWN)); + btnDown.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + + chosenDisks = getChosenDisks(); + List<Disk> selectedDisks = getSelectedChosenDisks(); + + chosenDisksContentProvider.removeElements(chosenDisks); + for(Disk disk : selectedDisks) { + int index = chosenDisks.indexOf(disk); + Disk diskBelow = chosenDisks.get(index + 1); + chosenDisks.set(index + 1, disk); + chosenDisks.set(index, diskBelow); + } + chosenDisksContentProvider.addElements(chosenDisks); + dualTableViewer.refreshChosenViewer(); + updateButtons(); + + } + }); + } + + private List<Disk> getSelectedChosenDisks() { + TableItem[] selectedItems = dualTableViewer.getChosenTable().getSelection(); + List<Disk> selectedDisks = new ArrayList<Disk>(); + for (TableItem item : selectedItems) { + selectedDisks.add((Disk)item.getData()); + } + return selectedDisks; + } + + private void createFilter(final Text filterText, boolean caseSensitive) { + final String initialFilterString = filterText.getText(); + + final EntityViewerFilter filter = new EntityViewerFilter(initialFilterString, caseSensitive); + // On every keystroke inside the text field, update the filter string + filterText.addKeyListener(new KeyAdapter() { + private String filterString = initialFilterString; + + @Override + public void keyReleased(KeyEvent e) { + String enteredString = filterText.getText(); + if (enteredString.equals(filterString)) { + // Filter string has not changed. don't do anything + return; + } + + // Update filter string + filterString = enteredString; + filter.setFilterString(filterString); + + // Refresh viewer with newly filtered content + dualTableViewer.refreshAvailableViewer(); + dualTableViewer.refreshChosenViewer(); + } + }); + + dualTableViewer.setAvailableViewerFilter(filter); + dualTableViewer.setChosenViewerFilter(filter); + } + + private void createDualTableViewer(List<Disk> allDisks, List<Disk> selectedDisks) { + TableColumnData[] columnData = createColumnData(); + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(); + + dualTableViewer = new CustomTableDualListComposite<Disk>(this, SWT.NONE, columnData, columnData); + + dualTableViewer.setViewerLabels("Available:", "Chosen:"); + + dualTableViewer.setAvailableTableLinesVisible(false); + dualTableViewer.setAvailableTableHeaderVisible(true); + dualTableViewer.setAvailableContentProvider(new RemovableContentProvider<Disk>(getAvailableDisks(allDisks, + selectedDisks))); + dualTableViewer.setAvailableLabelProvider(diskLabelProvider); + + dualTableViewer.setChosenTableLinesVisible(true); + dualTableViewer.setChosenTableHeaderVisible(true); + + chosenDisksContentProvider = new RemovableContentProvider<Disk>(selectedDisks); + dualTableViewer.setChosenContentProvider(chosenDisksContentProvider); + dualTableViewer.setChosenLabelProvider(diskLabelProvider); + + dualTableViewer.getChosenTable().addSelectionListener(new SelectionAdapter() { + /* (non-Javadoc) + * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(SelectionEvent e) { + updateButtons(); + } + }); + } + + private void updateButtons() { + btnUp.setEnabled(true); + btnDown.setEnabled(true); + List<Disk> selectedChosenDisks = getSelectedChosenDisks(); + List<Disk> chosenDisks = getChosenDisks(); + for(Disk disk : selectedChosenDisks) { + int index = chosenDisks.indexOf(disk); + if(index == 0) { + btnUp.setEnabled(false); + } + if(index == chosenDisks.size() - 1) { + btnDown.setEnabled(false); + } + } + } + + /** + * @param allDisks + * @param selectedDisks + * @return + */ + private List<Disk> getAvailableDisks(List<Disk> allDisks, List<Disk> selectedDisks) { + List<Disk> availableDisks = new ArrayList<Disk>(); + for (Disk disk : allDisks) { + if (!selectedDisks.contains(disk)) { + availableDisks.add(disk); + } + } + return availableDisks; + } + + private TableColumnData[] createColumnData() { + DISK_TABLE_COLUMN_INDICES[] columns = DISK_TABLE_COLUMN_INDICES.values(); + TableColumnData[] columnData = new TableColumnData[columns.length]; + + for (DISK_TABLE_COLUMN_INDICES column : columns) { + int columnNum = column.ordinal(); + columnData[columnNum] = new TableColumnData(columnNum, DISK_TABLE_COLUMNS_NAMES[columnNum], 100); + } + return columnData; + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + + setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + public List<Disk> getChosenDisks() { + Object[] disksArr = (Object[]) chosenDisksContentProvider.getElements(dualTableViewer); + if (disksArr != null) { + List<Disk> disks = new ArrayList<Disk>(); + for (Object disk : disksArr) { + disks.add((Disk) disk); + } + return disks; + } + return null; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java new file mode 100644 index 00000000..d919fd84 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumePage1.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; + +public class CreateVolumePage1 extends WizardPage { + public static final String PAGE_NAME = "create.volume.page.1"; + private Text txtName; + private ComboViewer typeComboViewer; + private Text txtAccessControl; + private Volume volume = new Volume(); + private List<Disk> allDisks; + private Button btnNfs; + private Button btnStartVolume; + private Link linkCustomize; + private ValidationListener valListener = new ValidationListener(); + + /** + * Create the wizard. + */ + public CreateVolumePage1() { + super(PAGE_NAME); + setTitle("Create Volume"); + setDescription("Create a new Volume by choosing disks from the cluster servers and configuring the volume properties."); + + // by default, we create volume with all available disks + allDisks = GlusterDataModelManager.getInstance().getReadyDisksOfAllServers(); + volume.setDisks(allDisks); + } + + private class ValidationListener implements ModifyListener { + /* (non-Javadoc) + * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent) + */ + @Override + public void modifyText(ModifyEvent e) { + String volumeName = txtName.getText().trim(); + String accessControl = txtAccessControl.getText().trim(); + String volumeNameToken = "^[a-zA-Z][a-zA-Z0-9\\-]*"; + + + setErrorMessage(null); + setPageComplete(true); + + if(volumeName.length() == 0) { + setPageComplete(false); + setErrorMessage("Please enter Volume Name"); + } + + if (!volumeName.matches(volumeNameToken)) { + setPageComplete(false); + setErrorMessage("Please enter valid Volume Name"); + } + + if(accessControl.length() == 0) { + setPageComplete(false); + setErrorMessage("Please enter Access Control"); + } + + + // acl validation + String[] aclList = accessControl.split(","); + for (String ip : aclList) { + if (!isValidIP(ip)) { + setPageComplete(false); + setErrorMessage("Please enter valid access control list"); + } + } + + } + + private Boolean isValidIP(String ip) { + // String pattern = "^.[0-9]{1,3}/..[0-9]{1,3}/..[0-9]{1,3}/..[0-9]{1,3}"; + String pattern = "^.[0-9]{1,3}/."; + if (ip == "*") { + return true; + } + String[] ipQuads = ip.split("."); + for (String quad : ipQuads) { + if (!quad.matches(pattern)) { + return false; + } + } + return true; + + } + } + + /** + * Create contents of the wizard. + * @param parent + */ + public void createControl(Composite parent) { + + setPageComplete(false); + Composite container = new Composite(parent, SWT.NULL); + + setControl(container); + GridLayout gl_container = new GridLayout(2, false); + gl_container.verticalSpacing = 10; + gl_container.marginHeight = 10; + gl_container.marginLeft = 20; + gl_container.horizontalSpacing = 10; + container.setLayout(gl_container); + + new Label(container, SWT.NONE); + new Label(container, SWT.NONE); + + Label lblName = new Label(container, SWT.NONE); + lblName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblName.setText("Name: "); + + txtName = new Text(container, SWT.BORDER); + GridData txtNameData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + txtNameData.widthHint = 300; + txtName.setLayoutData(txtNameData); + txtName.addModifyListener(valListener); + + Label lblType = new Label(container, SWT.NONE); + lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblType.setText("Type: "); + + typeComboViewer = new ComboViewer(container, SWT.READ_ONLY); + Combo typeCombo = typeComboViewer.getCombo(); + GridData typeComboData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + typeCombo.setLayoutData(typeComboData); + typeComboViewer.setContentProvider(new ArrayContentProvider()); + typeComboViewer.setInput(Volume.VOLUME_TYPE.values()); + typeCombo.select(VOLUME_TYPE.PLAIN_DISTRIBUTE.ordinal()); // default type = Plain Distribute + typeComboViewer.setLabelProvider(new LabelProvider() { + @Override + public String getText(Object element) { + VOLUME_TYPE volumeType = (VOLUME_TYPE)element; + return Volume.getVolumeTypeStr(volumeType); + } + }); + + Label lblTransportType = new Label(container, SWT.NONE); + lblTransportType.setText("Transport Type: "); + + Label lblEthernet = new Label(container, SWT.NONE); + lblEthernet.setText("Ethernet"); + + Label lblDisks = new Label(container, SWT.RIGHT); + lblDisks.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblDisks.setText("Disks: "); + + linkCustomize = new Link(container, SWT.UNDERLINE_LINK); + linkCustomize.setText("All Disk(s) (<a>customize</a>)"); + linkCustomize.addListener (SWT.Selection, new Listener () { + public void handleEvent(Event event) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + SelectDisksDialog dialog = new SelectDisksDialog(getShell(), allDisks, volume.getDisks()); + + dialog.create(); + if(dialog.open() == Window.OK) { + // user has customized disks. get them from the dialog box. + volume.setDisks(dialog.getSelectedDisks()); + linkCustomize.setText("" + volume.getDisks().size() + " Disk(s) (<a>customize</a>)"); + } + } + }); + } + }); + + Label lblNasProtocol = new Label(container, SWT.RIGHT); + lblNasProtocol.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblNasProtocol.setText("NAS Protocol: "); + + Button btnGluster = new Button(container, SWT.CHECK); + btnGluster.setEnabled(false); + btnGluster.setSelection(true); + btnGluster.setText("Gluster"); + new Label(container, SWT.NONE); + + btnNfs = new Button(container, SWT.CHECK); + btnNfs.setSelection(true); + btnNfs.setText("NFS"); + + Label lblAccessControl = new Label(container, SWT.NONE); + lblAccessControl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblAccessControl.setText("Access Control: "); + + txtAccessControl = new Text(container, SWT.BORDER); + txtAccessControl.setText("*"); + GridData accessControlData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); + accessControlData.widthHint = 300; + txtAccessControl.setLayoutData(accessControlData); + txtAccessControl.addModifyListener(valListener); + + new Label(container, SWT.NONE); + Label lblAccessControlInfo = new Label(container, SWT.TOP); + lblAccessControlInfo.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); + lblAccessControlInfo.setText("(Comma separated list of IP addresses)"); + + Label lblStartVolume = new Label(container, SWT.NONE); + lblStartVolume.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + lblStartVolume.setText("Start Volume: "); + + btnStartVolume = new Button(container, SWT.CHECK); + btnStartVolume.setSelection(true); + } + + public Volume getVolume() { + volume.setName(txtName.getText()); + + IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); + volume.setVolumeType((VOLUME_TYPE)selection.getFirstElement()); + + volume.setTransportType(TRANSPORT_TYPE.ETHERNET); + Set<NAS_PROTOCOL> nasProtocols = new HashSet<Volume.NAS_PROTOCOL>(); + nasProtocols.add(NAS_PROTOCOL.GLUSTERFS); + if(btnNfs.getSelection()) { + nasProtocols.add(NAS_PROTOCOL.NFS); + } + + volume.setAccessControlList(txtAccessControl.getText()); + + return volume; + } + + public Boolean getStartVolumeRequest() { + return btnStartVolume.getSelection(); + } + + public Boolean isValidCreateVolumeForm() { + IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection(); + if (selection.getFirstElement().equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && ((int)volume.getDisks().size()) % 2 != 0 ) { + setErrorMessage("Mirror type volume requires disk in multiples of two"); + return false; + } else if(selection.getFirstElement().equals(VOLUME_TYPE.DISTRIBUTED_STRIPE) && ((int)volume.getDisks().size()) % 4 != 0) { + setErrorMessage("Stripe type volume requires disk in multiples of four"); + return false; + } + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java new file mode 100644 index 00000000..36755bec --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/CreateVolumeWizard.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; + +public class CreateVolumeWizard extends Wizard { + + public CreateVolumeWizard() { + setWindowTitle("Gluster Management Console - Create Volume"); + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + addPage(new CreateVolumePage1()); + } + + @Override + public boolean performFinish() { + CreateVolumePage1 page = (CreateVolumePage1) getPage(CreateVolumePage1.PAGE_NAME); + if (!page.isValidCreateVolumeForm()) { + return false; + } + + Volume newVolume = page.getVolume(); + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + VolumesClient volumesClient = new VolumesClient(modelManager.getSecurityToken()); + Status status = volumesClient.createVolume(newVolume); + + if (status.isSuccess()) { + newVolume.setStatus(VOLUME_STATUS.OFFLINE); + if (page.getStartVolumeRequest()) { + Status volumeStartStatus = volumesClient.startVolume(newVolume.getName()); + if (volumeStartStatus.isSuccess()) { + newVolume.setStatus(VOLUME_STATUS.ONLINE); + } + } + //update the model + modelManager.addVolume(newVolume); + MessageDialog.openInformation(getShell(), "Create Volume", "Volume created successfully and configuration added!"); + } else { + MessageDialog.openError(getShell(), "Create Volume", "Volume creation failed! [" + status.getCode() + "][" + + status.getMessage() + "]"); + } + + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java new file mode 100644 index 00000000..7dc0b03d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.GlusterDummyModel; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class MigrateDiskPage1 extends WizardPage { + private static final String PAGE_NAME = "migrate.disk.page.1"; + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_IN_USE + } + private static final String[] DISK_TABLE_COLUMN_NAMES = { "Server", "Disk", "Space (GB)", "Used Space (GB)" }; + + private Volume volume; + private Disk fromDisk; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private ITableLabelProvider getDiskLabelProvider() { + return new TableLabelProviderAdapter() { + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof Disk)) { + return null; + } + + Disk disk = (Disk) element; + return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? disk.getServerName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.DISK.ordinal() ? disk.getName() + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE.ordinal() ? NumberUtil.formatNumber(disk.getSpace()) + : columnIndex == DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal() ? NumberUtil.formatNumber(disk.getSpaceInUse()) + : "Invalid"); + } + }; + } + + private void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SERVER, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.DISK, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE, SWT.CENTER, 90); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE, SWT.CENTER, 90); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, DISK_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + + /** + * Create the wizard. + */ + public MigrateDiskPage1(Volume volume, Disk disk) { + super(PAGE_NAME); + this.volume = volume; + this.fromDisk = disk; + setTitle("Migrate Disk [" + volume.getName() + "]"); +// setDescription("Migrate data from one disk to another for the chosen Volume. " + +// "This will copy all data present in the \"from disk\" of the volume " + +// "to \"to disk\", remove \"from disk\" from the volume, and " + +// "add \"to disk\" to the volume"); + setDescription("Migrate volume data from \"From Disk\" to \"To Disk\""); + } + + private void setupPageLayout(Composite container) { + final GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + layout.horizontalSpacing = 10; + layout.marginTop = 10; + layout.marginLeft = 10; + layout.marginRight = 10; + container.setLayout(layout); + } + + private Composite createTableViewerComposite(Composite parent) { + Composite tableViewerComposite = new Composite(parent, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + /** + * Create contents of the wizard. + * + * @param parent + */ + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + setControl(container); + + setupPageLayout(container); + + GridData labelLayoutData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); + labelLayoutData.minimumWidth = 100; + labelLayoutData.verticalAlignment = SWT.BOTTOM; + //labelLayoutData.verticalIndent = 10; + + Label lblFromDisk = new Label(container, SWT.NONE); + lblFromDisk.setText("From Disk:"); + lblFromDisk.setLayoutData(labelLayoutData); + Label lblToDisk = new Label(container, SWT.NONE); + lblToDisk.setText("To Disk:"); + lblToDisk.setLayoutData(labelLayoutData); + + Text txtFilterFrom = guiHelper.createFilterText(container); + Text txtFilterTo = guiHelper.createFilterText(container); + + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(); + + GlusterDummyModel glusterDummyModel = GlusterDummyModel.getInstance(); + List<Disk> fromDisks = glusterDummyModel.getReadyDisksOfVolume(volume); + List<Disk> toDisks = glusterDummyModel.getReadyDisksOfAllServersExcluding(volume.getDisks()); + + TableViewer tableViewerFrom = createTableViewer(container, diskLabelProvider, fromDisks, txtFilterFrom); + if(fromDisk != null) { + setFromDisk(tableViewerFrom, fromDisk); + } + + createTableViewer(container, diskLabelProvider, toDisks, txtFilterTo); + } + + private void setFromDisk(TableViewer tableViewer, Disk diskToSelect) { + Table table = tableViewer.getTable(); + for(int i = 0 ; i < table.getItemCount(); i++) { + TableItem item = table.getItem(i); + if(item.getData() == diskToSelect) { + table.select(i); + return; + } + } + } + + private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, List<Disk> fromDisks, Text txtFilterText) { + Composite tableViewerComposite = createTableViewerComposite(container); + + TableViewer tableViewer = new TableViewer(tableViewerComposite, SWT.SINGLE); + tableViewer.setContentProvider(new ArrayContentProvider()); + tableViewer.setLabelProvider(diskLabelProvider); + + setupDiskTable(tableViewerComposite, tableViewer.getTable()); + guiHelper.createFilter(tableViewer, txtFilterText, false); + + tableViewer.setInput(fromDisks.toArray()); + return tableViewer; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java new file mode 100644 index 00000000..464abefa --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import org.eclipse.jface.wizard.Wizard; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; + +public class MigrateDiskWizard extends Wizard { + private Volume volume; + private Disk disk; + + public MigrateDiskWizard(Volume volume, Disk disk) { + setWindowTitle("Gluster Management Console - Migrate Disk [" + volume.getName() + "]"); + this.volume = volume; + this.disk = disk; + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + addPage(new MigrateDiskPage1(volume, disk)); + } + + @Override + public boolean performFinish() { + System.out.println("Triggered Disk Migration!"); + // TODO: Add code to migrate disk + return true; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java new file mode 100644 index 00000000..10a36fb0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/SelectDisksDialog.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.dialogs; + +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.osgi.framework.internal.core.Msg; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; + +public class SelectDisksDialog extends Dialog { + + private CreateVolumeDisksPage disksPage; + private List<Disk> allDisks; + private List<Disk> selectedDisks; + + /** + * Create the dialog. + * + * @param parentShell + */ + public SelectDisksDialog(Shell parentShell, List<Disk> allDisks, List<Disk> selectedDisks) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + this.allDisks = allDisks; + this.selectedDisks = selectedDisks; + } + + /** + * Create contents of the dialog. + * + * @param parent + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + GridLayout containerLayout = new GridLayout(2, false); + container.setLayout(containerLayout); + GridData containerLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + container.setLayoutData(containerLayoutData); + + getShell().setText("Create Volume - Select Disks"); + + disksPage = new CreateVolumeDisksPage(container, SWT.NONE, allDisks, selectedDisks); + + return container; + } + + /** + * Create contents of the button bar. + * + * @param parent + */ + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + /** + * Return the initial size of the dialog. + */ + @Override + protected Point getInitialSize() { + return new Point(1024, 600); + } + + @Override + protected void cancelPressed() { + super.cancelPressed(); + } + + @Override + protected void okPressed() { + if (this.getSelectedDisks().size() == 0 ) { + MessageDialog.openError(getShell(), "Select Disk(s)", "Please select atlease one disk"); + } else { + super.okPressed(); + } + } + + public List<Disk> getSelectedDisks() { + return disksPage.getChosenDisks(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java new file mode 100644 index 00000000..b5945e61 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/jobs/InitializeDiskJob.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.jobs; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.ui.progress.IProgressConstants; +import org.eclipse.ui.progress.IProgressConstants2; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class InitializeDiskJob extends Job { + private Disk disk; + private Application app = Application.getApplication(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + public InitializeDiskJob(Disk disk) { + super("Initialize Disk [" + disk.getQualifiedName() + "]"); + this.disk = disk; + setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.WORK_IN_PROGRESS)); + } + + private void updateStatus(final DISK_STATUS status) { + disk.setStatus(status); + disk.setSpaceInUse(0d); + app.entityChanged(disk, new String[] { "status", "spaceInUse" }); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + monitor.beginTask("Formatting the disk...", 100); + boolean cancelRequested = false; + String msgPrefix = ""; + try { + for (int i = 1; i <= 5; i++) { + if (!cancelRequested && monitor.isCanceled()) { + cancelRequested = true; // come only once here + + msgPrefix = "This task cannot be cancelled! "; + monitor.setTaskName(msgPrefix); +// setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.STATUS_CANCELLED)); +// +// updateStatus(DISK_STATUS.UNINITIALIZED); +// return new Status(Status.CANCEL, Application.PLUGIN_ID, "Cancelled"); + } + Thread.sleep(2000); + monitor.worked(20); + monitor.setTaskName(msgPrefix + "[" + 20 * i + "%] completed"); + } + monitor.done(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + updateStatus(DISK_STATUS.READY); + setProperty(IProgressConstants.ICON_PROPERTY, guiHelper.getImageDescriptor(IImageKeys.STATUS_SUCCESS)); + + return new Status(Status.OK, Application.PLUGIN_ID, "Task Completed!"); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java new file mode 100644 index 00000000..45b13a19 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/login/LoginDialog.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.login; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.PojoProperties; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.UsersClient; +import com.gluster.storage.management.client.constants.ClientConstants; +import com.gluster.storage.management.core.model.ConnectionDetails; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.validators.StringRequiredValidator; + +/** + * Login dialog, which prompts for the user's account info, and has Login and Cancel buttons. + */ +public class LoginDialog extends Dialog { + + private Text userIdText = null; + private Text passwordText = null; + private Button okButton; + + private final ConnectionDetails connectionDetails = new ConnectionDetails("gluster", ""); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Composite composite; + + public LoginDialog(Shell parentShell) { + super(parentShell); + } + + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + + newShell.setText("Gluster Management Console"); + addEscapeListener(newShell); + } + + private void addEscapeListener(Shell shell) { + shell.addTraverseListener(new TraverseListener() { + + @Override + public void keyTraversed(TraverseEvent e) { + if (e.keyCode == SWT.ESC) { + cancelPressed(); + } + } + }); + } + + private void createUserIdLabel(Composite composite) { + Label userIdLabel = new Label(composite, SWT.NONE); + userIdLabel.setText("&User ID:"); + userIdLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createUserIdText(Composite composite) { + userIdText = new Text(composite, SWT.BORDER); + userIdText.setText("gluster"); + userIdText.setEnabled(false); + + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + ; + layoutData.widthHint = convertWidthInCharsToPixels(32); + userIdText.setLayoutData(layoutData); + } + + private void createPasswordLabel(Composite composite) { + Label passwordLabel = new Label(composite, SWT.NONE); + passwordLabel.setText("&Password:"); + passwordLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false)); + } + + private void createPasswordText(Composite composite) { + passwordText = new Text(composite, SWT.BORDER | SWT.PASSWORD); + + GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false); + ; + layoutData.widthHint = convertWidthInCharsToPixels(32); + passwordText.setLayoutData(layoutData); + } + + private void configureDialogLayout(Composite composite) { + GridLayout layout = (GridLayout) composite.getLayout(); + layout.numColumns = 2; + layout.marginLeft = 20; + layout.marginRight = 20; + layout.marginTop = 20; + layout.horizontalSpacing = 20; + layout.verticalSpacing = 20; + } + + /** + * Overriding to make sure that the dialog is centered in screen + */ + @Override + protected void initializeBounds() { + super.initializeBounds(); + + guiHelper.centerShellInScreen(getShell()); + } + + @Override + protected Control createDialogArea(Composite parent) { + parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE)); + parent.setBackgroundMode(SWT.INHERIT_FORCE); // Makes sure that child composites inherit the same background + + composite = (Composite) super.createDialogArea(parent); + configureDialogLayout(composite); + + createUserIdLabel(composite); + createUserIdText(composite); + + createPasswordLabel(composite); + createPasswordText(composite); + + return composite; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + okButton = createButton(parent, IDialogConstants.OK_ID, "&Login", true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + + setupDataBinding(); + } + + /** + * Sets up data binding between the text fields and the connection details object. Also attaches a "string required" + * validator to the "password" text field. This validator is configured to do the following on validation failure<br> + * <li>show an ERROR decorator</li><li>disable the "Login" button + */ + private void setupDataBinding() { + DataBindingContext dataBindingContext = new DataBindingContext(SWTObservables.getRealm(Display.getCurrent())); + UpdateValueStrategy passwordBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + + // The Validator shows error decoration and disables OK button on validation failure + passwordBindingStrategy.setBeforeSetValidator(new StringRequiredValidator("Please enter password!", guiHelper + .createErrorDecoration(passwordText), okButton)); + + dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(passwordText), + PojoProperties.value("password").observe(connectionDetails), passwordBindingStrategy, + passwordBindingStrategy); + + UpdateValueStrategy userIdBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); + dataBindingContext + .bindValue(WidgetProperties.text(SWT.Modify).observe(userIdText), PojoProperties.value("userId") + .observe(connectionDetails), userIdBindingStrategy, userIdBindingStrategy); + } + + protected void okPressed() { + String user = connectionDetails.getUserId(); + String password = connectionDetails.getPassword(); + + UsersClient usersClient = new UsersClient(); + if (usersClient.authenticate(user, password)) { + GlusterDataModelManager.getInstance().initializeModel(usersClient.getSecurityToken()); + super.okPressed(); + } else { + MessageDialog.openError(getShell(), "Authentication Failed", "Invalid User ID or password"); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java new file mode 100644 index 00000000..14dbeba9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ClusterPreferencePage.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.Activator; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing <samp>FieldEditorPreferencePage</samp>, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + * <p> + * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ + +public class ClusterPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public ClusterPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java new file mode 100644 index 00000000..2d49af9b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ConsolePreferencePage.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.Activator; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing <samp>FieldEditorPreferencePage</samp>, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + * <p> + * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ + +public class ConsolePreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public ConsolePreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java new file mode 100644 index 00000000..23b2cff2 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/GlusterPreferencePage.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.gluster.storage.management.gui.Activator; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing <samp>FieldEditorPreferencePage</samp>, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + * <p> + * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ + +public class GlusterPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public GlusterPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("A demonstration of a preference page implementation"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + public void createFieldEditors() { + addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, + "&Directory preference:", getFieldEditorParent())); + addField( + new BooleanFieldEditor( + PreferenceConstants.P_BOOLEAN, + "&An example of a boolean preference", + getFieldEditorParent())); + + addField(new RadioGroupFieldEditor( + PreferenceConstants.P_CHOICE, + "An example of a multiple-choice preference", + 1, + new String[][] { { "&Choice 1", "choice1" }, { + "C&hoice 2", "choice2" } + }, getFieldEditorParent())); + addField( + new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java new file mode 100644 index 00000000..4c1bfcd5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceConstants.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.preferences; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants { + + public static final String P_PATH = "pathPreference"; + + public static final String P_BOOLEAN = "booleanPreference"; + + public static final String P_CHOICE = "choicePreference"; + + public static final String P_STRING = "stringPreference"; + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java new file mode 100644 index 00000000..74ace130 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/PreferenceInitializer.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.gluster.storage.management.gui.Activator; + +/** + * Class used to initialize default preference values. + */ +public class PreferenceInitializer extends AbstractPreferenceInitializer { + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + store.setDefault(PreferenceConstants.P_BOOLEAN, true); + store.setDefault(PreferenceConstants.P_CHOICE, "choice2"); + store.setDefault(PreferenceConstants.P_STRING, + "Default value"); + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java new file mode 100644 index 00000000..a98c7862 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/GlusterToolbarManager.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.toolbar; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.actions.IActionSetIDs; + +public class GlusterToolbarManager implements ToolbarManager { + private enum ENTITY_TYPE { + CLUSTER, VOLUMES, VOLUME, GLUSTER_SERVERS, GLUSTER_SERVER, DISCOVERED_SERVERS, DISCOVERED_SERVER + }; + + private IWorkbenchWindow window; + private final Map<Class<? extends Entity>, ENTITY_TYPE> entityTypeMap = createEntityTypeMap(); + private final Map<ENTITY_TYPE, String> actionSetMap = createActionSetMap(); + + private Map<Class<? extends Entity>, ENTITY_TYPE> createEntityTypeMap() { + Map<Class<? extends Entity>, ENTITY_TYPE> entityTypeMap = new HashMap<Class<? extends Entity>, GlusterToolbarManager.ENTITY_TYPE>(); + entityTypeMap.put(Cluster.class, ENTITY_TYPE.CLUSTER); + entityTypeMap.put(Volume.class, ENTITY_TYPE.VOLUME); + entityTypeMap.put(Server.class, ENTITY_TYPE.DISCOVERED_SERVER); + entityTypeMap.put(GlusterServer.class, ENTITY_TYPE.GLUSTER_SERVER); + + return entityTypeMap; + } + + private Map<ENTITY_TYPE, String> createActionSetMap() { + Map<ENTITY_TYPE, String> actionSetMap = new HashMap<GlusterToolbarManager.ENTITY_TYPE, String>(); + actionSetMap.put(ENTITY_TYPE.CLUSTER, IActionSetIDs.ACTION_SET_CLUSTER); + actionSetMap.put(ENTITY_TYPE.VOLUMES, IActionSetIDs.ACTION_SET_VOLUMES); + actionSetMap.put(ENTITY_TYPE.VOLUME, IActionSetIDs.ACTION_SET_VOLUME); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVERS, IActionSetIDs.ACTION_SET_GLUSTER_SERVERS); + actionSetMap.put(ENTITY_TYPE.GLUSTER_SERVER, IActionSetIDs.ACTION_SET_GLUSTER_SERVER); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVERS, IActionSetIDs.ACTION_SET_DISCOVERED_SERVERS); + actionSetMap.put(ENTITY_TYPE.DISCOVERED_SERVER, IActionSetIDs.ACTION_SET_DISCOVERED_SERVER); + + return actionSetMap; + } + + public GlusterToolbarManager(IWorkbenchWindow window) { + this.window = window; + } + + @SuppressWarnings("rawtypes") + private ENTITY_TYPE getEntityType(Entity entity) { + if (entity instanceof EntityGroup) { + EntityGroup entityGroup = (EntityGroup) entity; + if (entityGroup.getEntityType() == Volume.class) { + return ENTITY_TYPE.VOLUMES; + } else if (entityGroup.getEntityType() == GlusterServer.class) { + return ENTITY_TYPE.GLUSTER_SERVERS; + } else { + return ENTITY_TYPE.DISCOVERED_SERVERS; + } + } + + return entityTypeMap.get(entity.getClass()); + } + + @Override + public void updateToolbar(Entity entity) { + ENTITY_TYPE entityType = getEntityType(entity); + IWorkbenchPage page = window.getActivePage(); + + for (ENTITY_TYPE targetEntityType : actionSetMap.keySet()) { + String actionSetId = actionSetMap.get(targetEntityType); + if (entityType == targetEntityType) { + // show only the action set mapped to given entity + page.showActionSet(actionSetId); + } else { + page.hideActionSet(actionSetId); + } + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java new file mode 100644 index 00000000..f68346d6 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/toolbar/ToolbarManager.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.toolbar; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Whenever the current selection/action demands changes to the toolbar, the toolbar manager is used to update the + * toolbar. + */ +public interface ToolbarManager { + /** + * Updates the toolbar for given entity. This typically means that user is working with the given entity, and hence + * the toolbar actions related to that entity should be made visible, and other un-related actions should be hidden. + * + * @param entity + */ + public void updateToolbar(Entity entity); +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java new file mode 100644 index 00000000..9cbf6664 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/EntityViewerFilter.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.utils; + +import java.util.Map.Entry; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import com.gluster.storage.management.core.model.Filterable; +import com.gluster.storage.management.core.utils.StringUtil; + +public class EntityViewerFilter extends ViewerFilter { + + private String filterString; + private boolean caseSensitive = false; + + public EntityViewerFilter(String filterString, boolean caseSensitive) { + this.filterString = filterString; + this.caseSensitive = caseSensitive; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public String getFilterString() { + return filterString; + } + + public void setFilterString(String filterString) { + this.filterString = filterString; + } + + @SuppressWarnings("unchecked") + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (filterString == null || filterString.isEmpty()) { + // No filter string. select everything + return true; + } + + if (element instanceof Filterable) { + return ((Filterable) element).filter(filterString, caseSensitive); + } + + if(element instanceof Entry) { + Entry<String, String> entry = (Entry<String, String>)element; + return StringUtil.filterString(entry.getKey() + entry.getValue(), filterString, caseSensitive); + } + + if(element instanceof String) { + return StringUtil.filterString((String)element, filterString, caseSensitive); + } + + return false; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java new file mode 100644 index 00000000..ccd5d8ec --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java @@ -0,0 +1,363 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.utils; + +import java.util.Iterator; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuCreator; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnLayoutData; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.events.ExpansionAdapter; +import org.eclipse.ui.forms.events.ExpansionEvent; +import org.eclipse.ui.forms.widgets.ColumnLayout; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.views.NavigationView; + +public class GUIHelper { + private static final GUIHelper instance = new GUIHelper(); + private static final ImageUtil imageUtil = new ImageUtil(); + + private GUIHelper() { + + } + + public static GUIHelper getInstance() { + return instance; + } + + public ScrolledForm setupForm(Composite parent, FormToolkit toolkit, final String formName) { + return setupForm(toolkit, formName, toolkit.createScrolledForm(parent)); + } + + public ScrolledForm setupForm(FormToolkit toolkit, final String formName, ScrolledForm form) { + form.setText(formName); + toolkit.decorateFormHeading(form.getForm()); + + ColumnLayout layout = new ColumnLayout(); + + // layout.topMargin = 0; + // layout.bottomMargin = 5; + // layout.leftMargin = 10; + // layout.rightMargin = 10; + // layout.horizontalSpacing = 10; + // layout.verticalSpacing = 10; + // layout.maxNumColumns = 4; + // layout.minNumColumns = 1; + + form.getBody().setLayout(layout); + return form; + } + + public Composite createSection(final ScrolledForm form, FormToolkit toolkit, String title, String desc, + int numColumns, boolean collapsible) { + int style = Section.TITLE_BAR | Section.EXPANDED; + if (desc != null && !desc.isEmpty()) { + style |= Section.DESCRIPTION; + } + if (collapsible) { + style |= Section.TWISTIE; + } + + Section section = toolkit.createSection(form.getBody(), style); + section.setText(title); + section.setDescription(desc); + + // toolkit.createCompositeSeparator(section); + Composite client = toolkit.createComposite(section); + GridLayout layout = new GridLayout(); + layout.marginWidth = layout.marginHeight = 0; + layout.numColumns = numColumns; + layout.verticalSpacing = 15; + layout.marginBottom = 20; + layout.marginTop = 5; + + client.setLayout(layout); + section.setClient(client); + + section.addExpansionListener(new ExpansionAdapter() { + public void expansionStateChanged(ExpansionEvent e) { + form.reflow(false); + } + }); + return client; + } + + public Composite createTab(TabFolder tabFolder, String title, String imageKey) { + TabItem item = new TabItem(tabFolder, SWT.NONE); + item.setText(title); + item.setImage(getImage(imageKey)); + + Composite composite = new Composite(tabFolder, SWT.NONE); + composite.setLayout(new FillLayout()); + + item.setControl(composite); + + return composite; + } + + public ImageDescriptor getImageDescriptor(String imagePath) { + return imageUtil.getImageDescriptor(imagePath); + } + + public Image getImage(String imagePath) { + return imageUtil.getImage(imagePath); + } + + public Action createPullDownMenu(String menuName, String iconPath, final MenuManager menuManager) { + Action action = new Action(menuName, IAction.AS_DROP_DOWN_MENU) { + public void run() { + } + }; + action.setMenuCreator(new IMenuCreator() { + + @Override + public Menu getMenu(Menu menu) { + return null; + } + + @Override + public Menu getMenu(Control control) { + return menuManager.createContextMenu(control); + } + + @Override + public void dispose() { + } + }); + action.setImageDescriptor(getImageDescriptor(iconPath)); + return action; + } + + public TableColumnLayout createTableColumnLayout(Table table, String[] columns) { + TableColumnLayout tableColumnLayout = new TableColumnLayout(); + ColumnLayoutData defaultColumnLayoutData = new ColumnWeightData(100); + + for (String columnName : columns) { + TableColumn column = new TableColumn(table, SWT.LEFT); + column.setText(columnName); + + tableColumnLayout.setColumnData(column, defaultColumnLayoutData); + } + + return tableColumnLayout; + } + + /** + * Creates a filter for given structured viewer that will filter the contents of the viewer based on the current + * text of the text field + * + * @param viewer + * Structured viewer for which the filter is to be created + * @param filterText + * The text field whose contents are to be used for filtering + * @param caseSensitive + * Flag indicating whether the filtering should be case sensitive + * @return The newly created filter + */ + public EntityViewerFilter createFilter(final StructuredViewer viewer, final Text filterText, boolean caseSensitive) { + final String initialFilterString = filterText.getText(); + + final EntityViewerFilter filter = new EntityViewerFilter(initialFilterString, caseSensitive); + // On every keystroke inside the text field, update the filter string + filterText.addKeyListener(new KeyAdapter() { + private String filterString = initialFilterString; + + @Override + public void keyReleased(KeyEvent e) { + String enteredString = filterText.getText(); + if (enteredString.equals(filterString)) { + // Filter string has not changed. don't do anything + return; + } + + // Update filter string + filterString = enteredString; + filter.setFilterString(filterString); + + // Refresh viewer with newly filtered content + viewer.refresh(true); + } + }); + + viewer.addFilter(filter); + return filter; + } + + public IViewPart getView(String viewId) { + IViewReference[] views = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getViewReferences(); + for (IViewReference view : views) { + if (view.getId().equals(viewId)) { + return view.getView(false); + } + } + return null; + } + + public ControlDecoration createErrorDecoration(Control control) { + ControlDecoration passwordErrorDecoration = new ControlDecoration(control, SWT.LEFT | SWT.TOP); + passwordErrorDecoration.setImage(FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage()); + return passwordErrorDecoration; + } + + public void centerShellInScreen(Shell shell) { + Rectangle monitorBounds = shell.getMonitor().getBounds(); + Rectangle myBounds = shell.getBounds(); + + int x = monitorBounds.x + (monitorBounds.width - myBounds.width) / 2; + int y = monitorBounds.y + (monitorBounds.height - myBounds.height) / 2; + shell.setLocation(x, y); + } + + public Text createFilterText(FormToolkit toolkit, Composite parent) { + final String tooltipMessage = "Start typing to filter table contents."; + final Text filterText = toolkit.createText(parent, "", SWT.FLAT); + + GridData data = new GridData(SWT.LEFT, SWT.CENTER, false, false); + data.widthHint = 300; + filterText.setLayoutData(data); + + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.RIGHT); + searchDecoration.setImage(getImage(IImageKeys.SEARCH)); + searchDecoration.show(); + searchDecoration.setShowHover(true); + searchDecoration.setDescriptionText(tooltipMessage); + + filterText.setToolTipText(tooltipMessage); + return filterText; + } + + public Text createFilterText(Composite parent) { + final String tooltipMessage = "Start typing to filter table contents."; + final Text filterText = new Text(parent, SWT.FLAT); + + GridData data = new GridData(SWT.LEFT, SWT.CENTER, false, false); + data.widthHint = 300; + filterText.setLayoutData(data); + + ControlDecoration searchDecoration = new ControlDecoration(filterText, SWT.RIGHT); + searchDecoration.setImage(getImage(IImageKeys.SEARCH)); + searchDecoration.show(); + searchDecoration.setShowHover(true); + searchDecoration.setDescriptionText(tooltipMessage); + + filterText.setToolTipText(tooltipMessage); + return filterText; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, int columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + * + * @return The table viewer column created + */ + public TableViewerColumn setColumnProperties(TableViewer tableViewer, int columnIndex, int style, int weight) { + TableViewerColumn column = new TableViewerColumn(tableViewer, style, columnIndex); + TableColumnLayout tableColumnLayout = (TableColumnLayout) tableViewer.getTable().getParent().getLayout(); + tableColumnLayout.setColumnData(column.getColumn(), new ColumnWeightData(weight)); + column.setLabelProvider(new ColumnLabelProvider()); + return column; + } + + /** + * Fetches the currently selected objects from the workbench site and returns the one of given type. If none of the + * selected objects are of given type, returns null + * + * @param site + * The workbench site + * @param expectedType + * Type of the selected object to look for + * @return The selected object of given type if found, else null + */ + public Object getSelectedEntity(IWorkbenchSite site, Class expectedType) { + ISelection selection = site.getWorkbenchWindow().getSelectionService().getSelection(NavigationView.ID); + if (selection instanceof IStructuredSelection) { + Iterator<Object> iter = ((IStructuredSelection) selection).iterator(); + while (iter.hasNext()) { + Object selectedObj = iter.next(); + if (selectedObj.getClass() == expectedType) { + return selectedObj; + } + } + } + return null; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java new file mode 100644 index 00000000..efa169de --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ImageUtil.java @@ -0,0 +1,51 @@ +/** + * ImageUtil.java + * + * Copyright (c) 2011 Gluster, Inc. <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.utils; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.gui.Application; + +/** + * + */ +public class ImageUtil { + private static final LRUCache<String, Image> imageCache = new LRUCache<String, Image>(20); + + public ImageDescriptor getImageDescriptor(String imagePath) { + return AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, imagePath); + } + + public synchronized Image getImage(String imagePath) { + if(imageCache.containsKey(imagePath)) { + return imageCache.get(imagePath); + } + return createImage(imagePath); + } + + private Image createImage(String imagePath) { + Image image = getImageDescriptor(imagePath).createImage(); + imageCache.put(imagePath, image); + return image; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java new file mode 100644 index 00000000..3c805ac8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/LRUCache.java @@ -0,0 +1,55 @@ +/** + * LRUCache.java + * + * Copyright (c) 2011 Gluster, Inc. <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.utils; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * An LRU cache, based on <code>LinkedHashMap</code>. + * <p> + * This cache has a fixed maximum number of elements (<code>cacheSize</code>). If the cache is full and another entry is + * added, the LRU (least recently used) entry is dropped. + * + */ +public class LRUCache<K, V> extends LinkedHashMap<K, V> { + + private static final long serialVersionUID = 1L; + private static final float loadFactor = 0.75f; + private int cacheSize; + + /** + * Creates a new LRU cache. + * + * @param cacheSize + * the maximum number of entries that will be kept in this cache. + */ + public LRUCache(int cacheSize) { + super((int) Math.ceil(cacheSize / loadFactor) + 1, loadFactor, true); + this.cacheSize = cacheSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { + return size() > cacheSize; + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java new file mode 100644 index 00000000..fd76c6e5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/validators/StringRequiredValidator.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.validators; + +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.swt.widgets.Control; + +public class StringRequiredValidator implements IValidator { + private final String errorText; + private final ControlDecoration controlDecoration; + private final Control linkedControl; + + public StringRequiredValidator(String errorText, ControlDecoration controlDecoration, Control linkedControl) { + super(); + this.errorText = errorText; + this.controlDecoration = controlDecoration; + this.linkedControl = linkedControl; + } + + public StringRequiredValidator(String errorText, ControlDecoration controlDecoration) { + this(errorText, controlDecoration, null); + } + + public IStatus validate(Object value) { + if (value instanceof String) { + if (((String) value).isEmpty()) { + controlDecoration.setDescriptionText(errorText); + controlDecoration.show(); + if (linkedControl != null) { + linkedControl.setEnabled(false); + } + return ValidationStatus.error(errorText); + } + } + linkedControl.setEnabled(true); + controlDecoration.hide(); + return Status.OK_STATUS; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java new file mode 100644 index 00000000..b2d2b93a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java @@ -0,0 +1,155 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * @author root + * + */ +public class ClusterSummaryView extends ViewPart { + public static final String ID = ClusterSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Cluster cluster; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (cluster == null) { + //cluster = (Cluster)guiHelper.getSelectedEntity(getSite(), Cluster.class); + cluster = (Cluster)GlusterDataModelManager.getInstance().getModel().getChildren().get(0); + } + + createSections(parent); + } + + private int getVolumeCountByStatus(Cluster cluster, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : cluster.getVolumes()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + private int getServerCountByStatus(Cluster cluster, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createVolumesSection() { + Composite section = guiHelper.createSection(form, toolkit, "Volumes", null, 1, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createServersSection() { + Composite section = guiHelper.createSection(form, toolkit, "Servers", null, 1, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.OFFLINE)) }; + + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + private void createActionsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Actions", null, 1, false); + + ImageHyperlink imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Create Volume"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.CREATE_VOLUME_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + + imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Add Server(s)"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.ADD_SERVER_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Cluster Summary"); + + createVolumesSection(); + createServersSection(); + createActionsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java new file mode 100644 index 00000000..efdb6457 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DetailsView.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.views.details.TabCreatorFactory; +import com.gluster.storage.management.gui.views.details.TabCreatorFactoryImpl; + +/** + * This view is displayed on the right hand side of the platform UI. It updates itself with appropriate tabs + * whenever selection changes on the navigation view (cluster tree) on the left hand side of the UI. + */ +public class DetailsView extends ViewPart implements ISelectionListener { + public static final String ID = DetailsView.class.getName(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TabFolder tabFolder; + private Entity entity; + private TabCreatorFactory tabCreatorFactory = new TabCreatorFactoryImpl(); + private GlusterToolbarManager toolbarManager; + private IWorkbenchPartSite site; + + public DetailsView() { + super(); + } + + @Override + public void createPartControl(final Composite parent) { + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + tabFolder = new TabFolder(parent, SWT.TOP); + + // listen to selection event on the navigation tree view + IWorkbenchWindow window = getViewSite().getWorkbenchWindow(); + window.getSelectionService().addSelectionListener(this); + + // Create the toolbar manager + toolbarManager = new GlusterToolbarManager(window); + site = getSite(); + } + + @Override + public void setFocus() { + tabFolder.setFocus(); + } + + private void removeAllTabs() { + for (TabItem item : tabFolder.getItems()) { + item.getControl().dispose(); + item.dispose(); + } + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (entity == selectedEntity || selectedEntity == null) { + // entity selection has not changed. do nothing. + return; + } + + entity = selectedEntity; + removeAllTabs(); + + // Create tabs for newly selected entity + tabCreatorFactory.getTabCreator(entity).createTabs(entity, tabFolder, toolkit, site); + + // update toolbar buttons visibility based on selected entity + toolbarManager.updateToolbar(entity); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java new file mode 100644 index 00000000..e13912c6 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServerView.java @@ -0,0 +1,90 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; + +/** + * @author root + * + */ +public class DiscoveredServerView extends ViewPart { + public static final String ID = DiscoveredServerView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Server server; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (Server) guiHelper.getSelectedEntity(getSite(), Server.class); + } + createSections(parent); + } + + private void createServerSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + server.getTotalMemory(), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(server.getTotalDiskSpace()), SWT.NONE); + } + + private void createSections(Composite parent) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(); + + parent.layout(); // IMP: lays out the form properly + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java new file mode 100644 index 00000000..69c506f4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DiscoveredServersView.java @@ -0,0 +1,109 @@ +/** + * DiscoveredServersView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage; + +/** + * + */ +public class DiscoveredServersView extends ViewPart implements IDoubleClickListener, ISelectionListener { + public static final String ID = DiscoveredServersView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup<Server> servers; + private ServersPage page; + + public DiscoveredServersView() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Server.class) { + servers = (EntityGroup<Server>)selectedObj; + } + } + + page = new ServersPage(parent, getSite(), servers); + page.addDoubleClickListener(this); + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(NavigationView.ID, this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, + * org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (servers == selectedEntity || selectedEntity == null || !(selectedEntity instanceof EntityGroup) + || ((EntityGroup) selectedEntity).getEntityType() != Server.class) { + // entity selection has not changed. do nothing. + return; + } + + servers = (EntityGroup<Server>) selectedEntity; + page.setInput(servers); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java new file mode 100644 index 00000000..260d0d4c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/DisksView.java @@ -0,0 +1,44 @@ +package com.gluster.storage.management.gui.views; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; + +public class DisksView extends ViewPart { + public static final String ID = DisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup<GlusterServer> servers; + private DisksPage page; + + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup<GlusterServer>)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + page = new DisksPage(parent, SWT.NONE, getSite(), getAllDisks(servers)); + page.layout(); // IMP: lays out the form properly + } + + private List<Disk> getAllDisks(EntityGroup<GlusterServer> servers) { + List<Disk> disks = new ArrayList<Disk>(); + for(GlusterServer server : (List<GlusterServer>)servers.getEntities()) { + disks.addAll(server.getDisks()); + } + return disks; + } + + @Override + public void setFocus() { + page.setFocus(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java new file mode 100644 index 00000000..624d968d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerDisksView.java @@ -0,0 +1,57 @@ +/** + * GlusterServerDisksView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage; + +public class GlusterServerDisksView extends ViewPart { + public static final String ID = GlusterServerDisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private GlusterServer server; + private ServerDisksPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + page = new ServerDisksPage(parent, SWT.NONE, getSite(), server.getDisks()); + + parent.layout(); // IMP: lays out the form properly + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java new file mode 100644 index 00000000..acc8144d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerLogsView.java @@ -0,0 +1,59 @@ +/** + * GlusterServerLogsView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerLogsPage; + +public class GlusterServerLogsView extends ViewPart { + public static final String ID = GlusterServerLogsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private GlusterServer server; + private ServerLogsPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + + page = new ServerLogsPage(parent, SWT.NONE, server); + + parent.layout(); // IMP: lays out the form properly + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java new file mode 100644 index 00000000..42a14dd4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java @@ -0,0 +1,246 @@ +/** + * GlusterServerSummaryView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.richclientgui.toolbox.gauges.CoolGauge; + +public class GlusterServerSummaryView extends ViewPart { + public static final String ID = GlusterServerSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private GlusterServer server; + + public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { + INTERFACE, IP_ADDRESS, NETMASK, GATEWAY + }; + + private static final String[] NETWORK_INTERFACE_TABLE_COLUMN_NAMES = { "Interface", "IP Address", "Netmask", + "Gateway" }; + + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (GlusterServer) guiHelper.getSelectedEntity(getSite(), GlusterServer.class); + } + createSections(parent); + } + + private void createSections(Composite parent) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + if (server.getStatus() == SERVER_STATUS.ONLINE) { + Composite section = createNetworkInterfacesSection(server, toolkit, form); + } + + parent.layout(); // IMP: lays out the form properly + } + + private void createServerSummarySection(GlusterServer server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + // toolkit.createLabel(section, "Preferred Network: ", SWT.NONE); + // toolkit.createLabel(section, server.getPreferredNetworkInterface().getName(), SWT.NONE); + + boolean online = server.getStatus() == SERVER_STATUS.ONLINE; + + if (online) { + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + // toolkit.createLabel(section, "CPU Usage (%): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getCpuUsage() : "NA", SWT.NONE); + + toolkit.createLabel(section, "% CPU Usage (avg): ", SWT.NONE); + CoolGauge gauge = new CoolGauge(section, guiHelper.getImage(IImageKeys.GAUGE_SMALL)); + gauge.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); + gauge.setGaugeNeedleColour(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + gauge.setGaugeNeedleWidth(2); + gauge.setGaugeNeedlePivot(new Point(66, 65)); + + gauge.setPoints(getPnts()); + gauge.setLevel(server.getCpuUsage() / 100); + gauge.setToolTipText(server.getCpuUsage() + "%"); + + toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + ProgressBar memoryUsageBar = new ProgressBar(section, SWT.SMOOTH); + memoryUsageBar.setMinimum(0); + memoryUsageBar.setMaximum((int) Math.round(server.getTotalMemory())); + memoryUsageBar.setSelection((int) Math.round(server.getMemoryInUse())); + memoryUsageBar.setToolTipText("Total: " + server.getTotalMemory() + "GB, In Use: " + + server.getMemoryInUse() + "GB"); + + // toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + // final CoolProgressBar bar = new CoolProgressBar(section,SWT.HORIZONTAL, + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_LEFT), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_FILLED), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_EMPTY), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_RIGHT)); + // bar.updateProgress(server.getMemoryInUse() / server.getTotalMemory()); + + // toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getTotalDiskSpace() : "NA", SWT.NONE); + // + // toolkit.createLabel(section, "Disk Space in Use (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getDiskSpaceInUse() : "NA", SWT.NONE); + + toolkit.createLabel(section, "Disk Usage: ", SWT.NONE); + ProgressBar diskUsageBar = new ProgressBar(section, SWT.SMOOTH); + diskUsageBar.setMinimum(0); + diskUsageBar.setMaximum((int) Math.round(server.getTotalDiskSpace())); + diskUsageBar.setSelection((int) Math.round(server.getDiskSpaceInUse())); + diskUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber(server.getTotalDiskSpace()) + + "GB, In Use: " + NumberUtil.formatNumber(server.getDiskSpaceInUse()) + "GB"); + } + + toolkit.createLabel(section, "Status: ", SWT.NONE); + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(server.getStatusStr()); + lblStatusValue.setImage(server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + toolkit.adapt(lblStatusValue, true, true); + } + + private List<Point> getPnts() { + final List<Point> pnts = new ArrayList<Point>(); + pnts.add(new Point(47, 98)); + pnts.add(new Point(34, 84)); + pnts.add(new Point(29, 65)); + pnts.add(new Point(33, 48)); + pnts.add(new Point(48, 33)); + pnts.add(new Point(66, 28)); + pnts.add(new Point(83, 32)); + pnts.add(new Point(98, 47)); + pnts.add(new Point(103, 65)); + pnts.add(new Point(98, 83)); + pnts.add(new Point(84, 98)); + return pnts; + } + + private Composite createNetworkInterfacesSection(GlusterServer server, FormToolkit toolkit, ScrolledForm form) { + final Composite section = guiHelper.createSection(form, toolkit, "Network Interfaces", null, 1, false); + createNetworkInterfacesTableViewer(createTableViewerComposite(section), server); + // Hyperlink changePreferredNetworkLink = toolkit.createHyperlink(section, "Change Preferred Network", + // SWT.NONE); + // changePreferredNetworkLink.addHyperlinkListener(new HyperlinkAdapter() { + // + // @Override + // public void linkActivated(HyperlinkEvent e) { + // new MessageDialog( + // section.getShell(), + // "Gluster Storage Platform", + // guiHelper.getImage(IImageKeys.SERVER), + // "This will show additional controls to help user choose a new network interface. TO BE IMPLEMENTED.", + // MessageDialog.INFORMATION, new String[] { "OK" }, 0).open(); + // } + // }); + return section; + } + + private TableViewer createNetworkInterfacesTableViewer(final Composite parent, GlusterServer server) { + TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new NetworkInterfaceTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupNetworkInterfaceTable(parent, tableViewer.getTable()); + tableViewer.setInput(server.getNetworkInterfaces().toArray()); + + return tableViewer; + } + + private void setupNetworkInterfaceTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, + NETWORK_INTERFACE_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.IP_ADDRESS, SWT.CENTER, 100); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.NETMASK, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.GATEWAY, SWT.CENTER, 70); + // setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED, SWT.CENTER, 70); + } + + private Composite createTableViewerComposite(Composite parent) { + Composite tableViewerComposite = new Composite(parent, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData tableLayoutData = new GridData(SWT.FILL, SWT.FILL, true, false); + tableLayoutData.widthHint = 400; + tableLayoutData.minimumWidth = 400; + // tableLayoutData.grabExcessHorizontalSpace = true; + tableViewerComposite.setLayoutData(tableLayoutData); + return tableViewerComposite; + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES columnIndex, int alignment, + int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + @Override + public void setFocus() { + form.setFocus(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java new file mode 100644 index 00000000..428e55d5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersSummaryView.java @@ -0,0 +1,123 @@ +/** + * GlusterServersSummaryView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * + */ +public class GlusterServersSummaryView extends ViewPart { + public static final String ID = GlusterServersSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private EntityGroup<GlusterServer> servers; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup<GlusterServer>)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + createSections(parent); + } + + /** + * @param parent + */ + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Volumes - Summary"); + + createSummarySection(); + createRunningTasksSection(); + createAlertsSection(); + + + parent.layout(); // IMP: lays out the form properly + } + + private void createSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.OFFLINE)) }; + createStatusChart(section, values); + } + + private int getServerCountByStatus(EntityGroup<GlusterServer> servers, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : (List<GlusterServer>)servers.getEntities()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createStatusChart(Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + + private void createAlertsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to servers\nwill be displayed here."); + } + + private void createRunningTasksSection() { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nservers will be displayed here."); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + form.setFocus(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java new file mode 100644 index 00000000..06b1e282 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServersView.java @@ -0,0 +1,77 @@ +/** + * GlusterServersView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.GlusterServersPage; + +/** + * @author root + * + */ +public class GlusterServersView extends ViewPart implements IDoubleClickListener { + public static final String ID = GlusterServersView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup<GlusterServer> servers; + private GlusterServersPage page; + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (servers == null) { + servers = (EntityGroup<GlusterServer>)guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + } + + page = new GlusterServersPage(parent, SWT.NONE, servers); + page.addDoubleClickListener(this); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) + */ + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java new file mode 100644 index 00000000..2b2645fc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java @@ -0,0 +1,130 @@ +/** + * GlusterViewsManager.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; + +/** + * @see ViewsManager + */ +public class GlusterViewsManager implements ViewsManager { + private IWorkbenchPage page; + + public GlusterViewsManager(IWorkbenchPage page) { + this.page = page; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.ViewsManager#updateViews(com.gluster.storage.management.core.model.Entity) + */ + @Override + public void updateViews(Entity entity) { + closeAllViews(); + + + try { + if (entity instanceof EntityGroup) { + showViewsForEntityGroup((EntityGroup)entity); + } else if (entity.getClass() == Server.class) { + showViewsForDiscoveredServer((Server)entity); + } else if (entity.getClass() == GlusterServer.class) { + showViewsForGlusterServer((GlusterServer)entity); + } else if (entity instanceof Volume) { + showViewsForVolume((Volume)entity); + } else if (entity instanceof Cluster) { + showViewsForCluster((Cluster)entity); + } + } catch (PartInitException e) { + e.printStackTrace(); + } + } + + /** + * + */ + private void closeAllViews() { + IViewReference[] viewReferences = page.getViewReferences(); + for (final IViewReference viewReference : viewReferences) { + if (!viewReference.getId().equals(NavigationView.ID)) { + page.hideView(viewReference); + } + } + } + + private void showViewsForCluster(Cluster cluster) throws PartInitException { + page.showView(ClusterSummaryView.ID); + } + + private void showViewsForVolume(Volume volume) throws PartInitException { + page.showView(VolumeSummaryView.ID); + page.showView(VolumeDisksView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(VolumeOptionsView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(VolumeLogsView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewsForGlusterServer(GlusterServer server) throws PartInitException { + page.showView(GlusterServerSummaryView.ID); + if (server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE) { + page.showView(GlusterServerDisksView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(GlusterServerLogsView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + } + + private void showViewsForDiscoveredServer(Server server) throws PartInitException { + page.showView(DiscoveredServerView.ID); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private void showViewsForEntityGroup(EntityGroup entityGroup) throws PartInitException { + Class entityType = entityGroup.getEntityType(); + if (entityType == Server.class) { + showViewForServers(entityGroup); + } else if (entityType == Volume.class) { + showViewsForVolumes(entityGroup); + } else if (entityType == GlusterServer.class) { + showViewsForGlusterServers(entityGroup); + } + } + + private void showViewsForGlusterServers(EntityGroup<GlusterServer> server) throws PartInitException { + page.showView(GlusterServersSummaryView.ID); + page.showView(GlusterServersView.ID, null, IWorkbenchPage.VIEW_CREATE); + page.showView(DisksView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewsForVolumes(EntityGroup<Volume> volumes) throws PartInitException { + page.showView(VolumesSummaryView.ID); + page.showView(VolumesView.ID, null, IWorkbenchPage.VIEW_CREATE); + } + + private void showViewForServers(EntityGroup<Server> servers) throws PartInitException { + page.showView(DiscoveredServersView.ID); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java new file mode 100644 index 00000000..4de5b61a --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.model.BaseWorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.views.navigator.ClusterAdapterFactory; + +public class NavigationView extends ViewPart implements ISelectionListener { + public static final String ID = NavigationView.class.getName(); + private GlusterDataModel model; + private TreeViewer treeViewer; + private IAdapterFactory adapterFactory = new ClusterAdapterFactory(); + private GlusterToolbarManager toolbarManager; + private Entity entity; + private GlusterViewsManager viewsManager; + + @Override + public void createPartControl(Composite parent) { + createNavigationTree(parent); + + // Create the views and toolbar managers + toolbarManager = new GlusterToolbarManager(getSite().getWorkbenchWindow()); + viewsManager = new GlusterViewsManager(getSite().getPage()); + + // listen to selection events to update views/toolbar accordingly + getSite().getPage().addSelectionListener(this); + } + + private void createNavigationTree(Composite parent) { + model = GlusterDataModelManager.getInstance().getModel(); + + Platform.getAdapterManager().registerAdapters(adapterFactory, Entity.class); + treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + treeViewer.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider()); + treeViewer.setContentProvider(new BaseWorkbenchContentProvider()); + treeViewer.setInput(model); + treeViewer.expandAll(); + // select the first element by default + treeViewer.setSelection(new StructuredSelection(model.getChildren().get(0))); + + setupContextMenu(); + + // register as selection provider so that other views can listen to any selection events on the tree + getSite().setSelectionProvider(treeViewer); + + // Refresh the navigation tree whenever there is a change to the data model + GlusterDataModelManager.getInstance().addClusterListener(new DefaultClusterListener() { + public void clusterChanged() { + treeViewer.refresh(); + } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + selectEntity(volume); // this makes sure that the toolbar buttons get updated accoring to new status + } + + @Override + public void volumeCreated(Volume volume) { + super.volumeCreated(volume); + selectEntity(volume); + } + }); + } + + private void setupContextMenu() { + MenuManager menuManager = new MenuManager("&Gluster", "gluster.context.menu"); + Menu contextMenu = menuManager.createContextMenu(treeViewer.getControl()); + treeViewer.getTree().setMenu(contextMenu); + getSite().registerContextMenu(menuManager, treeViewer); + } + + public void selectEntity(Entity entity) { + treeViewer.setSelection(new StructuredSelection(entity)); + treeViewer.reveal(entity); + setFocus(); // this ensures that the "selection changed" event gets fired + } + + @Override + public void setFocus() { + treeViewer.getControl().setFocus(); + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (selectedEntity != null && selectedEntity != entity) { + entity = selectedEntity; + + // update views and toolbar buttons visibility based on selected entity + viewsManager.updateViews(entity); + toolbarManager.updateToolbar(entity); + + // Opening of other views may cause navigation tree to lose focus; get it back. + setFocus(); + } + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java new file mode 100644 index 00000000..2b33308e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ViewsManager.java @@ -0,0 +1,38 @@ +/** + * ViewsManager.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import com.gluster.storage.management.core.model.Entity; + +/** + * Whenever the current selection/action demands opening different set of views, the views manager is used to open + * appropriate views. + */ +public interface ViewsManager { + /** + * Updates the views for given entity. This typically means that user is working with the given entity, and hence + * the views related to that entity should be made visible, and other un-related views should be hidden. + * + * @param entity + * The entity for which views are to be updated + */ + public void updateViews(Entity entity); +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java new file mode 100644 index 00000000..cbf6736b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeDisksView.java @@ -0,0 +1,39 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; + +public class VolumeDisksView extends ViewPart { + public static final String ID = VolumeDisksView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private DisksPage page; + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + /** + * @param parent + */ + private void createPage(Composite parent) { + page = new DisksPage(parent, SWT.NONE, getSite(), volume.getDisks()); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java new file mode 100644 index 00000000..b6c98ad3 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeLogsView.java @@ -0,0 +1,35 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage; + +public class VolumeLogsView extends ViewPart { + VolumeLogsPage logsPage; + public static final String ID = VolumeLogsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + private void createPage(Composite parent) { + logsPage = new VolumeLogsPage(parent, SWT.NONE, volume); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + logsPage.setFocus(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java new file mode 100644 index 00000000..e8695737 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeOptionsView.java @@ -0,0 +1,36 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage; + +public class VolumeOptionsView extends ViewPart { + public static final String ID = VolumeOptionsView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private VolumeOptionsPage page; + private Volume volume; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createPage(parent); + } + + private void createPage(Composite parent) { + page = new VolumeOptionsPage(parent, SWT.NONE, volume); + parent.layout(); // IMP: lays out the form properly + } + + @Override + public void setFocus() { + page.setFocus(); + } +} + diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java new file mode 100644 index 00000000..798c2a40 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java @@ -0,0 +1,270 @@ +package com.gluster.storage.management.gui.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumeSummaryView extends ViewPart { + public static final String ID = VolumeSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Volume volume; + private CLabel lblStatusValue; + private DefaultClusterListener volumeChangedListener; + + @Override + public void createPartControl(Composite parent) { + if (volume == null) { + volume = (Volume) guiHelper.getSelectedEntity(getSite(), Volume.class); + } + + createSections(parent); + + // Refresh the navigation tree whenever there is a change to the data model + volumeChangedListener = new DefaultClusterListener() { + @Override + public void volumeChanged(Volume volume, Event event) { + if(event.getEventType() == EVENT_TYPE.VOLUME_STATUS_CHANGED) { + updateVolumeStatusLabel(); + new GlusterToolbarManager(getSite().getWorkbenchWindow()).updateToolbar(volume); + } + } + }; + GlusterDataModelManager.getInstance().addClusterListener(volumeChangedListener); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#dispose() + */ + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(volumeChangedListener); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Volume Properties [" + volume.getName() + "]"); + + createVolumePropertiesSection(); + createVolumeMountingInfoSection(); + createVolumeAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createVolumeAlertsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 3, false); + toolkit.createLabel(section, "Volume related alerts will be displayed here"); + } + + private void createVolumeMountingInfoSection() { + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 3, false); + toolkit.createLabel(section, "Information about mounting the\nvolume will be printed here"); + } + + /** + * + */ + private void createVolumePropertiesSection() { + Composite section = guiHelper.createSection(form, toolkit, "Properties", null, 3, false); + + createVolumeTypeField(section); + + VOLUME_TYPE volumeType = volume.getVolumeType(); + if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + createReplicaCountField(section); + } + + if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + createStripeCountField(section); + } + + createNumOfDisksField(section); + createDiskSpaceField(section); + createTransportTypeField(section); + createNASProtocolField(section); + createAccessControlField(section); + createStatusField(section); + } + + private GridData createDefaultLayoutData() { + GridData layoutData = new GridData(); + layoutData.minimumWidth = 150; + layoutData.widthHint = 150; + return layoutData; + } + + private void createAccessControlField(Composite section) { + toolkit.createLabel(section, "Access Control: ", SWT.NONE); + Text accessControlText = toolkit.createText(section, volume.getAccessControlList()); + accessControlText.setLayoutData(createDefaultLayoutData()); + accessControlText.setEnabled(false); + createChangeLinkForAccessControl(section, accessControlText); + } + + private void createChangeLinkForAccessControl(Composite section, final Text accessControlText) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + // TODO: Validation of entered text + volume.setAccessControlList(accessControlText.getText()); + accessControlText.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + accessControlText.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (accessControlText.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void createNASProtocolField(Composite section) { + toolkit.createLabel(section, "NAS Protocols: ", SWT.NONE); + + Composite nasProtocolsComposite = toolkit.createComposite(section); + nasProtocolsComposite.setLayout(new FillLayout()); + + createCheckbox(nasProtocolsComposite, "Gluster", true); + final Button nfsCheckBox = createCheckbox(nasProtocolsComposite, "NFS", + volume.getNASProtocols().contains(NAS_PROTOCOL.NFS)); + + createChangeLinkForNASProtocol(section, nfsCheckBox); + } + + private Button createCheckbox(Composite parent, String label, boolean selected) { + final Button checkBox = toolkit.createButton(parent, label, SWT.CHECK); + checkBox.setEnabled(false); + checkBox.setSelection(selected); + return checkBox; + } + + private void createChangeLinkForNASProtocol(Composite section, final Button nfsCheckBox) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + if (nfsCheckBox.getSelection()) { + volume.enableNFS(); + } else { + volume.disableNFS(); + } + nfsCheckBox.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + nfsCheckBox.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (nfsCheckBox.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void createDiskSpaceField(Composite section) { + Label diskSpaceLabel = toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + diskSpaceLabel.setToolTipText("<b>bold</b>normal"); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(volume.getTotalDiskSpace()), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStatusField(Composite section) { + toolkit.createLabel(section, "Status: ", SWT.NONE); + + lblStatusValue = new CLabel(section, SWT.NONE); + updateVolumeStatusLabel(); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void updateVolumeStatusLabel() { + lblStatusValue.setText(volume.getStatusStr()); + lblStatusValue.setImage(volume.getStatus() == Volume.VOLUME_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + lblStatusValue.redraw(); + } + + private void createTransportTypeField(Composite section) { + toolkit.createLabel(section, "Transport Type: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getTransportTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createNumOfDisksField(Composite section) { + toolkit.createLabel(section, "Number of Disks: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getNumOfDisks(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStripeCountField(Composite section) { + toolkit.createLabel(section, "Stripe Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getStripeCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createReplicaCountField(Composite section) { + toolkit.createLabel(section, "Replica Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getReplicaCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createVolumeTypeField(Composite section) { + toolkit.createLabel(section, "Volume Type: ", SWT.NONE); + toolkit.createLabel(section, volume.getVolumeTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); + } + + @Override + public void setFocus() { + form.setFocus(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java new file mode 100644 index 00000000..1983f6e4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeView.java @@ -0,0 +1,90 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.utils.GUIHelper; + +/** + * @author root + * + */ +public class VolumeView extends ViewPart { + public static final String ID = VolumeView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private Server server; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (server == null) { + server = (Server) guiHelper.getSelectedEntity(getSite(), Server.class); + } + createSections(parent, server, toolkit); + } + + private void createServerSummarySection(Server server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + server.getTotalMemory(), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(server.getTotalDiskSpace()), SWT.NONE); + } + + private void createSections(Composite parent, Server server, FormToolkit toolkit) { + String serverName = server.getName(); + form = guiHelper.setupForm(parent, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + parent.layout(); // IMP: lays out the form properly + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java new file mode 100644 index 00000000..9477e170 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java @@ -0,0 +1,145 @@ +/** + * DiscoveredServerView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.tabcreators.PieChartViewerComposite; + +/** + * + */ +public class VolumesSummaryView extends ViewPart { + public static final String ID = VolumesSummaryView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private ScrolledForm form; + private EntityGroup<Volume> volumes; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (volumes == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Volume.class) { + volumes = (EntityGroup<Volume>)selectedObj; + } + } + + createSections(parent); + } + + private void createSections(Composite parent) { + form = guiHelper.setupForm(parent, toolkit, "Volumes - Summary"); + createSummarySection(); + createRunningTasksSection(); + createAlertsSection(); + + parent.layout(); // IMP: lays out the form properly + } + + private void createAlertsSection() { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to volumes\nwill be displayed here."); + } + + private void createRunningTasksSection() { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + GlusterDataModel model = modelManager.getModel(); + Cluster cluster = (Cluster) model.getChildren().get(0); // Assume the first/root node of the model is cluster (invisible) + + List<RunningTask> runningTasks = cluster.getRunningTasks(); + String taskMessage = ""; + for(RunningTask task : runningTasks) { + if (task.getStatus().isPercentageSupported()) { + //TODO Progress bar + } + //TODO show different labels for each task + taskMessage = taskMessage + CoreConstants.NEWLINE + task.getDescription(); + } + toolkit.createLabel(section, taskMessage); + } + + private void createSummarySection() { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private int getVolumeCountByStatus(EntityGroup<Volume> volumes, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : (List<Volume>) volumes.getEntities()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, + values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + if (form != null) { + form.setFocus(); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java new file mode 100644 index 00000000..4ccf5325 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesView.java @@ -0,0 +1,108 @@ +/** + * DiscoveredServersView.java + * + * Copyright (c) 2011 Gluster, Inc. <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; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.ServersPage; +import com.gluster.storage.management.gui.views.pages.VolumesPage; + +/** + * + */ +public class VolumesView extends ViewPart implements IDoubleClickListener, ISelectionListener { + public static final String ID = VolumesView.class.getName(); + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + private EntityGroup<Volume> volumes; + private VolumesPage page; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + if (volumes == null) { + Object selectedObj = guiHelper.getSelectedEntity(getSite(), EntityGroup.class); + if (selectedObj != null && ((EntityGroup) selectedObj).getEntityType() == Volume.class) { + volumes = (EntityGroup<Volume>)selectedObj; + } + } + + page = new VolumesPage(parent, getSite(), volumes); + page.addDoubleClickListener(this); + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(NavigationView.ID, this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + page.setFocus(); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, + * org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (part instanceof NavigationView && selection instanceof TreeSelection) { + Entity selectedEntity = (Entity) ((TreeSelection) selection).getFirstElement(); + + if (volumes == selectedEntity || selectedEntity == null || !(selectedEntity instanceof EntityGroup) + || ((EntityGroup) selectedEntity).getEntityType() != Volume.class) { + // entity selection has not changed. do nothing. + return; + } + + volumes = (EntityGroup<Volume>) selectedEntity; + page.setInput(volumes); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java new file mode 100644 index 00000000..e00fe3f8 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/AbstractDisksPage.java @@ -0,0 +1,315 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.TableEditor; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.progress.IProgressConstants; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IEntityListener; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.jobs.InitializeDiskJob; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public abstract class AbstractDisksPage extends Composite implements IEntityListener { + protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + protected TableViewer tableViewer; + private IWorkbenchSite site; + protected static final GUIHelper guiHelper = GUIHelper.getInstance(); + + /** + * Setup properties of the table e.g. column headers, widths, etc. + * + * @param parent + * The parent composite. (TableColumnLayout has to be set on this) + * @param table + * The table to be set up + */ + protected abstract void setupDiskTable(Composite parent, Table table); + + /** + * @return The label provider to be used with the disk table viewer + */ + protected abstract ITableLabelProvider getTableLabelProvider(); + + /** + * @return Index of the "status" column in the table. Return -1 if status column is not displayed + */ + protected abstract int getStatusColumnIndex(); + + private void init(final Composite parent, IWorkbenchSite site, List<Disk> disks) { + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + this.site = site; + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupDiskTableViewer(createTableViewerComposite(), filterText); + + tableViewer.setInput(disks); + setupStatusCellEditor(); // creates hyperlinks for "unitialized" disks + + site.setSelectionProvider(tableViewer); + Application.getApplication().addEntityListener(this); + + parent.layout(); // Important - this actually paints the table + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + } + + public AbstractDisksPage(final Composite parent, int style, IWorkbenchSite site, List<Disk> disks) { + super(parent, style); + init(parent, site, disks); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void createInitializeLink(final TableItem item, final int rowNum, final Disk disk) { + final Table table = tableViewer.getTable(); + final TableEditor editor = new TableEditor(table); + editor.grabHorizontal = true; + editor.horizontalAlignment = SWT.RIGHT; + + table.addPaintListener(new PaintListener() { + private TableItem myItem = item; + private int myRowNum = rowNum; + private ImageHyperlink myLink = null; + private TableEditor myEditor = null; + + private void createLinkFor(Disk disk1, TableItem item1, int rowNum1) { + myItem = item1; + myRowNum = rowNum1; + + myEditor = new TableEditor(table); + myEditor.grabHorizontal = true; + myEditor.horizontalAlignment = SWT.RIGHT; + + myLink = toolkit.createImageHyperlink(table, SWT.NONE); + // link.setImage(guiHelper.getImage(IImageKeys.DISK_UNINITIALIZED)); + myLink.setText("Initialize"); + myLink.addHyperlinkListener(new StatusLinkListener(myLink, myEditor, myItem, tableViewer, disk1, site)); + + myEditor.setEditor(myLink, item1, getStatusColumnIndex()); + + myItem.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + myLink.dispose(); + myEditor.dispose(); + } + }); + } + + @Override + public void paintControl(PaintEvent e) { + int itemCount = table.getItemCount(); + + // Find the table item corresponding to our disk + Disk disk1 = null; + int rowNum1 = -1; + TableItem item1 = null; + for (int i = 0; i < itemCount; i++) { + item1 = table.getItem(i); + disk1 = (Disk) item1.getData(); + if (disk1 != null && disk1 == disk) { + rowNum1 = i; + break; + } + } + + if (rowNum1 == -1) { + // item disposed and disk not visible. nothing to do. + return; + } + + if (myEditor == null || myItem.isDisposed()) { + // item visible, and + // either editor never created, OR + // old item disposed. create the link for it + createLinkFor(disk1, item1, rowNum1); + } + + if (rowNum1 != myRowNum) { + // disk visible, but at a different row num. re-create the link + myLink.dispose(); + myEditor.dispose(); + createLinkFor(disk1, item1, rowNum1); + } + + myEditor.layout(); // IMPORTANT. Without this, the link location goes for a toss on maximize + restore + } + }); + } + + private void setupStatusCellEditor() { + final TableViewer viewer = tableViewer; + final Table table = viewer.getTable(); + for (int i = 0; i < table.getItemCount(); i++) { + final TableItem item = table.getItem(i); + if (item.isDisposed() || item.getData() == null) { + continue; + } + final Disk disk = (Disk) item.getData(); + if (disk.isUninitialized()) { + createInitializeLink(item, i, disk); + } + } + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private TableViewer createDiskTableViewer(Composite parent) { + tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + + tableViewer.setLabelProvider(getTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupDiskTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private void setupDiskTableViewer(Composite parent, final Text filterText) { + tableViewer = createDiskTableViewer(parent); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + private final class StatusLinkListener extends HyperlinkAdapter { + private final Disk disk; + private final TableEditor myEditor; + private final ImageHyperlink myLink; + private final TableViewer viewer; + private final IWorkbenchSite site; + + private StatusLinkListener(ImageHyperlink link, TableEditor editor, TableItem item, TableViewer viewer, + Disk disk, IWorkbenchSite site) { + this.disk = disk; + this.viewer = viewer; + this.myEditor = editor; + this.myLink = link; + this.site = site; + } + + private void updateStatus(final DISK_STATUS status, final boolean disposeEditor) { + if (disposeEditor) { + myLink.dispose(); + myEditor.dispose(); + } + disk.setStatus(status); + viewer.update(disk, new String[] { "status" }); + Application.getApplication().entityChanged(disk, new String[] { "status" }); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + updateStatus(DISK_STATUS.INITIALIZING, true); + + try { + site.getWorkbenchWindow().getActivePage().showView(IProgressConstants.PROGRESS_VIEW_ID); + } catch (PartInitException e1) { + e1.printStackTrace(); + throw new GlusterRuntimeException("Could not open the progress view!", e1); + } + + new InitializeDiskJob(disk).schedule(); + } + } + + @Override + public void entityChanged(final Entity entity, final String[] paremeters) { + if (!(entity instanceof Disk)) { + return; + } + final Disk disk = (Disk) entity; + + Display.getDefault().syncExec(new Runnable() { + public void run() { + tableViewer.update(disk, paremeters); + + if (disk.isUninitialized()) { + Table table = tableViewer.getTable(); + + for (int rowNum = 0; rowNum < table.getItemCount(); rowNum++) { + TableItem item = table.getItem(rowNum); + if (item.getData() == disk) { + createInitializeLink(item, rowNum, disk); + } + } + } + } + }); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java new file mode 100644 index 00000000..9ea962de --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/DisksPage.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.gui.DiskTableLabelProvider; + +public class DisksPage extends AbstractDisksPage { + + public enum DISK_TABLE_COLUMN_INDICES { + SERVER, DISK, SPACE, SPACE_IN_USE, STATUS + }; + + private static final String[] DISK_TABLE_COLUMN_NAMES = new String[] { "Server", "Disk", "Space (GB)", + "Space in Use (GB)", "Status" }; + + public DisksPage(final Composite parent, int style, IWorkbenchSite site, List<Disk> disks) { + super(parent, style, site, disks); + } + + @Override + protected void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SERVER.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.DISK.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal(), SWT.CENTER, 90); + } + + @Override + protected ITableLabelProvider getTableLabelProvider() { + return new DiskTableLabelProvider(); + } + + @Override + protected int getStatusColumnIndex() { + return DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java new file mode 100644 index 00000000..01766115 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/GlusterServersPage.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.GlusterServerTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class GlusterServersPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum GLUSTER_SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_CPUS, TOTAL_MEMORY, TOTAL_DISK_SPACE, STATUS // Removed PREFERRED_NETWORK + }; + + private static final String[] GLUSTER_SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", + "IP Address(es)", "Number\nof CPUs", "Total\nMemory (GB)", "Total Disk\n Space (GB)", "Status" }; // Removed "Preferred\nNetwork", + + public GlusterServersPage(Composite parent, int style) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupServerTableViewer(filterText); + } + + public GlusterServersPage(final Composite parent, int style, EntityGroup<GlusterServer> servers) { + this(parent, style); + + tableViewer.setInput(servers); + parent.layout(); // Important - this actually paints the table + + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupServerTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, GLUSTER_SERVER_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 100); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.STATUS, SWT.CENTER, 70); + // setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.PREFERRED_NETWORK, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.NUM_OF_CPUS, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_MEMORY, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE, SWT.CENTER, 90); + setColumnProperties(table, GLUSTER_SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE, SWT.CENTER, 90); + //setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + private TableViewer createServerTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + //TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new GlusterServerTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider<GlusterServer>()); + + setupServerTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private void setupServerTableViewer(final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createServerTableViewer(tableViewerComposite); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, GLUSTER_SERVER_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java new file mode 100644 index 00000000..bace2af9 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerDisksPage.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.gui.views.details; + +import java.util.List; + +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IWorkbenchSite; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.gui.ServerDiskTableLabelProvider; +import com.gluster.storage.management.gui.TableLabelProviderAdapter; + +public class ServerDisksPage extends AbstractDisksPage { + public ServerDisksPage(Composite parent, int style, IWorkbenchSite site, List<Disk> disks) { + super(parent, style, site, disks); + } + + public enum SERVER_DISK_TABLE_COLUMN_INDICES { + DISK, SPACE, SPACE_IN_USE, STATUS + }; + + private static final String[] SERVER_DISK_TABLE_COLUMN_NAMES = new String[] { "Disk", "Space (GB)", + "Space in Use (GB)", "Status" }; + + @Override + protected void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, SERVER_DISK_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK.ordinal(), SWT.CENTER, 100); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.SPACE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.SPACE_IN_USE.ordinal(), SWT.CENTER, 90); + guiHelper.setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(), SWT.LEFT, 90); + } + + @Override + protected int getStatusColumnIndex() { + return SERVER_DISK_TABLE_COLUMN_INDICES.STATUS.ordinal(); + } + + @Override + protected TableLabelProviderAdapter getTableLabelProvider() { + return new ServerDiskTableLabelProvider(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java new file mode 100644 index 00000000..a499caf3 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/ServerLogsPage.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class ServerLogsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Text text; + private Table table; + + public enum LOG_TABLE_COLUMN_INDICES { + DATE, TIME, DISK, SEVERITY, MESSAGE + }; + + private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Disk", "Severity", "Message" }; + + /** + * Create the composite. + * + * @param parent + * @param style + */ + public ServerLogsPage(Composite parent, int style, GlusterServer server) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setLayout(new GridLayout(1, false)); + GridData layoutData = new GridData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + setLayoutData(layoutData); + + Composite composite = toolkit.createComposite(this, SWT.NONE); + toolkit.paintBordersFor(composite); + + Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE); + lblScanLast.setBounds(0, 15, 80, 20); + + text = toolkit.createText(composite, "100", SWT.NONE); + text.setBounds(85, 15, 60, 20); + + Label lblMessagesAndFilter = toolkit.createLabel(composite, " messages from ", SWT.CENTER); + lblMessagesAndFilter.setBounds(160, 15, 110, 20); + + Combo combo = new Combo(composite, SWT.CENTER); + combo.setBounds(295, 15, 100, 20); + combo.setItems(new String[] { "syslog", "dmesg" }); + toolkit.adapt(combo); + toolkit.paintBordersFor(combo); + combo.select(0); + + Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE); + btngo.setBounds(410, 13, 50, 30); + + Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL); + separator.setBounds(0, 50, 500, 2); + + Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT); + lblFilterString.setBounds(0, 65, 100, 20); + + text = guiHelper.createFilterText(toolkit, composite); + text.setBounds(105, 65, 250, 20); + + Composite logContentsComposite = createLogContentsComposite(toolkit); + // Text logContentsText = toolkit.createText(logContentsComposite, "", SWT.MULTI | SWT.FLAT | SWT.BORDER); + // logContentsText.setEditable(false); + // populateDummyLogContent(logContentsText); + + ListViewer logViewer = new ListViewer(logContentsComposite, SWT.BORDER | SWT.V_SCROLL | SWT.NO); + logViewer.setContentProvider(new ArrayContentProvider()); + guiHelper.createFilter(logViewer, text, false); + logViewer.setInput(getDummyLogContents()); + + // TODO: Link the filter string with the contents text + } + + private Composite createLogContentsComposite(FormToolkit toolkit) { + Composite tableViewerComposite = toolkit.createComposite(this, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.verticalIndent = 10; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; + } + + private String[] getDummyLogContents() { + + String[] logMessages = { + "Jan 19 13:43:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:44:08 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:44:47 shireesh-laptop dhclient: last message repeated 2 times", + "Jan 19 13:44:47 shireesh-laptop dhclient: DHCPREQUEST of 192.168.1.174 on eth1 to 255.255.255.255 port 67", + "Jan 19 13:45:49 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:46:59 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:48:01 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:49:02 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:50:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:51:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:52:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:53:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:54:08 shireesh-laptop dhclient: last message repeated 5 times", + "Jan 19 13:55:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:56:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:57:08 shireesh-laptop dhclient: last message repeated 3 times", + "Jan 19 13:58:08 shireesh-laptop dhclient: last message repeated 6 times", + "Jan 19 13:59:08 shireesh-laptop dhclient: last message repeated 4 times", + "Jan 19 13:59:40 shireesh-laptop dhclient: last message repeated 3 times", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> DHCP: device eth1 state changed bound -> expire", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 8", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> DHCP: device eth1 state changed expire -> preinit", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPOFFER of 192.168.1.174 from 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPREQUEST of 192.168.1.174 on eth1 to 255.255.255.255 port 67", + "Jan 19 13:59:40 shireesh-laptop dhclient: DHCPACK of 192.168.1.174 from 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop dhclient: bound to 192.168.1.174 -- renewal in 3205 seconds.", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> DHCP: device eth1 state changed preinit -> bound", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> address 192.168.1.174", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> prefix 24 (255.255.255.0)", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> gateway 192.168.1.1", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> nameserver '192.168.1.1'", + "Jan 19 13:59:40 shireesh-laptop NetworkManager: <info> domain name 'in.gluster.com'", + "Jan 19 14:03:53 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:53 shireesh-laptop avahi-daemon[1098]: Received response from host 192.168.1.155 with invalid source port 37219 on interface 'eth0.0'", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Invalid legacy unicast query packet.", + "Jan 19 14:03:54 shireesh-laptop avahi-daemon[1098]: Received response from host 192.168.1.155 with invalid source port 37219 on interface 'eth0.0'", + "Jan 19 14:05:09 shireesh-laptop avahi-daemon[1098]: last message repeated 8 times", + "Jan 19 14:12:48 shireesh-laptop NetworkManager: <debug> [1295426568.002642] periodic_update(): Roamed from BSSID E0:CB:4E:C0:0B:7F (glfs) to (none) ((none))", + "Jan 19 14:12:54 shireesh-laptop NetworkManager: <debug> [1295426574.002448] periodic_update(): Roamed from BSSID (none) ((none)) to E0:CB:4E:C0:0B:7F (glfs)", + "Jan 19 14:17:01 shireesh-laptop CRON[5321]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)" }; + + return logMessages; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java new file mode 100644 index 00000000..1f5f8a15 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreator.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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 new file mode 100644 index 00000000..f5098af5 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactory.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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 new file mode 100644 index 00000000..28d3d4aa --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/TabCreatorFactoryImpl.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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/VolumeLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java new file mode 100644 index 00000000..d435201e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.DateTime; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.GlusterDummyModel; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.VolumeLogTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumeLogsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private final GUIHelper guiHelper = GUIHelper.getInstance(); + private Text text; + public enum LOG_TABLE_COLUMN_INDICES { + DATE, TIME, DISK, SEVERITY, MESSAGE + }; + + private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Disk", "Severity", "Message" }; + + /** + * Create the composite. + * @param parent + * @param style + */ + public VolumeLogsPage(Composite parent, int style, Volume volume) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setLayout(new GridLayout(1, false)); + GridData layoutData = new GridData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + //layoutData.verticalIndent = 10; + setLayoutData(layoutData); + + Composite composite = toolkit.createComposite(this, SWT.NONE); + toolkit.paintBordersFor(composite); + + Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE); + lblScanLast.setBounds(0, 15, 80, 20); + + text = toolkit.createText(composite, "100", SWT.NONE); + text.setBounds(85, 15, 60, 20); + + Label lblMessagesAndFilter = toolkit.createLabel(composite, "messages, and filter on disk", SWT.NONE); + lblMessagesAndFilter.setBounds(160, 15, 200, 20); + + Combo combo = new Combo(composite, SWT.NONE); + combo.setBounds(365, 15, 100, 20); + combo.setItems(new String[] {"ALL", "sda", "sdb", "sdc", "sdd"}); + toolkit.adapt(combo); + toolkit.paintBordersFor(combo); + combo.select(0); + + Label lblSeverity = toolkit.createLabel(composite, "Severity", SWT.NONE); + lblSeverity.setBounds(480, 15, 70, 20); + + Combo combo_1 = new Combo(composite, SWT.NONE); + combo_1.setBounds(555, 15, 110, 20); + combo_1.setItems(new String[] {"ALL", "SEVERE", "WARNING", "DEBUG", "INFO"}); + toolkit.adapt(combo_1); + toolkit.paintBordersFor(combo_1); + combo_1.select(1); + + Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE); + lblFrom.setBounds(0, 60, 40, 20); + + DateTime dateTime = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + dateTime.setBounds(45, 60, 120, 20); + toolkit.adapt(dateTime); + toolkit.paintBordersFor(dateTime); + + DateTime dateTime_1 = new DateTime(composite, SWT.BORDER | SWT.TIME); + dateTime_1.setBounds(171, 60, 120, 20); + toolkit.adapt(dateTime_1); + toolkit.paintBordersFor(dateTime_1); + + Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE); + lblTo.setBounds(329, 60, 26, 20); + + DateTime dateTime_2 = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN); + dateTime_2.setBounds(355, 60, 120, 20); + toolkit.adapt(dateTime_2); + toolkit.paintBordersFor(dateTime_2); + + DateTime dateTime_3 = new DateTime(composite, SWT.BORDER | SWT.TIME); + dateTime_3.setBounds(480, 60, 120, 20); + toolkit.adapt(dateTime_3); + toolkit.paintBordersFor(dateTime_3); + + Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE); + btngo.setBounds(605, 55, 60, 30); + + Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL); + separator.setBounds(0, 95, 680, 2); + + Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT); + lblFilterString.setBounds(0, 105, 85, 20); + + text = guiHelper.createFilterText(toolkit, composite); + text.setBounds(90, 105, 250, 20); + + Composite tableViewerComposite = createTableViewerComposite(); + + TableViewer tableViewer = new TableViewer(tableViewerComposite, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeLogTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupLogsTable(tableViewerComposite, tableViewer.getTable()); + guiHelper.createFilter(tableViewer, text, false); + tableViewer.setInput(GlusterDummyModel.getDummyLogMessages().toArray()); + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.verticalIndent = 10; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; + } + + private void setupLogsTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, LOG_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.DATE, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.TIME, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.DISK, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.SEVERITY, SWT.CENTER, 50); + setColumnProperties(table, LOG_TABLE_COLUMN_INDICES.MESSAGE, SWT.LEFT, 100); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + private void setColumnProperties(Table table, LOG_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java new file mode 100644 index 00000000..baa14a59 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.VolumeOptionsTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumeOptionsPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum OPTIONS_TABLE_COLUMN_INDICES { + OPTION_KEY, OPTION_VALUE + }; + + private static final String[] OPTIONS_TABLE_COLUMN_NAMES = new String[] { "Option Key", "Option Value" }; + + public VolumeOptionsPage(Composite parent, int style) { + super(parent, style); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + Text filterText = guiHelper.createFilterText(toolkit, this); + setupDiskTableViewer(filterText); + } + + public VolumeOptionsPage(final Composite parent, int style, Volume volume) { + this(parent, style); + + tableViewer.setInput(volume.getOptions().entrySet().toArray()); + + parent.layout(); // Important - this actually paints the table + + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupDiskTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, OPTIONS_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY, SWT.CENTER, 100); + setColumnProperties(table, OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE, SWT.CENTER, 100); + } + + private TableViewer createDiskTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeOptionsTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupDiskTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private void setupDiskTableViewer(final Text filterText) { + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createDiskTableViewer(tableViewerComposite); + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, OPTIONS_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java new file mode 100644 index 00000000..571afb2e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ClusterTabCreator.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class ClusterTabCreator implements TabCreator { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + private int getVolumeCountByStatus(Cluster cluster, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : cluster.getVolumes()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + private int getServerCountByStatus(Cluster cluster, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : cluster.getServers()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createVolumesSection(Cluster cluster, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Volumes", null, 1, false); + + // toolkit.createLabel(sectionClient, "Number of Volumes: ", SWT.NONE); + // toolkit.createLabel(sectionClient, "12", SWT.NONE); + // + // toolkit.createLabel(sectionClient, "Online: ", SWT.NONE); + // Label labelOnlineCount = toolkit.createLabel(sectionClient, "9", SWT.NONE); + // labelOnlineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN)); + // + // toolkit.createLabel(sectionClient, "Offline: ", SWT.NONE); + // Label lblOfflineCount = toolkit.createLabel(sectionClient, "3", SWT.NONE); + // lblOfflineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED)); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(cluster, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createServersSection(Cluster cluster, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Servers", null, 1, false); + +// toolkit.createLabel(sectionClient, "Number of Servers: ", SWT.NONE); +// toolkit.createLabel(sectionClient, "7", SWT.NONE); +// +// toolkit.createLabel(sectionClient, "Online: ", SWT.NONE); +// Label labelOnlineCount = toolkit.createLabel(sectionClient, "6", SWT.NONE); +// labelOnlineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN)); +// +// toolkit.createLabel(sectionClient, "Offline: ", SWT.NONE); +// Label lblOfflineCount = toolkit.createLabel(sectionClient, "1", SWT.NONE); +// lblOfflineCount.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED)); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(cluster, SERVER_STATUS.OFFLINE)) }; + + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + private void createActionsSection(final Cluster cluster, final FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Actions", null, 1, false); + + ImageHyperlink imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Create Volume"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.CREATE_VOLUME_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + + imageHyperlink = toolkit.createImageHyperlink(section, SWT.NONE); + imageHyperlink.setText("Add Server(s)"); + imageHyperlink.setImage(guiHelper.getImage(IImageKeys.ADD_SERVER_BIG)); + imageHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + // TODO: Override appropriate method and handle hyperlink event + }); + } + + private void createClusterSummaryTab(final Cluster cluster, final TabFolder tabFolder, final FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, cluster.getName(), IImageKeys.CLUSTER); + + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Cluster Summary"); + createVolumesSection(cluster, toolkit, form); + createServersSection(cluster, toolkit, form); + createActionsSection(cluster, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createClusterSummaryTab((Cluster) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java new file mode 100644 index 00000000..3c94c3cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupGlusterServerTabCreator.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.DisksPage; +import com.gluster.storage.management.gui.views.details.GlusterServersPage; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class EntityGroupGlusterServerTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private int getServerCountByStatus(EntityGroup<GlusterServer> servers, SERVER_STATUS status) { + int count = 0; + for (GlusterServer server : (List<GlusterServer>)servers.getEntities()) { + if (server.getStatus() == status) { + count++; + } + } + return count; + } + + private void createAlertsSection(final EntityGroup<GlusterServer> servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to servers\nwill be displayed here."); + } + + private void createRunningTasksSection(final EntityGroup<GlusterServer> servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nservers will be displayed here."); + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createSummaryTab((EntityGroup<GlusterServer>)entity, tabFolder, toolkit); + createServersTab((EntityGroup<GlusterServer>)entity, tabFolder, toolkit); + createDisksTab((EntityGroup<GlusterServer>)entity, tabFolder, toolkit, site); + } + + private void createServersTab(EntityGroup<GlusterServer> servers, TabFolder tabFolder, FormToolkit toolkit) { + Composite serversTab = guiHelper.createTab(tabFolder, "Servers", IImageKeys.SERVERS); + GlusterServersPage page = new GlusterServersPage(serversTab, SWT.NONE, servers); + page.addDoubleClickListener(this); + } + + private void createSummaryTab(EntityGroup<GlusterServer> servers, TabFolder tabFolder, FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, "Summary", IImageKeys.SERVERS); + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Servers - Summary"); + createSummarySection(servers, toolkit, form); + createRunningTasksSection(servers, toolkit, form); + createAlertsSection(servers, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + private void createSummarySection(final EntityGroup<GlusterServer> servers, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.ONLINE)), + Double.valueOf(getServerCountByStatus(servers, SERVER_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + + private void createDisksTab(EntityGroup<GlusterServer> servers, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite disksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.SERVERS); + DisksPage page = new DisksPage(disksTab, SWT.NONE, site, getAllDisks(servers)); + + disksTab.layout(); // IMP: lays out the form properly + } + + private List<Disk> getAllDisks(EntityGroup<GlusterServer> servers) { + List<Disk> disks = new ArrayList<Disk>(); + for(GlusterServer server : (List<GlusterServer>)servers.getEntities()) { + disks.addAll(server.getDisks()); + } + return disks; + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java new file mode 100644 index 00000000..3f49ba6b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupServerTabCreator.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.pages.ServersPage; + +public class EntityGroupServerTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createServersTab((EntityGroup<Server>) entity, tabFolder); + } + + private void createServersTab(EntityGroup<Server> servers, TabFolder tabFolder) { + Composite serversTab = guiHelper.createTab(tabFolder, "Discovered Servers", IImageKeys.SERVERS); + ServersPage page = new ServersPage(serversTab, null, servers); + page.addDoubleClickListener(this); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java new file mode 100644 index 00000000..22ffd94d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/EntityGroupVolumeTabCreator.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import java.util.List; + +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.pages.VolumesPage; + +public class EntityGroupVolumeTabCreator implements TabCreator, IDoubleClickListener { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createSummaryTab((EntityGroup<Volume>) entity, tabFolder, toolkit); + createVolumesTab((EntityGroup<Volume>) entity, tabFolder, toolkit); + } + + private int getVolumeCountByStatus(EntityGroup<Volume> volumes, VOLUME_STATUS status) { + int count = 0; + for (Volume volume : (List<Volume>) volumes.getEntities()) { + if (volume.getStatus() == status) { + count++; + } + } + return count; + } + + private void createStatusChart(FormToolkit toolkit, Composite section, Double[] values) { + String[] categories = new String[] { "Online", "Offline" }; + PieChartViewerComposite chartViewerComposite = new PieChartViewerComposite(section, SWT.NONE, categories, + values); + + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.widthHint = 250; + data.heightHint = 250; + chartViewerComposite.setLayoutData(data); + } + + private void createAlertsSection(final EntityGroup<Volume> volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 2, false); + + toolkit.createLabel(section, "Any alerts related to volumes\nwill be displayed here."); + } + + private void createRunningTasksSection(final EntityGroup<Volume> volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Running Tasks", null, 2, false); + + toolkit.createLabel(section, "List of running tasks related to\nvolumes will be displayed here."); + } + + private void createSummarySection(final EntityGroup<Volume> volumes, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Availability", null, 2, false); + + Double[] values = new Double[] { Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.ONLINE)), + Double.valueOf(getVolumeCountByStatus(volumes, VOLUME_STATUS.OFFLINE)) }; + createStatusChart(toolkit, section, values); + } + + private void createSummaryTab(final EntityGroup<Volume> volumes, TabFolder tabFolder, FormToolkit toolkit) { + Composite summaryTab = guiHelper.createTab(tabFolder, "Summary", IImageKeys.VOLUMES); + final ScrolledForm form = guiHelper.setupForm(summaryTab, toolkit, "Volumes - Summary"); + createSummarySection(volumes, toolkit, form); + createRunningTasksSection(volumes, toolkit, form); + createAlertsSection(volumes, toolkit, form); + + summaryTab.layout(); // IMP: lays out the form properly + } + + private void createVolumesTab(EntityGroup<Volume> volumes, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumesTab = guiHelper.createTab(tabFolder, "Volumes", IImageKeys.VOLUMES); + VolumesPage page = new VolumesPage(volumesTab, null, volumes); + page.addDoubleClickListener(this); + } + + @Override + public void doubleClick(DoubleClickEvent event) { + NavigationView clusterView = (NavigationView) guiHelper.getView(NavigationView.ID); + if (clusterView != null) { + clusterView.selectEntity((Entity) ((StructuredSelection) event.getSelection()).getFirstElement()); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java new file mode 100644 index 00000000..e1aa59ff --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/GlusterServerTabCreator.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.ServerDisksPage; +import com.gluster.storage.management.gui.views.details.ServerLogsPage; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.richclientgui.toolbox.gauges.CoolGauge; + +public class GlusterServerTabCreator implements TabCreator { + public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { + INTERFACE, IP_ADDRESS, NETMASK, GATEWAY + }; + + private static final String[] NETWORK_INTERFACE_TABLE_COLUMN_NAMES = { "Interface", "IP Address", "Netmask", + "Gateway" }; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private void createServerSummarySection(GlusterServer server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + +// toolkit.createLabel(section, "Preferred Network: ", SWT.NONE); +// toolkit.createLabel(section, server.getPreferredNetworkInterface().getName(), SWT.NONE); + + boolean online = server.getStatus() == SERVER_STATUS.ONLINE; + + if (online) { + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + + // toolkit.createLabel(section, "CPU Usage (%): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getCpuUsage() : "NA", SWT.NONE); + + toolkit.createLabel(section, "% CPU Usage (avg): ", SWT.NONE); + CoolGauge gauge = new CoolGauge(section, guiHelper.getImage(IImageKeys.GAUGE_SMALL)); + gauge.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); + gauge.setGaugeNeedleColour(Display.getDefault().getSystemColor(SWT.COLOR_RED)); + gauge.setGaugeNeedleWidth(2); + gauge.setGaugeNeedlePivot(new Point(66, 65)); + + gauge.setPoints(getPnts()); + gauge.setLevel(server.getCpuUsage() / 100); + gauge.setToolTipText(server.getCpuUsage() + "%"); + + toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + ProgressBar memoryUsageBar = new ProgressBar(section, SWT.SMOOTH); + memoryUsageBar.setMinimum(0); + memoryUsageBar.setMaximum((int) Math.round(server.getTotalMemory())); + memoryUsageBar.setSelection((int) Math.round(server.getMemoryInUse())); + memoryUsageBar.setToolTipText("Total: " + server.getTotalMemory() + "GB, In Use: " + + server.getMemoryInUse() + "GB"); + + // toolkit.createLabel(section, "Memory Usage: ", SWT.NONE); + // final CoolProgressBar bar = new CoolProgressBar(section,SWT.HORIZONTAL, + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_LEFT), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_FILLED), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_EMPTY), + // guiHelper.getImage(IImageKeys.PROGRESS_BAR_RIGHT)); + // bar.updateProgress(server.getMemoryInUse() / server.getTotalMemory()); + + // toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getTotalDiskSpace() : "NA", SWT.NONE); + // + // toolkit.createLabel(section, "Disk Space in Use (GB): ", SWT.NONE); + // toolkit.createLabel(section, online ? "" + server.getDiskSpaceInUse() : "NA", SWT.NONE); + + toolkit.createLabel(section, "Disk Usage: ", SWT.NONE); + ProgressBar diskUsageBar = new ProgressBar(section, SWT.SMOOTH); + diskUsageBar.setMinimum(0); + diskUsageBar.setMaximum((int) Math.round(server.getTotalDiskSpace())); + diskUsageBar.setSelection((int) Math.round(server.getDiskSpaceInUse())); + diskUsageBar.setToolTipText("Total: " + NumberUtil.formatNumber(server.getTotalDiskSpace()) + + "GB, In Use: " + NumberUtil.formatNumber(server.getDiskSpaceInUse()) + "GB"); + } + + toolkit.createLabel(section, "Status: ", SWT.NONE); + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(server.getStatusStr()); + lblStatusValue.setImage(server.getStatus() == GlusterServer.SERVER_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + toolkit.adapt(lblStatusValue, true, true); + } + + private List<Point> getPnts() { + final List<Point> pnts = new ArrayList<Point>(); + pnts.add(new Point(47, 98)); + pnts.add(new Point(34, 84)); + pnts.add(new Point(29, 65)); + pnts.add(new Point(33, 48)); + pnts.add(new Point(48, 33)); + pnts.add(new Point(66, 28)); + pnts.add(new Point(83, 32)); + pnts.add(new Point(98, 47)); + pnts.add(new Point(103, 65)); + pnts.add(new Point(98, 83)); + pnts.add(new Point(84, 98)); + return pnts; + } + + private void createServerSummaryTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverSummaryTab = guiHelper.createTab(tabFolder, serverName, IImageKeys.SERVER); + final ScrolledForm form = guiHelper.setupForm(serverSummaryTab, toolkit, "Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + if (server.getStatus() == SERVER_STATUS.ONLINE) { + Composite section = createNetworkInterfacesSection(server, toolkit, form); + } + + serverSummaryTab.layout(); // IMP: lays out the form properly + } + + private void setupNetworkInterfaceTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, + NETWORK_INTERFACE_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.INTERFACE, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.IP_ADDRESS, SWT.CENTER, 100); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.NETMASK, SWT.CENTER, 70); + setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.GATEWAY, SWT.CENTER, 70); + // setColumnProperties(table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES.PREFERRED, SWT.CENTER, 70); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, NETWORK_INTERFACE_TABLE_COLUMN_INDICES columnIndex, int alignment, + int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + private TableViewer createNetworkInterfacesTableViewer(final Composite parent, GlusterServer server) { + TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new NetworkInterfaceTableLabelProvider()); + tableViewer.setContentProvider(new ArrayContentProvider()); + + setupNetworkInterfaceTable(parent, tableViewer.getTable()); + tableViewer.setInput(server.getNetworkInterfaces().toArray()); + + return tableViewer; + } + + private Composite createTableViewerComposite(Composite parent) { + Composite tableViewerComposite = new Composite(parent, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + GridData tableLayoutData = new GridData(SWT.FILL, SWT.FILL, true, false); + tableLayoutData.widthHint = 400; + tableLayoutData.minimumWidth = 400; + // tableLayoutData.grabExcessHorizontalSpace = true; + tableViewerComposite.setLayoutData(tableLayoutData); + return tableViewerComposite; + } + + private Composite createNetworkInterfacesSection(GlusterServer server, FormToolkit toolkit, ScrolledForm form) { + final Composite section = guiHelper.createSection(form, toolkit, "Network Interfaces", null, 1, false); + createNetworkInterfacesTableViewer(createTableViewerComposite(section), server); +// Hyperlink changePreferredNetworkLink = toolkit.createHyperlink(section, "Change Preferred Network", SWT.NONE); +// changePreferredNetworkLink.addHyperlinkListener(new HyperlinkAdapter() { +// +// @Override +// public void linkActivated(HyperlinkEvent e) { +// new MessageDialog( +// section.getShell(), +// "Gluster Storage Platform", +// guiHelper.getImage(IImageKeys.SERVER), +// "This will show additional controls to help user choose a new network interface. TO BE IMPLEMENTED.", +// MessageDialog.INFORMATION, new String[] { "OK" }, 0).open(); +// } +// }); + return section; + } + + private void createServerLogsTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverLogsTab = guiHelper.createTab(tabFolder, "Logs", IImageKeys.SERVER); + ServerLogsPage logsPage = new ServerLogsPage(serverLogsTab, SWT.NONE, server); + + serverLogsTab.layout(); // IMP: lays out the form properly + } + + private void createServerDisksTab(GlusterServer server, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite serverDisksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.SERVER); + ServerDisksPage page = new ServerDisksPage(serverDisksTab, SWT.NONE, site, server.getDisks()); + + serverDisksTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + GlusterServer server = (GlusterServer) entity; + + createServerSummaryTab(server, tabFolder, toolkit); + if (server.getStatus() == SERVER_STATUS.ONLINE) { + createServerDisksTab(server, tabFolder, toolkit, site); + createServerLogsTab(server, tabFolder, toolkit); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java new file mode 100644 index 00000000..80c9c807 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/PieChartViewerComposite.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.eclipse.birt.chart.api.ChartEngine; +import org.eclipse.birt.chart.device.IDeviceRenderer; +import org.eclipse.birt.chart.device.IUpdateNotifier; +import org.eclipse.birt.chart.exception.ChartException; +import org.eclipse.birt.chart.factory.GeneratedChartState; +import org.eclipse.birt.chart.factory.Generator; +import org.eclipse.birt.chart.model.Chart; +import org.eclipse.birt.chart.model.ChartWithoutAxes; +import org.eclipse.birt.chart.model.attribute.Bounds; +import org.eclipse.birt.chart.model.attribute.ChartDimension; +import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; +import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; +import org.eclipse.birt.chart.model.component.Series; +import org.eclipse.birt.chart.model.component.impl.SeriesImpl; +import org.eclipse.birt.chart.model.data.NumberDataSet; +import org.eclipse.birt.chart.model.data.SeriesDefinition; +import org.eclipse.birt.chart.model.data.TextDataSet; +import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl; +import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl; +import org.eclipse.birt.chart.model.data.impl.TextDataSetImpl; +import org.eclipse.birt.chart.model.impl.ChartWithoutAxesImpl; +import org.eclipse.birt.chart.model.layout.Legend; +import org.eclipse.birt.chart.model.layout.Plot; +import org.eclipse.birt.chart.model.type.PieSeries; +import org.eclipse.birt.chart.model.type.impl.PieSeriesImpl; +import org.eclipse.birt.core.framework.PlatformConfig; +import org.eclipse.core.runtime.Platform; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; + +/** + * + */ +public final class PieChartViewerComposite extends Composite implements + PaintListener, IUpdateNotifier { + + private IDeviceRenderer deviceReader = null; + private Chart chart = null; + private GeneratedChartState generatedChartState = null; + private boolean needsGeneration = true; + + private static Logger logger = Logger + .getLogger(PieChartViewerComposite.class.getName()); + + /** + * @param parent + * Parent composite of this pie chart viewer composite + * @param style + * SWT style to be used + * @param categories + * Categories of the pie chart + * @param values + * Values of each category in the pie chart Constructs a pie + * chart viewer composite for given categories and values + */ + public PieChartViewerComposite(Composite parent, int style, String[] categories, + Double[] values) { + super(parent, style); + try { + PlatformConfig config = new PlatformConfig(); + config.setBIRTHome(Platform.getInstallLocation().getURL().getPath()); + // Get the connection with SWT device to render the graphics. + deviceReader = ChartEngine.instance(config).getRenderer("dv.SWT");//$NON-NLS-1$ + } catch (ChartException ex) { + logger.log(Level.SEVERE, "Could not create Chart Renderer for SWT", + ex); + } + + addControlListener(new ControlListener() { + + public void controlMoved(ControlEvent e) { + needsGeneration = true; + } + + public void controlResized(ControlEvent e) { + needsGeneration = true; + } + }); + + chart = createPieChart(categories, values); + addPaintListener(this); + } + + /** + * @param categories + * Categories of the pie chart + * @param values + * Values of each category in the pie chart + * @return The chart object created for given categories and values + */ + public static final Chart createPieChart(String[] categories, + Double[] values) { + ChartWithoutAxes pieChart = ChartWithoutAxesImpl.create(); + + // Plot + pieChart.setSeriesThickness(2); + pieChart.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL); + pieChart.getBlock().setBackground(ColorDefinitionImpl.WHITE()); + Plot p = pieChart.getPlot(); + p.getClientArea().setBackground(null); + p.getClientArea().getOutline().setVisible(false); + p.getOutline().setVisible(false); + + // Legend + Legend lg = pieChart.getLegend(); + lg.getText().getFont().setSize(8); + lg.setBackground(null); + lg.getOutline().setVisible(false); + lg.setVisible(true); + + // Title + pieChart.getTitle().getLabel().getCaption().setValue("Pie Chart");//$NON-NLS-1$ + pieChart.getTitle().getOutline().setVisible(false); + pieChart.getTitle().setVisible(false); + + TextDataSet categoryValues = TextDataSetImpl.create(categories); + NumberDataSet seriesOneValues = NumberDataSetImpl.create(values); + + // Base Series + Series seCategory = SeriesImpl.create(); + seCategory.setDataSet(categoryValues); + + SeriesDefinition sd = SeriesDefinitionImpl.create(); + pieChart.getSeriesDefinitions().add(sd); + sd.getSeriesPalette().shift(0); + sd.getSeries().add(seCategory); + + // Orthogonal Series + PieSeries sePie = (PieSeries) PieSeriesImpl.create(); + sePie.setDataSet(seriesOneValues); + sePie.setSeriesIdentifier("Cities");//$NON-NLS-1$ + sePie.getTitle().setVisible(false); + sePie.setExplosion(2); + + SeriesDefinition seriesDefinition = SeriesDefinitionImpl.create(); + seriesDefinition.getQuery().setDefinition("query.definition");//$NON-NLS-1$ + sd.getSeriesDefinitions().add(seriesDefinition); + seriesDefinition.getSeries().add(sePie); + + return pieChart; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events + * .PaintEvent) + */ + public final void paintControl(PaintEvent e) { + Rectangle d = ((Composite) e.getSource()).getBounds(); + Image imgChart = new Image(this.getDisplay(), d); + GC gcImage = new GC(imgChart); + deviceReader.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, gcImage); + deviceReader.setProperty(IDeviceRenderer.UPDATE_NOTIFIER, this); + + Bounds bo = BoundsImpl.create(0, 0, d.width, d.height); + bo.scale(58d / deviceReader.getDisplayServer().getDpiResolution()); + + Generator gr = Generator.instance(); + if (needsGeneration) { + needsGeneration = false; + try { + generatedChartState = gr.build(deviceReader.getDisplayServer(), + chart, bo, null, null, null); + } catch (ChartException ce) { + ce.printStackTrace(); + } + } + + try { + gr.render(deviceReader, generatedChartState); + GC gc = e.gc; + gc.drawImage(imgChart, d.x, d.y); + } catch (ChartException gex) { + logger.log(Level.SEVERE, "Exception while rendering pie chart [" + + gex.getMessage() + "]", gex); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#getDesignTimeModel() + */ + public Chart getDesignTimeModel() { + return chart; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#getRunTimeModel() + */ + public Chart getRunTimeModel() { + return generatedChartState.getChartModel(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#peerInstance() + */ + public Object peerInstance() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#regenerateChart() + */ + public void regenerateChart() { + redraw(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.birt.chart.device.IUpdateNotifier#repaintChart() + */ + public void repaintChart() { + redraw(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java new file mode 100644 index 00000000..d634253e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/ServerTabCreator.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.TabCreator; + +public class ServerTabCreator implements TabCreator { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private void createServerSummarySection(Server server, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Summary", null, 2, false); + + toolkit.createLabel(section, "Number of CPUs: ", SWT.NONE); + toolkit.createLabel(section, "" + server.getNumOfCPUs(), SWT.NONE); + +// toolkit.createLabel(section, "CPU Usage (%): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getCpuUsage(), SWT.NONE); + + toolkit.createLabel(section, "Total Memory (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + server.getTotalMemory(), SWT.NONE); + +// toolkit.createLabel(section, "Memory in Use (GB): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getMemoryInUse(), SWT.NONE); + + toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(server.getTotalDiskSpace()), SWT.NONE); + +// toolkit.createLabel(section, "Disk Space in Use (GB): ", SWT.NONE); +// toolkit.createLabel(section, "" + server.getDiskSpaceInUse(), SWT.NONE); + } + + private void createServerSummaryTab(Server server, TabFolder tabFolder, FormToolkit toolkit) { + String serverName = server.getName(); + Composite serverSummaryTab = guiHelper.createTab(tabFolder, serverName, IImageKeys.SERVER); + final ScrolledForm form = guiHelper.setupForm(serverSummaryTab, toolkit, "Discovered Server Summary [" + serverName + "]"); + createServerSummarySection(server, toolkit, form); + + serverSummaryTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createServerSummaryTab((Server) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java new file mode 100644 index 00000000..3e5382cc --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/tabcreators/VolumeTabCreator.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.tabcreators; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.details.DisksPage; +import com.gluster.storage.management.gui.views.details.TabCreator; +import com.gluster.storage.management.gui.views.details.VolumeLogsPage; +import com.gluster.storage.management.gui.views.details.VolumeOptionsPage; + +public class VolumeTabCreator implements TabCreator { + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private void createVolumePropertiesSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Properties", null, 3, false); + + createVolumeTypeField(volume, toolkit, section); + + VOLUME_TYPE volumeType = volume.getVolumeType(); + if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + createReplicaCountField(volume, toolkit, section); + } + + if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + createStripeCountField(volume, toolkit, section); + } + + createNumOfDisksField(volume, toolkit, section); + createDiskSpaceField(volume, toolkit, section); + createTransportTypeField(volume, toolkit, section); + createNASProtocolField(volume, toolkit, section); + createAccessControlField(volume, toolkit, section); + createStatusField(volume, toolkit, section); + } + + private void createDiskSpaceField(final Volume volume, FormToolkit toolkit, Composite section) { + Label diskSpaceLabel = toolkit.createLabel(section, "Total Disk Space (GB): ", SWT.NONE); + diskSpaceLabel.setToolTipText("<b>bold</b>normal"); + toolkit.createLabel(section, "" + NumberUtil.formatNumber(volume.getTotalDiskSpace()), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStatusField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Status: ", SWT.NONE); + + CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue.setText(volume.getStatusStr()); + lblStatusValue.setImage(volume.getStatus() == Volume.VOLUME_STATUS.ONLINE ? guiHelper + .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createTransportTypeField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Transport Type: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getTransportTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createNumOfDisksField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Number of Disks: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getNumOfDisks(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createStripeCountField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Stripe Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getStripeCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createReplicaCountField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Replica Count: ", SWT.NONE); + toolkit.createLabel(section, "" + volume.getReplicaCount(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void createVolumeTypeField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Volume Type: ", SWT.NONE); + toolkit.createLabel(section, volume.getVolumeTypeStr(), SWT.NONE); + toolkit.createLabel(section, "", SWT.NONE); + } + + private void createVolumeAlertsSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Alerts", null, 3, false); + toolkit.createLabel(section, "Volume related alerts will be displayed here"); + } + + private void createVolumeMountingInfoSection(final Volume volume, FormToolkit toolkit, final ScrolledForm form) { + Composite section = guiHelper.createSection(form, toolkit, "Mounting Information", null, 3, false); + toolkit.createLabel(section, "Information about mounting the\nvolume will be printed here"); + } + + private GridData createDefaultLayoutData() { + GridData layoutData = new GridData(); + layoutData.minimumWidth = 150; + layoutData.widthHint = 150; + return layoutData; + } + + private void createAccessControlField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "Access Control: ", SWT.NONE); + Text accessControlText = toolkit.createText(section, volume.getAccessControlList()); + accessControlText.setLayoutData(createDefaultLayoutData()); + accessControlText.setEnabled(false); + createChangeLinkForAccessControl(volume, toolkit, section, accessControlText); + } + + private void createChangeLinkForAccessControl(final Volume volume, FormToolkit toolkit, Composite section, + final Text accessControlText) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + // TODO: Validation of entered text + volume.setAccessControlList(accessControlText.getText()); + accessControlText.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + accessControlText.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (accessControlText.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private void createNASProtocolField(final Volume volume, FormToolkit toolkit, Composite section) { + toolkit.createLabel(section, "NAS Protocols: ", SWT.NONE); + + Composite nasProtocolsComposite = toolkit.createComposite(section); + nasProtocolsComposite.setLayout(new FillLayout()); + + createCheckbox(toolkit, nasProtocolsComposite, "Gluster", true); + final Button nfsCheckBox = createCheckbox(toolkit, nasProtocolsComposite, "NFS", volume.getNASProtocols().contains(NAS_PROTOCOL.NFS)); + + createChangeLinkForNASProtocol(volume, toolkit, section, nfsCheckBox); + } + + private void createChangeLinkForNASProtocol(final Volume volume, FormToolkit toolkit, Composite section, + final Button nfsCheckBox) { + final Hyperlink changeLink = toolkit.createHyperlink(section, "change", SWT.NONE); + changeLink.addHyperlinkListener(new HyperlinkAdapter() { + + private void finishEdit() { + // TODO: Update value to back-end + if (nfsCheckBox.getSelection()) { + volume.enableNFS(); + } else { + volume.disableNFS(); + } + nfsCheckBox.setEnabled(false); + changeLink.setText("change"); + } + + private void startEdit() { + nfsCheckBox.setEnabled(true); + changeLink.setText("update"); + } + + @Override + public void linkActivated(HyperlinkEvent e) { + if (nfsCheckBox.isEnabled()) { + // we were already in edit mode. + finishEdit(); + } else { + // Get in to edit mode + startEdit(); + } + } + }); + } + + private Button createCheckbox(FormToolkit toolkit, Composite parent, String label, boolean selected) { + final Button checkBox = toolkit.createButton(parent, label, SWT.CHECK); + checkBox.setEnabled(false); + checkBox.setSelection(selected); + return checkBox; + } + + private void createVolumePropertiesTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, volume.getName() + " - Properties", IImageKeys.VOLUME); + final ScrolledForm form = guiHelper.setupForm(volumeTab, toolkit, "Volume Properties [" + volume.getName() + "]"); + createVolumePropertiesSection(volume, toolkit, form); + createVolumeMountingInfoSection(volume, toolkit, form); + createVolumeAlertsSection(volume, toolkit, form); + + volumeTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeLogsTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, "Logs", IImageKeys.VOLUME); + VolumeLogsPage logsPage = new VolumeLogsPage(volumeTab, SWT.NONE, volume); + + volumeTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeDisksTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + Composite volumeDisksTab = guiHelper.createTab(tabFolder, "Disks", IImageKeys.VOLUME); + DisksPage page = new DisksPage(volumeDisksTab, SWT.NONE, site, volume.getDisks()); + + volumeDisksTab.layout(); // IMP: lays out the form properly + } + + private void createVolumeOptionsTab(Volume volume, TabFolder tabFolder, FormToolkit toolkit) { + Composite volumeTab = guiHelper.createTab(tabFolder, "Options", IImageKeys.VOLUME); + VolumeOptionsPage page = new VolumeOptionsPage(volumeTab, SWT.NONE, volume); + + volumeTab.layout(); // IMP: lays out the form properly + } + + @Override + public void createTabs(Entity entity, TabFolder tabFolder, FormToolkit toolkit, IWorkbenchSite site) { + createVolumePropertiesTab((Volume) entity, tabFolder, toolkit); + createVolumeDisksTab((Volume) entity, tabFolder, toolkit, site); + createVolumeOptionsTab((Volume) entity, tabFolder, toolkit); + createVolumeLogsTab((Volume) entity, tabFolder, toolkit); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java new file mode 100644 index 00000000..d7ef44ac --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/ClusterAdapterFactory.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.navigator; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterDataModel; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; + +public class ClusterAdapterFactory implements IAdapterFactory { + private IWorkbenchAdapter entityAdapter = new IWorkbenchAdapter() { + + @Override + public Object getParent(Object o) { + return ((Entity) o).getParent(); + } + + @Override + public String getLabel(Object o) { + return ((Entity)o).getName(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public ImageDescriptor getImageDescriptor(Object object) { + String iconPath = null; + + if(object instanceof GlusterDataModel || object instanceof Cluster) { + iconPath = IImageKeys.CLUSTER; + } + + if(object instanceof EntityGroup) { + Class<? extends Entity> entityType = ((EntityGroup) object).getEntityType(); + if(entityType == Volume.class) { + iconPath = IImageKeys.VOLUMES; + } else { + iconPath = IImageKeys.SERVERS; + } + } + + if(object instanceof Volume) { + iconPath = IImageKeys.VOLUME; + } + + if(object instanceof Server || object instanceof GlusterServer) { + iconPath = IImageKeys.SERVER; + } + + return AbstractUIPlugin.imageDescriptorFromPlugin( + Application.PLUGIN_ID, iconPath); + } + + @Override + public Object[] getChildren(Object o) { + return ((Entity)o).getChildren().toArray(); + } + }; + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (adapterType == IWorkbenchAdapter.class) { + if (adaptableObject instanceof Entity) { + return entityAdapter; + } + } + return null; + } + + @SuppressWarnings("rawtypes") + @Override + public Class[] getAdapterList() { + return new Class[] { IWorkbenchAdapter.class }; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java new file mode 100644 index 00000000..4cdc2e66 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/navigator/NavigationTreeLabelDecorator.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.navigator; + +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ILightweightLabelDecorator; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.Application; +import com.gluster.storage.management.gui.IImageKeys; + +public class NavigationTreeLabelDecorator implements ILightweightLabelDecorator { + + @Override + public void addListener(ILabelProviderListener listener) { + } + + @Override + public void dispose() { + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return false; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + } + + @SuppressWarnings("rawtypes") + @Override + public void decorate(Object element, IDecoration decoration) { + if (element instanceof Volume) { + Volume volume = (Volume) element; + if (volume.getStatus() == Volume.VOLUME_STATUS.OFFLINE) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_OFFLINE)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE)); + } + } + + if (element instanceof GlusterServer) { + GlusterServer server = (GlusterServer) element; + if (server.getStatus() == GlusterServer.SERVER_STATUS.OFFLINE) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_OFFLINE)); + } else { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_ONLINE)); + } + } + + if (element instanceof Server) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR)); + } + + if(element instanceof EntityGroup && ((EntityGroup)element).getEntityType() == Server.class) { + decoration.addOverlay(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, + IImageKeys.OVERLAY_STAR)); + } + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java new file mode 100644 index 00000000..6be3e78c --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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 org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.ServerTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class ServersPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum SERVER_TABLE_COLUMN_INDICES { + NAME, IP_ADDRESSES, NUM_OF_DISKS, TOTAL_DISK_SPACE + }; + + private static final String[] SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", "IP Address(es)", "Number of Disks", "Total Disk Space (GB)" }; + + // public enum SERVER_DISK_TABLE_COLUMN_INDICES { + // NAME, NUM_OF_CPUS, CPU_USAGE, TOTAL_MEMORY, MEMORY_IN_USE, TOTAL_DISK_SPACE, DISK_SPACE_IN_USE + // }; + // + // private static final String[] SERVER_TABLE_COLUMN_NAMES = new String[] { "Name", + // "Number\nof CPUs", "CPU\nUsage (%)", "Total\nMemory (GB)", "Memory\nIn Use (GB)", + // "Total Disk\n Space (GB)", "Disk Space\nin Use (GB)"}; + + public ServersPage(final Composite parent, IWorkbenchSite site, EntityGroup<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 + + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + } + + public void setInput(EntityGroup<Server> servers) { + tableViewer.setInput(servers); + tableViewer.refresh(); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupServerTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(false); + + TableColumnLayout tableColumnLayout = guiHelper.createTableColumnLayout(table, SERVER_TABLE_COLUMN_NAMES); + parent.setLayout(tableColumnLayout); + + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NAME, SWT.CENTER, 70); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.IP_ADDRESSES, SWT.CENTER, 100); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.NUM_OF_DISKS, SWT.CENTER, 70); + setColumnProperties(table, SERVER_TABLE_COLUMN_INDICES.TOTAL_DISK_SPACE, SWT.CENTER, 70); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.NUM_OF_CPUS, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.CPU_USAGE, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.TOTAL_MEMORY, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.MEMORY_IN_USE, SWT.CENTER, 90); + // setColumnProperties(table, SERVER_DISK_TABLE_COLUMN_INDICES.DISK_SPACE_IN_USE, SWT.CENTER, 90); + } + + private TableViewer createServerTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + // TableViewer tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new ServerTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider<Server>()); + + setupServerTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NONE); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private void setupPage(IWorkbenchSite site, EntityGroup<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); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + private void setColumnProperties(Table table, SERVER_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java new file mode 100644 index 00000000..9e25a018 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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 org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchSite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.gluster.storage.management.core.model.EntityGroup; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.EntityGroupContentProvider; +import com.gluster.storage.management.gui.VolumeTableLabelProvider; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class VolumesPage extends Composite { + + private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); + private TableViewer tableViewer; + private GUIHelper guiHelper = GUIHelper.getInstance(); + + public enum VOLUME_TABLE_COLUMN_INDICES { + NAME, VOLUME_TYPE, NUM_OF_DISKS, TRANSPORT_TYPE, VOLUME_STATUS + }; + + private static final String[] VOLUME_TABLE_COLUMN_NAMES = new String[] { "Name", + "Volume Type", "Number of\nDisks", "Transport Type", "Status" }; + + public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup<Volume> volumes) { + super(parent, SWT.NONE); + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + toolkit.dispose(); + } + }); + + toolkit.adapt(this); + toolkit.paintBordersFor(this); + + setupPageLayout(); + setupVolumeTableViewer(site, volumes); + + parent.layout(); // Important - this actually paints the table + + /** + * Ideally not required. However the table viewer is not getting laid out properly on performing + * "maximize + restore" So this is a hack to make sure that the table is laid out again on re-size of the window + */ + addPaintListener(new PaintListener() { + + @Override + public void paintControl(PaintEvent e) { + parent.layout(); + } + }); + } + + public void addDoubleClickListener(IDoubleClickListener listener) { + tableViewer.addDoubleClickListener(listener); + } + + private void setupPageLayout() { + final GridLayout layout = new GridLayout(1, false); + layout.verticalSpacing = 10; + layout.marginTop = 10; + setLayout(layout); + } + + private void setupVolumeTable(Composite parent, Table table) { + table.setHeaderVisible(true); + table.setLinesVisible(true); + + TableColumnLayout columnLayout = guiHelper.createTableColumnLayout(table, VOLUME_TABLE_COLUMN_NAMES); + parent.setLayout(columnLayout); + + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.VOLUME_STATUS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.NUM_OF_DISKS, SWT.CENTER, 50); + setColumnProperties(table, VOLUME_TABLE_COLUMN_INDICES.TRANSPORT_TYPE, SWT.CENTER, 70); + } + + private TableViewer createVolumeTableViewer(Composite parent) { + TableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + tableViewer.setLabelProvider(new VolumeTableLabelProvider()); + tableViewer.setContentProvider(new EntityGroupContentProvider<Volume>()); + + setupVolumeTable(parent, tableViewer.getTable()); + + return tableViewer; + } + + private Composite createTableViewerComposite() { + Composite tableViewerComposite = new Composite(this, SWT.NO); + tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + return tableViewerComposite; + } + + private void setupVolumeTableViewer(IWorkbenchSite site, EntityGroup<Volume> volumes) { + Text filterText = guiHelper.createFilterText(toolkit, this); + + Composite tableViewerComposite = createTableViewerComposite(); + tableViewer = createVolumeTableViewer(tableViewerComposite); + site.setSelectionProvider(tableViewer); + + // Create a case insensitive filter for the table viewer using the filter text field + guiHelper.createFilter(tableViewer, filterText, false); + tableViewer.setInput(volumes); + } + + /** + * Sets properties for alignment and weight of given column of given table + * + * @param table + * @param columnIndex + * @param alignment + * @param weight + */ + public void setColumnProperties(Table table, VOLUME_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) { + TableColumn column = table.getColumn(columnIndex.ordinal()); + column.setAlignment(alignment); + + TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout(); + tableColumnLayout.setColumnData(column, new ColumnWeightData(weight)); + } + + public void setInput(EntityGroup<Volume> volumes) { + tableViewer.setInput(volumes); + tableViewer.refresh(); + } +} diff --git a/src/com.gluster.storage.management.releng/.project b/src/com.gluster.storage.management.releng/.project new file mode 100644 index 00000000..f4723731 --- /dev/null +++ b/src/com.gluster.storage.management.releng/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.releng</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.pde.FeatureBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.FeatureNature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.releng/build.properties b/src/com.gluster.storage.management.releng/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/src/com.gluster.storage.management.releng/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery new file mode 100644 index 00000000..7bb4b868 --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.client.cquery @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="glustermc.rmap"> + <cq:rootRequest name="com.gluster.storage.management.core" componentType="osgi.bundle"/> +</cq:componentQuery> diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery new file mode 100644 index 00000000..a97d350d --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.core.cquery @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="glustermc.rmap"> + <cq:rootRequest name="com.gluster.storage.management.client" componentType="osgi.bundle"/> +</cq:componentQuery> diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery new file mode 100644 index 00000000..4d5dc425 --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gui.feature.webstart.cquery @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="glustermc.rmap"> + <cq:rootRequest name="com.gluster.storage.management.gui.feature.webstart" componentType="eclipse.feature"/> +</cq:componentQuery> diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery new file mode 100644 index 00000000..346b39bf --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="glustermc.rmap"> + <cq:rootRequest name="com.gluster.storage.management.server" componentType="unknown"/> +</cq:componentQuery> diff --git a/src/com.gluster.storage.management.releng/feature.xml b/src/com.gluster.storage.management.releng/feature.xml new file mode 100644 index 00000000..22a0938f --- /dev/null +++ b/src/com.gluster.storage.management.releng/feature.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<feature + id="com.gluster.storage.management.releng" + label="Releng" + version="1.0.0" + provider-name="Gluster Inc."> + + <description url="http://www.example.com/description"> + [Enter Feature Description here.] + </description> + + <copyright url="http://www.example.com/copyright"> + [Enter Copyright Description here.] + </copyright> + + <license url="http://www.example.com/license"> + [Enter License Description here.] + </license> + +</feature> diff --git a/src/com.gluster.storage.management.releng/gluster-management-console.target b/src/com.gluster.storage.management.releng/gluster-management-console.target new file mode 100644 index 00000000..e30fcf49 --- /dev/null +++ b/src/com.gluster.storage.management.releng/gluster-management-console.target @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?pde version="3.6"?> + +<target includeMode="feature" name="Gluster Storage Platform Target"> +<locations> +<location path="gmc-target/com.gluster.storage.management.gui.target/rcp.sdk.helios.SR1" type="Directory"/> +<location path="gmc-target/com.gluster.storage.management.gui.target/richclientgui.rcptoolbox" type="Directory"/> +<location path="gmc-target/com.gluster.storage.management.gui.target/birt.charts.helios" type="Directory"/> +<location path="gmc-target/com.gluster.storage.management.gui.target/delta.pack.helios" type="Directory"/> +</locations> +<targetJRE path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> +</target> diff --git a/src/com.gluster.storage.management.releng/glustermc.rmap b/src/com.gluster.storage.management.releng/glustermc.rmap new file mode 100644 index 00000000..e4048df6 --- /dev/null +++ b/src/com.gluster.storage.management.releng/glustermc.rmap @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0"> + <rm:locator searchPathRef="glustermc"/> + <rm:searchPath name="glustermc"> + <rm:provider componentTypes="osgi.bundle,eclipse.feature,unknown" readerType="local"> + <rm:uri format="file:///{0}/gmc-src/{1}/"> + <bc:propertyRef key="workspace.root"/> + <bc:propertyRef key="buckminster.component"/> + </rm:uri> + </rm:provider> + </rm:searchPath> +</rm:rmap> diff --git a/src/com.gluster.storage.management.releng/glustermc_build.properties b/src/com.gluster.storage.management.releng/glustermc_build.properties new file mode 100644 index 00000000..b808ec9d --- /dev/null +++ b/src/com.gluster.storage.management.releng/glustermc_build.properties @@ -0,0 +1,10 @@ +# Where all the output should go +buckminster.output.root=/tmp/buckminster/glustermc +# Where the temp files should go +buckminster.temp.root=/tmp/buckminster +# How .qualifier in versions should be replaced +qualifier.replacement.*=generator:lastRevision + +target.os=linux +target.ws=gtk +target.arch=x86_64 diff --git a/src/com.gluster.storage.management.server.scripts/.project b/src/com.gluster.storage.management.server.scripts/.project new file mode 100644 index 00000000..beda33b7 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.server.scripts</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.python.pydev.PyDevBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.python.pydev.pythonNature</nature> + </natures> +</projectDescription> diff --git a/src/com.gluster.storage.management.server.scripts/.pydevproject b/src/com.gluster.storage.management.server.scripts/.pydevproject new file mode 100644 index 00000000..0a912df5 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/.pydevproject @@ -0,0 +1,10 @@ +<?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 3.0</pydev_property> +<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> +<path>/com.gluster.storage.management.server.scripts/src</path> +</pydev_pathproperty> +</pydev_project> diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Commands.py b/src/com.gluster.storage.management.server.scripts/src/common/Commands.py new file mode 100644 index 00000000..c728b565 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Commands.py @@ -0,0 +1,78 @@ +COMMAND_CREATE_VOLUME = "create-volume" +COMMAND_DELETE_VOLUME = "delete-volume" +COMMAND_START_VOLUME = "start-volume" +COMMAND_STOP_VOLUME = "stop-volume" +COMMAND_GET_VOLUME_HEALTH_STATUS = "get-volume-health-status" +COMMAND_GET_VOLUME_LIST = "get-volume-list" +COMMAND_GET_VOLUME_LOG = "get-volume-log" +COMMAND_CLEAR_VOLUME_LOGS = "clear-volume-logs" +COMMAND_GET_VOLUME_PROPERTY = "get-volume-property" +COMMAND_SET_VOLUME_PROPERTY = "set-volume-property" +COMMAND_GET_VOLUME_STATUS = "get-volume-status" +COMMAND_DOWNLOAD_VOLUME_LOGS = "download-volume-logs" +COMMAND_DELETE_SERVER = "delete-server" +COMMAND_GET_SERVER_DATE = "get-server-date" +COMMAND_GET_SERVER_VERSION_INFO = "get-server-version-info" +COMMAND_GET_INSTALLER_INFO = "get-installer-info" +COMMAND_GET_SERVER_LIST = "get-server-list" +COMMAND_GET_SERVER_SERVICE_STATUS = "get-server-service-status" +COMMAND_GET_STORAGE_SERVER_POOL_INFO = "get-storage-server-pool-info" +COMMAND_INSTALL_SERVER_BACKGROUND = "install-server-background" +COMMAND_PREPARE_DATA_DISK_BACKGROUND = "prepare-data-disk-background" +COMMAND_SET_SERVER_DATE = "set-server-date" +COMMAND_SET_SERVER_NETWORK_CONFIG = "set-server-network-config" +COMMAND_SET_STORAGE_SERVER_POOL_INFO = "set-storage-server-pool-info" +COMMAND_GET_SERVER_NETWORK_CONFIG = "get-server-network-config" +COMMAND_INSTALL_SERVER_STATUS = "install-server-status" +COMMAND_GET_SERVER_DISK_LIST = "get-server-disk-list" +COMMAND_PREPARE_DATA_DISK_STATUS = "prepare-data-disk-status" +COMMAND_GET_SERVER_SYSTEM_RESOURCE = "get-server-system-resource" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SHUTDOWN_SERVER = "shutdown-server" +COMMAND_GET_SERVER_STATUS = "get-server-status" +COMMAND_GET_SERVER_LOG = "get-server-log" +COMMAND_DOWNLOAD_SERVER_LOGS = "download-server-logs" +COMMAND_CLEAR_SERVER_LOGS = "clear-server-logs" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_GET_GSN_USER_INFO = "get-gsn-user-info" +COMMAND_SET_GSN_USER_INFO = "set-gsn-user-info" +COMMAND_GET_GLUSTER_UPDATE_INFO = "get-gluster-update-info" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_BACKGROUND = "download-gluster-update-background" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_STATUS = "download-gluster-update-status" +COMMAND_INSTALL_GLUSTER_UPDATE = "install-gluster-update" +COMMAND_EXPORT_CONFIG = "export-config" +COMMAND_IMPORT_CONFIG = "import-config" +COMMAND_SET_SYSTEM_PASSWORD = "set-system-password" +COMMAND_GET_SERVER_VOLUME_LIST = "get-server-volume-list" +COMMAND_RECONFIGURE_VOLUME = "reconfigure-volume" +COMMAND_SET_SERVER_DIRECTORY_SERVICE_CONFIG = "set-server-directory-service-config" +COMMAND_GET_SERVER_DIRECTORY_SERVICE_CONFIG = "get-server-directory-service-config" +COMMAND_JOIN_SERVER_TO_DIRECTORY_SERVICE = "join-server-to-directory-service" +COMMAND_SET_SERVER_TIME_CONFIG = "set-server-time-config" +COMMAND_GET_SERVER_TIME_CONFIG = "get-server-time-config" +COMMAND_LOGIN = "login" +COMMAND_LOGOUT = "logout" +COMMAND_GET_LOGIN_STATUS = "get-login-status" +COMMAND_GET_SERVER_TRANSPORT_LIST = "get-server-transport-list" +COMMAND_ADD_SERVER_PARTITION = "add-server-partition" +COMMAND_ADD_VOLUME_USER = "add-volume-user" +COMMAND_GET_PARTITION_VOLUME_LIST = "get-partition-volume-list" +COMMAND_GET_VOLUME_USER_INFO = "get-volume-user-info" +COMMAND_GET_VOLUME_USER_LIST = "get-volume-user-list" +COMMAND_MIGRATE_PARTITION_BACKGROUND = "migrate-partition-background" +COMMAND_MIGRATE_PARTITION_STATUS = "migrate-partition-status" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_BACKGROUND = "migrate-volume-server-partition-background" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_STATUS = "migrate-volume-server-partition-status" +COMMAND_REMOVE_SERVER_PARTITION = "remove-server-partition" +COMMAND_REMOVE_VOLUME_USER = "remove-volume-user" +COMMAND_RENAME_VOLUME_USER = "rename-volume-user" +COMMAND_RENAME_VOLUME = "rename-volume" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SET_VOLUME_USER_PASSWORD = "set-volume-user-password" +COMMAND_STOP_PARTITION_MIGRATION = "stop-partition-migration" +COMMAND_STOP_VOLUME_SERVER_PARTITION_MIGRATION = "stop-volume-server-partition-migration" +COMMAND_GET_SERVER_DISK_INFO = "get-server-disk-info" +COMMAND_INITIALIZE_SERVER_DISK = "initialize-server-disk" +COMMAND_SET_SERVER_COUNT = "set-server-count" +COMMAND_GET_SERVER_COUNT = "get-server-count" diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Common.py b/src/com.gluster.storage.management.server.scripts/src/common/Common.py new file mode 100644 index 00000000..60f200fe --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Common.py @@ -0,0 +1,34 @@ +# Copyright (c) 2009 Gluster, Inc. <http://www.gluster.com>
+# This file is part of GlusterSP.
+#
+# GlusterSP is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+#
+# GlusterSP is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import sys
+import syslog
+
+def log(priority, message=None):
+ if type(priority) == type(""):
+ logPriority = syslog.LOG_INFO
+ logMessage = priority
+ else:
+ logPriority = priority
+ logMessage = message
+ if not logMessage:
+ return
+ #if Globals.DEBUG:
+ # sys.stderr.write(logMessage)
+ else:
+ syslog.syslog(logPriority, logMessage)
+ return
diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Globals.py b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py new file mode 100644 index 00000000..365d4af7 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py @@ -0,0 +1,119 @@ +# Copyright (C) 2010 Gluster, Inc. <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/>. + +MULTICAST_GROUP = '224.224.1.1' +MULTICAST_PORT = 5353 +GLUSTER_PLATFORM_VERSION = "3.2" + +## System configuration constants +SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" +DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" + +FSTAB_FILE = "/etc/fstab" +NFS_EXPORTS_FILE = "/etc/exports" +SAMBA_CONF_FILE = "/etc/samba/smb.conf" +TIMEZONE_FILE = "/etc/timezone" +ZONEINFO_DIR = "/usr/share/zoneinfo" +LOCALTIME_FILE = "/etc/localtime" +KERBEROS_CONF_FILE = "/etc/krb5.conf" +NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" +NTP_CONF_FILE = "/etc/ntp.conf" +MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" +SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" +RESOLV_CONF_FILE = "/etc/resolv.conf" +DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" +LIVE_MODE_FILE = "/etc/live" +ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" + +DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" +DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" +## + +## Base constants +MAX_PARTITION_SIZE = 16777216 # 16 TB +OS_PARTITION_SIZE = 4000 # 4 GB +SESSION_TIMEOUT = 1800 # 30 minutes +SERVER_AGENT_PORT = 50000 + +BOOT_PARTITION_LABEL = "GLUSTEROS" +DATA_PARTITION_LABEL = "GLUSTERDATA" +VOLUME_USER_DESCRIPTION = "Gluster Volume User" +SERVER_AGENT_RUN_USERNAME = "transport" +INSTALLER_SERVER_NAME = "$installer$" + +GLUSTER_BASE_DIR = "/GLUSTER" +GLUSTER_LUN_DIR = "/data" +REEXPORT_DIR = "/reexport" +NFS_EXPORT_DIR = "/nfs" +CIFS_EXPORT_DIR = "/cifs" +WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" +UPDATES_DIR = "/UPDATES" +TRANSPORT_HOME_DIR = "/transport" +GLUSTERFS_LOG_DIR = "/var/log/glusterfs" +LOG_DIR = "/var/log/platform" + +GLUSTER_UPDATES_FILE = "updates.xml" +INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" +INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" +LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" +PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" +## + +## Derived constants +GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" +GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" +VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" +SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" +DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" +INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME + +GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" +GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" +GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" +GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" +GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" +TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" +SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" +SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" +GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" +GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" + +VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" + +GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" +INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" +INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" +INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" + +SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" + +GENERAL_LOG_FILE = LOG_DIR + "/general.log" +INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" +SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" +TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" +## + + +## Global variables +## TODO: These should be removed +DOWNLOAD_GLUSTER_UPDATE_PROCESS = None +DOWNLOAD_GLUSTER_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None +REQUEST_MAP = {} +VERSION_DICTONARY = {} +## diff --git a/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py b/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py new file mode 100644 index 00000000..1ce1b132 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/NetworkUtils.py @@ -0,0 +1,422 @@ +# Copyright (c) 2010 Gluster, Inc. <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 + +if not "/usr/share/system-config-network/" in sys.path: + sys.path.append("/usr/share/system-config-network") + +import os +import tempfile +import Globals + +from Utils import * +from netconfpkg.NCHardwareList import getHardwareList + +def readHostFile(fileName=None): + hostEntryList = [] + if not fileName: + fileName = "/etc/hosts" + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + hostEntryList.append({tokens[0] : tokens[1:]}) + return hostEntryList + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeHostFile(hostEntryList, fileName=None): + if fileName: + hostFile = fileName + else: + hostFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(hostFile, "w") + for host in hostEntryList: + fp.write("%s\t%s\n" % (host.keys()[0], " ".join(host.values()[0]))) + fp.close() + if hostFile == fileName: + return True + except IOError: + log("failed to write %s file" % hostFile) + return False + if runCommandFG("mv -f %s /etc/hosts" % hostFile, root=True) != 0: + log("failed to rename file %s to /etc/hosts" % hostFile) + return False + return True + + +def readResolvConfFile(fileName=None, includeLocalHost=False): + nameServerList = [] + domain = None + searchDomain = None + if not fileName: + fileName = Globals.RESOLV_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + if tokens[0].upper() == "NAMESERVER": + if includeLocalHost == False and tokens[1] == "127.0.0.1": + continue + nameServerList.append(tokens[1]) + continue + if tokens[0].upper() == "DOMAIN": + domain = tokens[1:] + continue + if tokens[0].upper() == "SEARCH": + searchDomain = tokens[1:] + continue + return nameServerList, domain, searchDomain + except IOError: + log("failed to read %s file" % fileName) + return None, None, None + + +def writeResolvConfFile(nameServerList, domain, searchDomain, fileName=None, appendLocalHost=True): + if fileName: + resolvConfFile = fileName + else: + resolvConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(resolvConfFile, "w") + if appendLocalHost: + fp.write("nameserver 127.0.0.1\n") + for nameServer in nameServerList: + fp.write("nameserver %s\n" % nameServer) + if domain: + fp.write("domain %s\n" % " ".join(domain)) + if searchDomain: + fp.write("search %s\n" % " ".join(searchDomain)) + fp.close() + if resolvConfFile == fileName: + return True + except IOError: + log("failed to write %s file" % resolvConfFile) + return False + if runCommandFG("mv -f %s %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE), root=True) != 0: + log("failed to rename file %s to %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE)) + return False + return True + + +def readIfcfgConfFile(deviceName, root=""): + conf = {} + fileName = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + try: + for line in open(fileName): + tokens = line.split("#")[0].split("=") + if len(tokens) != 2: + continue + conf[tokens[0].strip().lower()] = tokens[1].strip() + return conf + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeIfcfgConfFile(deviceName, conf, root="", deviceFile=None): + if not deviceFile: + deviceFile = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + if root: + ifcfgConfFile = deviceFile + else: + ifcfgConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(ifcfgConfFile, "w") + for key in conf.keys(): + if key == "description": + fp.write("#%s=%s\n" % (key.upper(), conf[key])) + continue + if key in ['link', 'mode']: + continue + if conf["device"].startswith("bond") and key in ['hwaddr', 'master', 'slave']: + continue + if key == "slave" and conf['master']: + fp.write("SLAVE=yes\n") + continue + if key == "onboot": + if conf[key] == True: + fp.write("ONBOOT=yes\n") + elif isString(conf[key]) and conf[key].upper() == "YES": + fp.write("ONBOOT=yes\n") + else: + fp.write("ONBOOT=no\n") + continue + if not conf[key]: + continue + fp.write("%s=%s\n" % (key.upper(), conf[key])) + fp.close() + if ifcfgConfFile == deviceFile: + return True + except IOError: + log("failed to write %s file" % ifcfgConfFile) + return False + if runCommandFG("mv -f %s %s" % (ifcfgConfFile, deviceFile), root=True) != 0: + log("failed to rename file %s to %s" % (ifcfgConfFile, deviceFile)) + return False + return True + + +def getLinkStatus(deviceName): + return True + ## ethtool takes very long time to respond. So its disabled now + rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) + if rv["Status"] != 0: + return False + for line in rv["Stdout"].split("\n"): + tokens = line.strip().split(":") + if tokens[0].upper() == "LINK DETECTED": + if tokens[1].strip().upper() == "YES": + return True + else: + return False + return False + + +def getBondMode(deviceName, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].split() + if len(tokens) < 4: + continue + if tokens[0].upper() == "OPTIONS" and tokens[1] == deviceName: + if tokens[2].startswith("mode="): + return tokens[2].split("=")[1] + if tokens[3].startswith("mode="): + return tokens[3].split("=")[1] + if tokens[4].startswith("mode="): + return tokens[4].split("=")[1] + if tokens[5].startswith("mode="): + return tokens[5].split("=")[1] + return None + except IOError: + log("failed to read %s file" % fileName) + return None + + +def setBondMode(deviceName, mode, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + tempFileName = getTempFileName() + try: + fp = open(tempFileName, "w") + lines = open(fileName).readlines() + except IOError: + log("unable to open file %s" % Globals.MODPROBE_CONF_FILE) + return False + for line in lines: + tokens = line.split() + if len(tokens) > 1 and "OPTIONS" == tokens[0].upper() and "BOND" in tokens[1].upper() and deviceName == tokens[1]: + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + deviceName = None + continue + fp.write(line) + if deviceName: + fp.write("alias %s bonding\n" % deviceName) + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + fp.close() + if runCommandFG(["mv", "-f", tempFileName, fileName], root=True) != 0: + log("unable to move file from %s to %s" % (tempFileName, fileName)) + return False + return True + +def getNetDeviceList(root=""): + netDeviceList = [] + for device in getHardwareList(): + netDevice = {} + netDevice["device"] = None + netDevice["description"] = None + netDevice["hwaddr"] = None + netDevice["type"] = None + netDevice["onboot"] = None + netDevice["bootproto"] = None + netDevice["ipaddr"] = None + netDevice["netmask"] = None + netDevice["gateway"] = None + netDevice["peerdns"] = None + netDevice["autodns"] = None + netDevice["dns1"] = None + netDevice["dns2"] = None + netDevice["dns3"] = None + netDevice["master"] = None + netDevice["slave"] = None + netDevice["nmcontrolled"] = None + netDevice["link"] = None + netDevice["mode"] = None + + netDevice["device"] = device.Name + netDevice["description"] = device.Description + netDevice["type"] = device.Type + netDevice["link"] = getLinkStatus(device.Name) + netDevice["mode"] = getBondMode(device.Name, root + Globals.MODPROBE_CONF_FILE) + try: + netDevice["hwaddr"] = open("/sys/class/net/%s/address" % device.Name).read().strip() + except IOError: + pass + netDeviceList.append(netDevice) + + conf = readIfcfgConfFile(device.Name, root) + if not conf: + continue + try: + netDevice["onboot"] = conf["onboot"] + except KeyError: + pass + try: + netDevice["bootproto"] = conf["bootproto"] + except KeyError: + pass + try: + netDevice["ipaddr"] = conf["ipaddr"] + except KeyError: + pass + try: + netDevice["netmask"] = conf["netmask"] + except KeyError: + pass + try: + netDevice["gateway"] = conf["gateway"] + except KeyError: + pass + try: + netDevice["peerdns"] = conf["peerdns"] + except KeyError: + pass + try: + netDevice["autodns"] = conf["autodns"] + except KeyError: + pass + try: + netDevice["dns1"] = conf["dns1"] + except KeyError: + pass + try: + netDevice["dns2"] = conf["dns2"] + except KeyError: + pass + try: + netDevice["dns3"] = conf["dns3"] + except KeyError: + pass + try: + netDevice["master"] = conf["master"] + except KeyError: + pass + try: + netDevice["slave"] = conf["slave"] + except KeyError: + pass + try: + netDevice["nmcontrolled"] = conf["nmcontrolled"] + except KeyError: + pass + + return netDeviceList + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + ## for deviceName in bondDevices: + ## if deviceName in linkedBondList: + ## if deviceName in sysConfigDeviceList: + ## deviceList[deviceName] = sysConfigDeviceList[deviceName] + ## else: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + ## continue + ## if len(ethDevices) > 2: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + + +def configureDhcpServer(serverIpAddress, dhcpIpAddress): + tmpDhcpConfFile = tempfile.mktemp(prefix="GSPSA") + + serverPortString = "68" + try: + for arg in open("/proc/cmdline").read().strip().split(): + token = arg.split("=") + if token[0] == "dhcp": + serverPortString = token[1] + break + except IOError: + log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") + try: + serverPort = int(serverPortString) + except ValueError: + log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) + serverPort = 68 + + try: + fp = open(tmpDhcpConfFile, "w") + fp.write("bind-interfaces\n") + fp.write("except-interface=lo\n") + fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) + fp.write("dhcp-lease-max=1\n") + fp.write("dhcp-alternate-port=%s\n" % serverPort) + fp.write("dhcp-leasefile=%s\n" % Globals.DNSMASQ_LEASE_FILE) + #fp.write("server=%s\n" % serverIpAddress) + #fp.write("dhcp-script=/usr/sbin/server-info\n") + fp.close() + except IOError: + log(syslog.LOG_ERR, "unable to write dnsmasq dhcp configuration %s" % tmpDhcpConfFile) + return False + if runCommandFG("mv -f %s %s" % (tmpDhcpConfFile, Globals.DNSMASQ_DHCP_CONF_FILE), root=True) != 0: + log(syslog.LOG_ERR, "unable to copy dnsmasq dhcp configuration to %s" % Globals.DNSMASQ_DHCP_CONF_FILE) + return False + return True + + +def isDhcpServer(): + return os.path.exists(Globals.DNSMASQ_DHCP_CONF_FILE) + + +def getDhcpServerStatus(): + if runCommandFG("service dnsmasq status", root=True) == 0: + return True + return False + + +def startDhcpServer(): + if runCommandFG("service dnsmasq start", root=True) == 0: + return True + return False + + +def stopDhcpServer(): + if runCommandFG("service dnsmasq stop", root=True) == 0: + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return True + return False + + +def restartDhcpServer(): + stopDhcpServer() + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return startDhcpServer() + + +def reloadDhcpServer(): + if runCommandFG("service dnsmasq reload", root=True) == 0: + return True + return False diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py b/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Protocol.py @@ -0,0 +1,438 @@ +# Copyright (C) 2009 Gluster, Inc. <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.scripts/src/common/Utils.py b/src/com.gluster.storage.management.server.scripts/src/common/Utils.py new file mode 100644 index 00000000..c605eecd --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/Utils.py @@ -0,0 +1,704 @@ +# Copyright (c) 2010 Gluster, Inc. <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 + + +RUN_COMMAND_ERROR = -1024 +LOG_SYSLOG = 1 +SYSLOG_REQUIRED = False +LOG_FILE_NAME = None +LOG_FILE_OBJ = None + + +def _getLogCode(priority): + if syslog.LOG_EMERG == priority: + return "M" + elif syslog.LOG_ALERT == priority: + return "A" + elif syslog.LOG_CRIT == priority: + return "C" + elif syslog.LOG_ERR == priority: + return "E" + elif syslog.LOG_WARNING == priority: + return "W" + elif syslog.LOG_NOTICE == priority: + return "N" + elif syslog.LOG_INFO == priority: + return "I" + elif syslog.LOG_DEBUG == priority: + return "D" + else: # UNKNOWN + return "X" + + +def setLogFile(fileName): + global LOG_FILE_NAME + + if fileName: + LOG_FILE_NAME = fileName + return True + return False + + +def closeLog(): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if SYSLOG_REQUIRED: + syslog.closelog() + SYSLOG_REQUIRED = False + return True + + if LOG_FILE_OBJ: + try: + LOG_FILE_OBJ.close() + LOG_FILE_OBJ = None + except IOError, e: + sys.stderr.write("Failed to close file: %s\n" % e) + return False + return True + + +def openLog(fileName=None): + global LOG_FILE_NAME + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if fileName == LOG_SYSLOG: + syslog.openlog(os.path.basename(sys.argv[0])) + SYSLOG_REQUIRED = True + return True + + if fileName: + LOG_FILE_NAME = fileName + + if not LOG_FILE_NAME: + return False + + closeLog() + + try: + LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") + except IOError, e: + sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) + return False + return True + + +def log(priority, message=None): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + stack = inspect.stack()[1] + if stack[3] == "<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(): + return tempfile.mkstemp(prefix="GSP_")[1] + + +def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, + shell=False, root=None): + log("runCommandBG(): Trying to execute command [%s]" % command) + + if shell: + if not isString(command): + return None + else: + if isString(command): + command = command.split() + + if root == True: + if shell: + command = "sudo " + command + else: + command = ['sudo'] + command + elif isString(root): + if shell: + command = "sudo -u " + root + " " + command + else: + command = ['sudo', '-u', root] + command + + if not stdinFileObj: + stdinFileObj=subprocess.PIPE + if not stdoutFileObj: + stdoutFileObj=subprocess.PIPE + if not stderrFileObj: + stderrFileObj=subprocess.PIPE + + try: + process = subprocess.Popen(command, + bufsize=-1, + stdin=stdinFileObj, + stdout=stdoutFileObj, + stderr=stderrFileObj, + shell=shell) + return process + except OSError, e: + log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) + return None + + +def runCommand(command, + input='', output=False, + shell=False, root=None): + rv = {} + rv["Status"] = RUN_COMMAND_ERROR + rv["Stdout"] = None + rv["Stderr"] = None + + try: + stdinFileName = getTempFileName() + stdinFileObj = open(stdinFileName, "w") + stdinFileObj.write(input) + stdinFileObj.close() + stdinFileObj = open(stdinFileName, "r") + + stdoutFileName = getTempFileName() + stdoutFileObj = open(stdoutFileName, "w") + + stderrFileName = getTempFileName() + stderrFileObj = open(stderrFileName, "w") + except IOError, e: + log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) + if output: + return rv + return rv["Status"] + + stdoutContent = None + stderrContent = None + + process = runCommandBG(command, + stdinFileObj=stdinFileObj, + stdoutFileObj=stdoutFileObj, + stderrFileObj=stderrFileObj, + shell=shell, root=root) + if process: + rv['Status'] = process.wait() + rv['Stdout'] = open(stdoutFileName).read() + rv['Stderr'] = open(stderrFileName).read() + + os.remove(stdinFileName) + os.remove(stdoutFileName) + os.remove(stderrFileName) + + log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) + + if output: + return rv + return rv["Status"] + + +def runCommandFG(command, stdout=False, stderr=False, + shell=False, root=None): + if stdout or stderr: + output = True + else: + output = False + return runCommand(command, output=output, shell=shell, root=root) + + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + + +def computeHostName(hostName): + if not hostName: + return False + + hostPrefix = "" + for i in range(len(hostName), 0, -1): + pos = i - 1 + if hostName[pos].isdigit(): + continue + break + hostPrefix = hostName[:pos+1] + try: + hostIndex = int(hostName[pos+1:]) + except ValueError: + hostIndex = 0 + # TODO: Check the availablity of the (server) name + return "%s%s" % (hostPrefix, hostIndex + 1) + + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + + +def getDownloadStatus(fileName): + try: + lines = [line for line in open(fileName) + if "saved" in line or "%" in line] + except IOError: + return 0 + if not lines: + return 0 + if "saved" in lines[-1]: + return 100 + return lines[-1].split("%")[0].split()[-1] + + +def getMeminfo(): + """-> dict of data from meminfo (str:int). + Values are in kilobytes. + """ + import re + re_parser = re.compile(r'^(?P<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.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm b/src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm Binary files differnew file mode 100644 index 00000000..4b07c4e4 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/common/system-config-network-tui-1.3.99.18-1.el5.noarch.rpm diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py b/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py new file mode 100644 index 00000000..6d867d9e --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/Agent.py @@ -0,0 +1,118 @@ +# Copyright (C) 2009 Gluster, Inc. <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 xmpp +import sys +import syslog + +class Agent: + def __init__(self, jidString, jidResource, password, proxySettings=None): + if jidString and jidResource and password: + self.password = password + self.proxySettings = proxySettings + self.jid = xmpp.protocol.JID(jid=jidString) + self.jid.setResource(jidResource) + self.xmppClient = xmpp.Client(self.jid.getDomain(), debug=[]) + self.presenceHandler = None + self.messageHandler = None + return + raise ValueError("jid, resource and password should not be empty") + + def registerPresenceHandler(self, function): + self.presenceHandler = function + + def registerMessageHandler(self, function): + self.messageHandler = function + + def __defaultMessageHandler(self, connection, event): + syslog.syslog(syslog.LOG_DEBUG, + "[Received]: from_jid=%s, type=%s, message=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getBody(), event.getError())) + if self.messageHandler: + self.messageHandler(connection, event) + else: + sys.stderr.write("[Message]: from_jid=%s, type=%s, message=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getBody(), event.getError())) + + def __defaultPresenceHandler(self, connection, event): + syslog.syslog(syslog.LOG_DEBUG, + "[Presence]: from_jid=%s, type=%s, status=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getShow(), event.getError())) + if self.presenceHandler: + self.presenceHandler(connection, event) + else: + sys.stderr.write("[Presence]: from_jid=%s, type=%s, status=%s, error=%s\n" % + (event.getFrom(), event.getType(), event.getShow(), event.getError())) + + def connect(self): + syslog.syslog("Connecting to server %s\n" % self.jid.getDomain()) + connection = self.xmppClient.connect() + if not connection: + syslog.syslog("failed\n") + if not self.proxySettings: + return False + syslog.syslog("Connecting to server %s through proxy server %s, port %s, username %s\n" % + (self.jid.getDomain(), + self.proxySettings["host"], + self.proxySettings["port"], + self.proxySettings["user"])) + connection = self.xmppClient.connect(proxy=self.proxySettings) + if not connection: + syslog.syslog("failed\n") + return False + + syslog.syslog("Authenticating with username %s\n" % self.jid) + auth = self.xmppClient.auth(self.jid.getNode(), + self.password, + self.jid.getResource()) + if not auth: + syslog.syslog("failed\n") + return False + syslog.syslog("done\n") + syslog.syslog("connection type is %s. authentication type is %s\n" % (connection, auth)) + + self.xmppClient.RegisterHandler("presence", self.__defaultPresenceHandler) + self.xmppClient.RegisterHandler("message", self.__defaultMessageHandler) + + self.xmppClient.sendInitPresence() + return True + + def disconnect(self): + self.xmppClient.disconnect() + + def processMessage(self, timeout=1): + return self.xmppClient.Process(timeout) + #if not self.xmppClient.isConnected(): + # self.xmppClient.reconnectAndReauth() + + def sendMessage(self, jidString, message, messageType="chat"): + syslog.syslog(syslog.LOG_DEBUG, + "[send]: from_jid=%s, type=%s, message=%s\n" % + (jidString, messageType, message)) + self.xmppClient.send(xmpp.protocol.Message(to=jidString, + body=message, + typ=messageType)) + + def getNetworkSocket(self): + return self.xmppClient.Connection._sock; + + def getRoster(self): + return self.xmppClient.getRoster() + + def isConnected(self): + return self.xmppClient.isConnected() +##--end of Agent diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py b/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py new file mode 100644 index 00000000..3311eb56 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/GetServerNetworkConfig.py @@ -0,0 +1,96 @@ +# Copyright (C) 2009 Gluster, Inc. <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 syslog +import Globals +import Commands +import re +from ServerUtils import * +from Protocol import * +from NetworkUtils import * + +def getServerNetworkConfig(requestXml): + serverName = requestXml.getTextByTagRoute("command.server-name") + version = requestXml.getVersion() + messageId = requestXml.getAttribute("id") + + if not serverName: + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) + responseDom.appendTagRoute("server.name", serverName) + return responseDom + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "OK", messageId, version) + serverTag = responseDom.createTag("server", None) + serverTag.appendChild(responseDom.createTag("name", serverName)) + nameServerList, domain, searchDomain = readResolvConfFile() + if domain: + domainName = domain[0] + else: + domainName = None + serverTag.appendChild(responseDom.createTag("domainname", domainName)) + i = 1 + for dns in nameServerList: + serverTag.appendChild(responseDom.createTag("dns%s" % i, dns)) + i += 1 + #TODO: probe and retrieve timezone, ntp-server, preferred-network details and update the tags + configDom = XDOM() + if configDom.parseFile("%s/%s/network.xml" % (Globals.SERVER_CONF_DIR, serverName)): + serverTag.appendChild(responseDom.createTag("timezone", configDom.getTextByTagRoute("network.timezone"))) + serverTag.appendChild(responseDom.createTag("ntp-server", configDom.getTextByTagRoute("network.ntp-server"))) + preferredNetwork = configDom.getTextByTagRoute("network.preferred-network") + if not preferredNetwork: + preferredNetwork = "any" + serverTag.appendChild(responseDom.createTag("preferred-network", preferredNetwork)) + + deviceList = {} + for device in getNetDeviceList(): + deviceList[device["device"]] = device + try: + macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() + except IOError: + continue + interfaceTag = responseDom.createTag("interface", None) + interfaceTag.appendChild(responseDom.createTag("device", device["device"])) + interfaceTag.appendChild(responseDom.createTag("description", device["description"])) + interfaceTag.appendChild(responseDom.createTag("hwaddr", macAddress)) + if deviceList[device["device"]]: + if deviceList[device["device"]]["onboot"]: + interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", deviceList[device["device"]]["bootproto"])) + interfaceTag.appendChild(responseDom.createTag("ipaddr", deviceList[device["device"]]["ipaddr"])) + interfaceTag.appendChild(responseDom.createTag("netmask", deviceList[device["device"]]["netmask"])) + interfaceTag.appendChild(responseDom.createTag("gateway", deviceList[device["device"]]["gateway"])) + if deviceList[device["device"]]["mode"]: + interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) + if deviceList[device["device"]]["master"]: + interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) + spliter = re.compile(r'[\D]') + interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", "none")) + serverTag.appendChild(interfaceTag) + responseDom.appendTag(serverTag) + return responseDom + +def test(): + requestString = """<command request="get-server-network-config" id="123" version="3.1.2.2"> +<server-name>s1</server-name></command>""" + requestDom = RequestXml(requestString) + print getServerNetworkConfig(requestDom).toxml() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py new file mode 100755 index 00000000..bcb2bac1 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerAgent.py @@ -0,0 +1,179 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. <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 os +import sys +import signal +import atexit +import socket +import syslog +import pwd +from optparse import OptionParser + +import Globals +import Socket +import Utils +import ServerRequestHandler + + +ME = os.path.basename(sys.argv[0]) +PID_FILE = "/var/run/serveragent.pid" +serverSocket = None +clientSocket = None +clientAddress = None +clientInputStream = None +clientOutputStream = None + + +def sigTermHandler(signal, frame): + sys.exit(0) + + +def cleanup(): + try: + if os.path.exists(PID_FILE): + os.unlink(PID_FILE) + except OSError, e: + Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(e))) + + try: + if clientSocket: + clientSocket.close() + except socket.error, e: + Utils.log("Failed to close client socket: %s" % str(e)) + + try: + if serverSocket: + serverSocket.close() + except socket.error, e: + Utils.log("Failed to close server socket: " % str(e)) + + +def main(): + global PID_FILE + global serverSocket + global clientSocket + global clientAddress + global clientInputStream + global clientOutputStream + + username = Globals.SERVER_AGENT_RUN_USERNAME + + Utils.openLog(Globals.SERVER_AGENT_LOG_FILE) + + parser = OptionParser(version="%s %s" % (ME, Globals.GLUSTER_PLATFORM_VERSION)) + + parser.add_option("-N", "--no-daemon", + action="store_false", dest="daemonMode", default=True, + help="Run in foreground") + parser.add_option("-r", "--run-as", dest="username", + help="Run the daemon as USERNAME (default: %s)" % Globals.SERVER_AGENT_RUN_USERNAME, + metavar="USERNAME") + (options, args) = parser.parse_args() + + if options.username: + username = options.username + try: + userInfo = pwd.getpwnam(username) + except KeyError, e: + sys.stderr.write("%s\n" % str(e)) + serverSocket.close() + sys.exit(-1) + uid = userInfo.pw_uid + gid = userInfo.pw_gid + + try: + Utils.log("__DEBUG__ Opening server socket on port %s" % Globals.SERVER_AGENT_PORT) + serverSocket = Socket.openServerSocket() + except socket.error, e: + sys.stderr.write("Failed to open server socket: %s\n" % str(e)) + sys.exit(-1) + + if options.daemonMode: + if os.path.exists(PID_FILE): + sys.stderr.write("fatal: %s file exists\n" % PID_FILE) + serverSocket.close() + sys.exit(-1) + + if not Utils.daemonize(): + sys.stderr.write("fatal: unable to run as daemon\n") + serverSocket.close() + sys.exit(-1) + try: + fp = open(PID_FILE, "w") + fp.write("%s\n" % os.getpid()) + fp.close() + except IOError, e: + Utils.log("Pid file %s: %s" % (PID_FILE, str(e))) + serverSocket.close() + sys.exit(-1) + try: + os.chown(PID_FILE, uid, gid) + except OSError, e: + Utils.log("Pid file %s: %s" % (PID_FILE, str(e))) + serverSocket.close() + try: + os.unlink(PID_FILE) + except OSError, ex: + Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(ex))) + sys.exit(-1) + else: + Globals.GLUSTER_DEBUG = True + + try: + os.setregid(gid, gid) + except OSError, e: + Utils.log("Failed to set effective and real gid to %s: %s" % (gid, str(e))) + cleanup() + sys.exit(-1) + try: + os.setreuid(uid, uid) + except OSError, e: + Utils.log("Failed to set effective and real uid to %s: %s" % (uid, str(e))) + cleanup() + sys.exit(-1) + + atexit.register(cleanup) + signal.signal(signal.SIGTERM, sigTermHandler) + + while True: + Utils.log("__DEBUG__ Waiting for new connection on port %s" % Globals.SERVER_AGENT_PORT) + try: + clientSocket, clientAddress, clientInputStream, clientOutputStream = Socket.acceptClient(serverSocket) + except socket.error, e: + Utils.log("Failed to accept new connection: %s" % str(e)) + sys.exit(-1) + + Utils.log('__DEBUG__ Connected by %s' % str(clientAddress)) + try: + requestString = Socket.readPacket(clientInputStream) + Utils.log('__DEBUG__ Received %s' % repr(requestString)) + responseString = ServerRequestHandler.handleRequest(requestString) + if responseString: + Socket.writePacket(clientOutputStream, responseString) + clientOutputStream.flush() + else: + Utils.log('__DEBUG__ empty response string') + Utils.log('__DEBUG__ Closing client %s' % str(clientAddress)) + clientSocket.close() + except socket.error, e: + Utils.log("Socket error on client: %s" % str(e)) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py new file mode 100644 index 00000000..31d4eb8c --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerRequestHandler.py @@ -0,0 +1,76 @@ +# Copyright (C) 2010 Gluster, Inc. <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 os + +import Commands +from Protocol import * +from Globals import * +from GetServerNetworkConfig import * + +def handleRequestGetServerNetworkConfig(requestDom): + return getServerNetworkConfig(requestDom) + +def handleRequest(requestString): + log("Received request %s" % repr(requestString)) + + requestDom = XDOM() + requestDom.parseString(requestString) + if not requestDom: + log("Invalid request") + return None + + preRequestMap = {} + + postRequestMap = {} + + cleanupRequestMap = {} + + requestMap = { Commands.COMMAND_GET_SERVER_NETWORK_CONFIG : handleRequestGetServerNetworkConfig } + + messageId = requestDom.getMessageId() + if not messageId: + log("Invalid message Id") + return None + + requestCommand = requestDom.getRequestCommand() + if not requestCommand: + log("invalid request command") + return None + + requestAction = requestDom.getRequestAction() + version = requestDom.getVersion() + #if not isSupportedVersion(version): + # log("Unsupported version request %s" % requestDom.toxml()) + # return ResponseXml(requestCommand, "Unsupported version request", messageId, version).toxml() + + try: + if not requestAction: + responseDom = requestMap[requestCommand](requestDom) + elif requestAction.upper() == "PRE": + responseDom = preRequestMap[requestCommand](requestDom) + elif requestAction.upper() == "POST": + responseDom = postRequestMap[requestCommand](requestDom) + elif requestAction.upper() == "CLEANUP": + responseDom = cleanupRequestMap[requestCommand](requestDom) + else: + log("Unknown request action %s" % requestAction) + return None + return responseDom.toxml() + except KeyError: + log("No handler found for command %s for action %s" % (requestCommand, requestAction)) + return ResponseXml(requestCommand, "Invalid command", messageId, version).toxml() diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py new file mode 100644 index 00000000..1fec994c --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/ServerUtils.py @@ -0,0 +1,308 @@ +# Copyright (c) 2010 Gluster, Inc. <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 os +import re +import subprocess +import glob +import Globals +from Protocol import * +from Utils import * + +def isValidServer(serverName): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + if serverName == profile.DNS.Hostname: + return True + return False + +def getHostname(): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + return profile.DNS.Hostname + return None + +def getDomainName(): + try: + domainName = open(Globals.DOMAINNAME_FILE).read() + except IOError: + return None + return domainName.split()[0] + +def replaceServerIp(fileName, findWhat, replaceWith): + try: + data = open(fileName).read() + fp = open(fileName, "w") + fp.write(re.sub(findWhat, replaceWith, data)) + fp.close() + return True + except IOError: + return False + except ValueError: + return False + except OSError: + return False + +def serverName2IpAddress(serverName): + command = "dig %s | grep '^%s'" % (serverName, serverName) + ps = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True) + ipAddress = serverName + if ps.wait() == 0: + output = ps.communicate() + ipAddress = output[0].split()[-1] + return ipAddress + +def getInstallerIp(): + if not os.path.exists(Globals.INSTALLER_INFO_FILE): + return None + try: + for line in open(Globals.INSTALLER_INFO_FILE): + tokens = line.split("=") + if tokens[0] == "IP-ADDRESS": + return tokens[1].split(",")[0].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def setInstallerIp(installerIp): + try: + open(Globals.INSTALLER_INFO_FILE, "w").write("IP-ADDRESS=%s\n" % installerIp) + return True + except IOError: + log(syslog.LOG_ERR, "unable to create %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def getCurrentServerName(): + try: + for line in open(Globals.SYSCONFIG_NETWORK_FILE): + tokens = line.split("=") + if tokens[0] == "HOSTNAME": + return tokens[1].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.SYSCONFIG_NETWORK_FILE) + return False + +def getLastAccessedNetwork(serverName): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + return open(lastAccessedNetworkFile).read().strip() + except IOError: + log(syslog.LOG_ERR, "failed to read last accessed network file %s" % lastAccessedNetworkFile) + pass + return False + +def setLastAccessedNetwork(serverName, ipAddress): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + open(lastAccessedNetworkFile, "w").write(ipAddress.strip() + "\n") + except IOError: + log(syslog.LOG_ERR, "failed to write last accessed network file %s" % lastAccessedNetworkFile) + return False + return True + +def getServerIpList(serverName, preferredNetworkOnly=False): + networkXmlFile = ("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + configDom = XDOM() + if not configDom.parseFile(networkXmlFile): + log(syslog.LOG_ERR, "failed to read %s file" % networkXmlFile) + return None + preferredNetwork = configDom.getTextByTagRoute("preferred-network") + ipList = [] + interfaceDom = XDOM() + for tagE in configDom.getElementsByTagName("interface"): + interfaceDom.setDomObj(tagE) + deviceName = interfaceDom.getTextByTagRoute("device") + hostIp = interfaceDom.getTextByTagRoute("ipaddr") + if not hostIp: + continue + if preferredNetworkOnly: + if preferredNetwork.upper() == "ANY" or preferredNetwork.upper() == deviceName.upper(): + ipList.append(hostIp) + else: + ipList.append(hostIp) + if preferredNetworkOnly: + lastAccessedNetworkIp = getLastAccessedNetwork(serverName) + if lastAccessedNetworkIp in ipList: + ipList.remove(lastAccessedNetworkIp) + ipList = [lastAccessedNetworkIp] + ipList + return ipList + +def getServerPreferredIpList(serverName): + return getServerIpList(serverName, True) + +def getExecuteServerList(serverList): + executeServerList = {} + for serverName in serverList: + if serverName == Globals.INSTALLER_SERVER_NAME: + installerIp = getInstallerIp() + if installerIp: + executeServerList[serverName] = [installerIp] + continue + executeServerList[serverName] = getServerPreferredIpList(serverName) + return executeServerList + +def getAllServerList(): + serverList = [] + for filePath in glob.glob("%s/servers/*" % Globals.GLUSTER_CONF_DIR): + if os.path.isdir(filePath): + serverList.append(os.path.basename(filePath)) + try: + serverList.remove(Globals.INSTALLER_SERVER_NAME) + except ValueError: + pass + return serverList + +def getServerNetworkConfigFromLocalFile(serverName): + configDom = XDOM() + configDom.parseFile("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + return configDom + +def updateServerNetworkConfigXmlFile(serverName, serverNetworkDom): + configDom = XDOM() + serverTag = serverNetworkDom.getElementsByTagRoute("server")[0] + configDom.setDomObj(serverTag) + if not configDom.writexml("%s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): + log("Faild to write xml file %s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + +def compareServerNetworkDom(serverNetworkDomA, serverNetworkDomB, requestFlag=True): + command = "command.server." + if not requestFlag: + command = "" + sourceServer = {} + tagText = serverNetworkDomA.getTextByTagRoute("name") + if not tagText: + taxText = None + sourceServer["name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("domain-name") + if not tagText: + tagText = None + sourceServer["domain-name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("search-domain") + if not tagText: + tagText = None + sourceServer["search-domain"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns1") + if not tagText: + tagText = None + sourceServer["dns1"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns2") + if not tagText: + tagText = None + sourceServer["dns2"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns3") + if not tagText: + tagText = None + sourceServer["dns3"] = tagText + for tagE in serverNetworkDomA.getElementsByTagRoute("interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + sourceServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + sourceServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + sourceServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + sourceServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + sourceServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + sourceServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + sourceServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + sourceServerList["gateway"] = tagText + sourceServer[interfaceDom.getTextByTagRoute("device")] = sourceServerList + objServer = {} + tagText = serverNetworkDomB.getTextByTagRoute(command + "name") + if not tagText: + taxText = None + objServer["name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "domain-name") + if not tagText: + tagText = None + objServer["domain-name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "search-domain") + if not tagText: + tagText = None + objServer["search-domain"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns1") + if not tagText: + tagText = None + objServer["dns1"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns2") + if not tagText: + tagText = None + objServer["dns2"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns3") + if not tagText: + tagText = None + objServer["dns3"] = tagText + for tagE in serverNetworkDomB.getElementsByTagRoute(command + "interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + objServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + objServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + objServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + objServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + objServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + objServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + objServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + objServerList["gateway"] = tagText + objServer[interfaceDom.getTextByTagRoute("device")] = objServerList + return sourceServer == objServer diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py b/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py new file mode 100644 index 00000000..ba6b6ad0 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/Socket.py @@ -0,0 +1,47 @@ +import socket +import sys +import Globals + +def openServerSocket(bindAddress="", port=Globals.SERVER_AGENT_PORT): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((bindAddress, port)) + sock.listen(1) + return sock + + +def connectToServer(serverName, port=Globals.SERVER_AGENT_PORT): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((serverName, port)) + print "__DEBUG__ connected to ", serverName, " on port ", port + inputStream = sock.makefile("r") + outputStream = sock.makefile("w") + return sock, inputStream, outputStream + + +def acceptClient(serverSocket): + clientSocket, clientAddress = serverSocket.accept() + clientInputStream = clientSocket.makefile("r") + clientOutputStream = clientSocket.makefile("w") + return clientSocket, clientAddress, clientInputStream, clientOutputStream + + +def readPacket(inputStream): + packetString = "" + while True: + line = inputStream.readline() + print "__DEBUG__", line + if not line: + break + if line.strip() == "": + # end of input received + return packetString + packetString += line + return packetString + + +def writePacket(outputStream, packetString): + rv = outputStream.write(packetString.strip() + "\n\n") + outputStream.flush() + + diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py b/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py new file mode 100644 index 00000000..d5a1fe19 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/XmlHandler.py @@ -0,0 +1,346 @@ +# Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3 of
+# the License, or (at your option) any later version.
+#
+# Gluster Storage Platform is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import xml
+import xml.parsers.expat
+import xml.dom.minidom as MDOM
+import os
+import Globals
+import copy
+import Utils
+
+XML_STRING = 0
+XML_FILE = 1
+
+class XDOM:
+ _domObj = None
+
+ def __init__(self):
+ self._domObj = MDOM.Document()
+ return
+
+ @classmethod
+ def getText(self, nodeList):
+ rc = ""
+ for node in nodeList:
+ if node.nodeType == node.TEXT_NODE:
+ rc = rc + node.data
+ return rc
+
+ def parseString(self, requestString):
+ try:
+ self._domObj = MDOM.parseString(requestString)
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML string parse error: %s" % str(e))
+ return False
+ return True
+
+ def parseFile(self, fileName):
+ try:
+ self._domObj = MDOM.parse(fileName)
+ except IOError, e:
+ Utils.log("error reading file: %s" % str(e))
+ return False
+ except xml.parsers.expat.ExpatError, e:
+ Utils.log("XML file %s parse error: %s" % (fileName, str(e)))
+ return False
+ return True
+
+ def setDomObj(self, dom):
+ if dom and type(dom) != type([]):
+ self._domObj = dom
+ return True
+ return False
+
+ def createTag(self, tag, text=None):
+ if not self._domObj:
+ return None
+ if tag == None:
+ return None
+
+ tagE = self._domObj.createElement(str(tag))
+ if text:
+ tagEText = self._domObj.createTextNode(str(text))
+ tagE.appendChild(tagEText)
+ return tagE
+
+ def addTag(self, tag):
+ if not self._domObj:
+ return False
+ if not tag:
+ return False
+
+ self._domObj.appendChild(tag)
+ return True
+
+ def createTagRoute(self, tagRoute, text=None):
+ if not tagRoute:
+ return False
+
+ tagList = tagRoute.split(".")
+ tag = None
+ previousTag = None
+ for tagName in tagList[:-1]:
+ newTag = self.createTag(tagName, None)
+ if not tag:
+ tag = newTag
+ previousTag = newTag
+ continue
+ previousTag.appendChild(newTag)
+ previousTag = newTag
+
+ if previousTag:
+ previousTag.appendChild(self.createTag(tagList[-1], text))
+ else:
+ tag = self.createTag(tagList[-1], text)
+ return tag
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._domObj:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._domObj
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+
+ def setTextByTagRoute(self, tagRoute, tagValue):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ tagE = self.getElementsByTagRoute(tagRoute)
+ if not tagE:
+ return False
+
+ parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1]))
+ if not parentTagE:
+ return False
+
+ parentTagE[0].childNodes.remove(tagE[0])
+ parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue))
+ return True
+
+ def getElementsByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ if not tagRoute:
+ return None
+
+ x = None
+ for tag in tagRoute.split("."):
+ if x is None:
+ x = self._domObj.getElementsByTagName(tag)
+ continue
+ if x == []:
+ break
+ x = x[0].getElementsByTagName(tag)
+ return x
+
+ def getTextByTagRoute(self, tagRoute):
+ if not self._domObj:
+ return None
+
+ x = self.getElementsByTagRoute(tagRoute)
+ if x:
+ return self.getText(x[0].childNodes)
+ return None
+
+ def getElementsByTagName(self, name):
+ if not self._domObj:
+ return None
+ return self._domObj.getElementsByTagName(name)
+
+ def writexml(self, fileName, indent="", addindent="", newl=""):
+ if not self._domObj:
+ return None
+ try:
+ fp = open(fileName, "w")
+ self._domObj.writexml(fp, indent, addindent, newl)
+ fp.close()
+ return True
+ except IOError:
+ return False
+
+ def toString(self, indent=" ", newl="\n", encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toprettyxml(indent, newl, encoding)
+
+ def toxml(self, encoding = None):
+ if not self._domObj:
+ return None
+ return self._domObj.toxml(encoding)
+
+ def toprettyxml(self, indent=" ", newl="\n", encoding = None):
+ return self.toString(indent, newl, encoding)
+
+ def createResponseTag(self):
+ responseTag = self._domObj.createElement("response")
+ return responseTag
+##--end of XDOM
+
+class RequestXml(XDOM):
+ def __init__(self, requestString, type=None):
+ if None == requestString:
+ XDOM.__init__(self)
+ return
+ try:
+ if None == type:
+ if os.path.isfile(requestString):
+ self._domObj = MDOM.parse(requestString)
+ else:
+ self._domObj = MDOM.parseString(requestString)
+ elif XML_FILE == type:
+ self._domObj = MDOM.parse(requestString)
+ elif XML_STRING == type:
+ self._domObj = MDOM.parseString(requestString)
+ except IOError:
+ XDOM.__init__(self)
+ except xml.parsers.expat.ExpatError:
+ XDOM.__init__(self)
+
+##--end of RequestXML
+
+
+class ResponseXml(XDOM):
+ _responseTag = None
+ def __init__(self):
+ XDOM.__init__(self)
+ self._responseTag = self.createResponseTag()
+ self._domObj.appendChild(self._responseTag)
+
+ @classmethod
+ def errorResponse(self, message):
+ if not self.responseTag:
+ return False
+ self.appendTagRoute("status.code", "-1");
+ self.appendTagRoute("status.message", message)
+
+ def append(self, tagName, tagValue=None):
+ if not self._responseTag:
+ return False
+ tag = self.createTag(tagName, tagValue)
+ if tag:
+ self._responseTag.appendChild(tag)
+ return True
+ return False
+
+ def appendTag(self, tag):
+ if not tag:
+ return False
+ if not self._responseTag:
+ return False
+ self._responseTag.appendChild(tag)
+ return True
+
+ def appendTagRoute(self, tagRoute, value=None):
+ if not self._responseTag:
+ return None
+ if not tagRoute:
+ return None
+
+ parentTagE = self._responseTag
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return None
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return None
+ return newTagE
+
+ def appendTagRouteOld(self, tagRoute, value=None):
+ if not self._responseTag:
+ return False
+ if not tagRoute:
+ return False
+
+ parentTagE = self._responseTag
+
+ tagNameList = tagRoute.split(".")
+ newTagRoute = tagNameList.pop(-1)
+
+ for i in range(len(tagNameList), 0, -1):
+ tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i]))
+ if tagE:
+ parentTagE = tagE[0]
+ break
+ newTagRoute = tagNameList[i-1] + "." + newTagRoute
+
+ newTagE = self.createTagRoute(newTagRoute, value)
+ if not newTagE:
+ return False
+ try:
+ parentTagE.appendChild(newTagE)
+ except xml.dom.HierarchyRequestErr, e:
+ Utils.log("error occured. %s" + str(e))
+ return False
+ return True
+##--end of ResponseXml
+
+def test():
+ rs = ResponseXml()
+ rs.appendTagRoute("status.code", "0");
+ rs.appendTagRoute("status.message", "SUCCESS")
+ serverTag = rs.appendTagRoute("server.name", "Server1")
+ networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None)
+ networkTag = rs.createTag("networkInterface", None)
+ networkTag.appendChild(rs.createTag("name", "interface1"))
+ networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40"))
+ networkInterfaces.appendChild(networkTag)
+ networkTag = rs.createTag("networkInterface", None)
+ networkTag.appendChild(rs.createTag("name", "interface2"))
+ networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41"))
+ networkInterfaces.appendChild(networkTag)
+ print rs.toprettyxml()
+
+test()
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py b/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py new file mode 100644 index 00000000..64bc0899 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/nodes/multicast_response.py @@ -0,0 +1,45 @@ +#!/usr/bin/python
+# Copyright (C) 2009 Gluster, Inc. <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 socket
+import struct
+import Globals
+
+def response(multiCastGroup, port):
+ # waiting for the request!
+ socketRequest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ socketRequest.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ socketRequest.bind(('', port))
+ mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY)
+ socketRequest.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+
+ socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
+
+ #TODO: Remove infinite loop and make this as a deamon (service)
+ while True:
+ request = socketRequest.recvfrom(1024)
+ if request and request[0].upper() == "SERVERDISCOVERY":
+ socketSend.sendto(socket.gethostname(), (multiCastGroup, port))
+ request = None
+
+def main():
+ response(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py b/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py new file mode 100644 index 00000000..1800234f --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/RemoteExecute.py @@ -0,0 +1,287 @@ +# Copyright (C) 2010 Gluster, Inc. <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 os +import socket +#import paramiko +import syslog +import sys +import Socket +import Globals +from copy import deepcopy +from ServerUtils import * + +SERVER_AGENT_COMMAND = "/usr/sbin/server-agent" +SERVER_AGENT_CLEANUP_COMMAND = SERVER_AGENT_COMMAND + " --cleanup" +SERVER_AGENT_PRE_COMMAND = SERVER_AGENT_COMMAND + " --pre" +SERVER_AGENT_POST_COMMAND = SERVER_AGENT_COMMAND + " --post" +TRANSPORT_USER_NAME = "transport" +TRANSPORT_PRIVATE_KEY_FILE = Globals.TRANSPORT_HOME_DIR + "/.ssh/id_rsa" + +def remoteExecute(serverList, command, commandInput=None): + print "REMOTE:", serverList + statusDict = {} + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + privateKey = paramiko.RSAKey.from_private_key_file(TRANSPORT_PRIVATE_KEY_FILE) + except IOError: + log(syslog.LOG_ERR, "Private key file %s not found" % TRANSPORT_PRIVATE_KEY_FILE) + return None + print "STAGE1" + for serverName in serverList.keys(): + serverStatus = {} + serverStatus["ConnectionStatus"] = None + serverStatus["ExecutionStatus"] = None + serverStatus["StdOutString"] = None + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = None + serverStatus["Error"] = None + + isConnected = False + for serverIp in serverList[serverName]: + try: + ssh.connect(serverIp, username=TRANSPORT_USER_NAME, pkey=privateKey) + isConnected = True + break + except socket.error: + log(syslog.LOG_ERR, "Server %s:%s is inaccessible" % (serverName, serverIp)) + continue + if not isConnected: + serverStatus["ConnectionStatus"] = "inaccessible" + statusDict[serverName] = serverStatus + continue + + try: + transport = ssh.get_transport() + channel = transport.open_session() + serverStatus["ConnectionStatus"] = True + channel.exec_command(command) + stdin = channel.makefile('wb') + stdout = channel.makefile('rb') + stderr = channel.makefile_stderr('rb') + if commandInput: + stdin.write(commandInput) + channel.shutdown_write() + + returnValue = channel.recv_exit_status() ## this is blocking call + serverStatus["ExecutionStatus"] = returnValue + print "RRRRRRRRRRRRRRRR:", returnValue + errorString = "" + if -1 == returnValue: + errorString = stderr.read() + serverStatus["StdErrString"] = errorString + if "bash: " + command.split()[0] + ": command not found\n" == errorString: + log(syslog.LOG_ERR, "command %s not found in server %s" % (command, serverName)) + serverStatus["Error"] = "Command not found" + else: + serverStatus["StdErrString"] = stderr.read() + serverStatus["StdOutString"] = stdout.read() + ssh.close() + except paramiko.SSHException: + # Channel error (channel not open) + log(syslog.LOG_ERR, "Server %s:%s connection aborted" % (serverName, serverIp)) + serverStatus["ConnectionStatus"] = "aborted" + except socket.error: + log(syslog.LOG_ERR, "Server %s:%s is inaccessible" % (serverName, serverIp)) + serverStatus["ConnectionStatus"] = "inaccessible" + except paramiko.AuthenticationException: + log(syslog.LOG_ERR, "Authentication error on server %s:%s of user %s" % + (serverName, serverIp, TRANSPORT_USER_NAME)) + serverStatus["ConnectionStatus"] = "authentication error" + serverStatus["ConnectedIp"] = serverIp + statusDict[serverName] = serverStatus + return statusDict + +def cleanupExecuteSsh(serverList, requestDom): + return remoteExecute(serverList, SERVER_AGENT_CLEANUP_COMMAND, requestDom.toxml()) + +def executeRequestCommandSsh(serverList, command, requestDom, cleanupFlag): + cleanupStatusDict = {} + successStatusDict = {} + failureServerList = {} + cleanupServerList = {} + serverList = deepcopy(serverList) + statusDict = remoteExecute(serverList, command, requestDom.toxml()) + for serverName in statusDict.keys(): + statusDict["Response"] = None + if statusDict[serverName]["ConnectionStatus"] == True: + setLastAccessedNetwork(serverName, statusDict[serverName]["ConnectedIp"]) + if statusDict[serverName]["ConnectedIp"]: + ipList = serverList[serverName] + ipList.remove(statusDict[serverName]["ConnectedIp"]) + cleanupServerList[serverName] = [statusDict[serverName]["ConnectedIp"]] + ipList + if statusDict[serverName]["ExecutionStatus"] != 0: + failureServerList[serverName] = statusDict[serverName] + continue + responseDom = XDOM() + if not responseDom.parseString(statusDict[serverName]["StdOutString"]): + failureServerList[serverName] = statusDict[serverName] + continue + statusDict["Response"] = responseDom + if "OK" != responseDom.getAttribute("response-code"): + failureServerList[serverName] = statusDict[serverName] + continue + successStatusDict[serverName] = statusDict[serverName] + if cleanupFlag and failureServerList: + cleanupStatusDict = remoteExecute(cleanupServerList, SERVER_AGENT_CLEANUP_COMMAND, requestDom.toxml()) + return successStatusDict, failureServerList, cleanupStatusDict + +def preExecuteSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_PRE_COMMAND, requestDom, cleanupFlag) + +def executeSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_COMMAND, requestDom, cleanupFlag) + +def postExecuteSsh(serverList, requestDom, cleanupFlag=True): + return executeRequestCommandSsh(serverList, SERVER_AGENT_POST_COMMAND, requestDom, cleanupFlag) + +def runPullUpdatesDir(sourceServerIp, destServerIpList): + command = "/usr/sbin/pull-dir.sh %s %s %s" % (sourceServerIp, + Globals.UPDATES_DIR[1:], + Globals.UPDATES_DIR) + statusDict = remoteExecute(destServerIpList, command) + status = True + for serverName in statusDict.keys(): + if statusDict[serverName]["ExecutionStatus"] != 0: + log(syslog.LOG_ERR, "Failed to execute [%s] in server %s" % (command, serverName)) + status = False + return status + +def runPullGlusterDir(sourceServerIp, destServerIpList): + command = "/usr/sbin/pull-dir.sh %s %s %s" % (sourceServerIp, + Globals.GLUSTER_BASE_DIR[1:], + Globals.GLUSTER_BASE_DIR) + statusDict = remoteExecute(destServerIpList, command) + status = True + for serverName in statusDict.keys(): + if statusDict[serverName]["ExecutionStatus"] != 0: + log(syslog.LOG_ERR, "Failed to execute [%s] in server %s" % (command, serverName)) + status = False + return status + +def syncConfiguration(syncToInstaller=False, sourceServerIpList=None): + thisServerName = getCurrentServerName() + serverList = getAllServerList() + serverList.remove(thisServerName) + serverIpList = getExecuteServerList(serverList) + if syncToInstaller: + installerIp = getInstallerIp() + if not installerIp: + log(syslog.LOG_ERR, "Installer IP address is not found") + return False + serverIpList[Globals.INSTALLER_SERVER_NAME] = [installerIp] + + if not serverIpList: + log(syslog.LOG_ERR, "No servers found for sync configuration") + return False + + signature = generateSignature() + if not storeSignature(signature, Globals.SIGNATURE_FILE): + log(syslog.LOG_ERR, "failed to store signature %s to %s file" % + (signature, Globals.SIGNATURE_FILE)) + return False + + thisServerIpList = getExecuteServerList([thisServerName]) + if sourceServerIpList: + thisServerIpList = sourceServerIpList + return runPullGlusterDir(thisServerIpList[thisServerName][0], serverIpList) + +def remoteExecuteTcp(serverIpList, requestString): + serverStatus = {} + serverStatus["ConnectionStatus"] = False + serverStatus["ExecutionStatus"] = -1 + serverStatus["StdOutString"] = None + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = None + serverStatus["Error"] = None + + for ipAddress in serverIpList.values()[0]: + try: + sock, inputStream, outputStream = Socket.connectToServer(ipAddress) + Socket.writePacket(outputStream, requestString) + packetString = Socket.readPacket(inputStream) + log('__DEBUG__ Received: %s' % repr(packetString)) + sock.close() + serverStatus["ConnectionStatus"] = True + serverStatus["ExecutionStatus"] = 0 + serverStatus["StdOutString"] = packetString + serverStatus["StdErrString"] = None + serverStatus["ConnectedIp"] = ipAddress + serverStatus["Error"] = None + return serverStatus + except socket.error, e: + log("socket error on [%s:%s]: %s" % (serverIpList.keys()[0], ipAddress, str(e))) + return serverStatus + +def executeRequestCommand(serverList, command, requestDom, cleanupFlag): + cleanupStatusDict = {} + successStatusDict = {} + failureServerList = {} + cleanupServerList = {} + serverList = deepcopy(serverList) + + statusDict = {} + for serverName in serverList.keys(): + serverStatus = remoteExecuteTcp({serverName : serverList[serverName]}, requestDom.toxml()) + statusDict[serverName] = serverStatus + for serverName in statusDict.keys(): + statusDict["Response"] = None + if statusDict[serverName]["ConnectionStatus"] == True: + setLastAccessedNetwork(serverName, statusDict[serverName]["ConnectedIp"]) + if statusDict[serverName]["ConnectedIp"]: + ipList = serverList[serverName] + ipList.remove(statusDict[serverName]["ConnectedIp"]) + cleanupServerList[serverName] = [statusDict[serverName]["ConnectedIp"]] + ipList + if statusDict[serverName]["ExecutionStatus"] != 0: + failureServerList[serverName] = statusDict[serverName] + continue + responseDom = XDOM() + if not responseDom.parseString(statusDict[serverName]["StdOutString"]): + failureServerList[serverName] = statusDict[serverName] + continue + statusDict["Response"] = responseDom + if "OK" != responseDom.getResponseCode(): + failureServerList[serverName] = statusDict[serverName] + continue + successStatusDict[serverName] = statusDict[serverName] + if cleanupFlag and failureServerList: + rq = deepcopy(requestDom) + rq.setRequestAction("cleanup") + cleanupStatusDict = {} + for serverName in cleanupServerList.keys(): + serverStatus = remoteExecuteTcp({serverName : cleanupServerList[serverName]}, rq.toxml()) + cleanupStatusDict[serverName] = serverStatus + return successStatusDict, failureServerList, cleanupStatusDict + +def preExecute(serverList, requestDom, cleanupFlag=True): + rq = deepcopy(requestDom) + rq.setRequestAction("pre") + return executeRequestCommand(serverList, SERVER_AGENT_PRE_COMMAND, rq, cleanupFlag) + +def execute(serverList, requestDom, cleanupFlag=True): + return executeRequestCommand(serverList, SERVER_AGENT_COMMAND, requestDom, cleanupFlag) + +def postExecute(serverList, requestDom, cleanupFlag=True): + rq = deepcopy(requestDom) + rq.setRequestAction("post") + return executeRequestCommand(serverList, SERVER_AGENT_POST_COMMAND, rq, cleanupFlag) + +def cleanupExecute(serverList, requestDom): + rq = deepcopy(requestDom) + rq.setRequestAction("cleanup") + return executeRequestCommand(serverList, SERVER_AGENT_CLEANUP_COMMAND, rq, False) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py b/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py new file mode 100644 index 00000000..e6fe88ff --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/RequestHandler.py @@ -0,0 +1,58 @@ +import os +import glob +#import paramiko +import tempfile +#import uuid +import socket +import tarfile +import time +import Globals +import Commands +from Protocol import * +from RemoteExecute import * +from NetworkUtils import * + +def handleRequestGetServerNetworkConfig(requestDom): + messageId = requestDom.getAttribute("id") + serverName = requestDom.getTextByTagRoute("command.server-name") + version = requestDom.getVersion() + request = requestDom.getAttribute("request") + + if not serverName: + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) + responseDom.appendTagRoute("server.name", serverName) + return responseDom + + #serverIpList = getExecuteServerList([serverName]) + #if not serverIpList: + # responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "Unable to get server ip", messageId, version) + # responseDom.appendTagRoute("server.name", serverName) + # return responseDom + + successStatusDict, failureServerList, cleanupStatusDict = \ + execute({serverName:[serverName]}, requestDom, Globals.REQUEST_MAP[request]["cleanup"]) + if failureServerList: + response = failureServerList[serverName]["StdOutString"] + if not response: + return ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Failed to execute get server network config", messageId, version) + responseDom = XDOM() + if responseDom.parseString(response): + return responseDom + errorResponseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Invalid response of get server network config", messageId, version) + errorResponseDom.appendTagRoute("server.name", serverName) + return errorResponseDom + + responseDom = XDOM() + if not responseDom.parseString(successStatusDict[serverName]["StdOutString"]): + errorResponseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, + "Invalid response of get server network config", messageId, version) + errorResponseDom.appendTagRoute("server.name", serverName) + return errorResponseDom + + #configDom = getServerNetworkConfigFromLocalFile(serverName) + #if not (configDom and compareServerNetworkDom(configDom, responseDom)): + # updateServerNetworkConfigXmlFile(serverName, responseDom) + # syncConfiguration() + return responseDom diff --git a/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py b/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py new file mode 100644 index 00000000..5f39b585 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/TransportAgent.py @@ -0,0 +1,26 @@ +import Commands +#from Common import log +from Protocol import * +from RequestHandler import * + +def processRequest(requestDom): + Globals.REQUEST_MAP = { + Commands.COMMAND_GET_SERVER_NETWORK_CONFIG : {"handle":handleRequestGetServerNetworkConfig, + "pre-run":False, "run":True, "post-run":False, \ + "cleanup":False, "sync-config":False, "safemode":False}} + + messageId = requestDom.getMessageId() + if not messageId: + log("invalid message from web agent") + return None + + requestCommand = requestDom.getRequestCommand() + if not requestCommand: + log("invalid request from web agent") + return None + + try: + requestCommand = Globals.REQUEST_MAP[requestCommand]['handle'] + except KeyError: # Handler not found! + return ResponseXml(requestCommand, "Invalid command", messageId, version) + return requestCommand(requestDom) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/transport.py b/src/com.gluster.storage.management.server.scripts/src/server/transport.py new file mode 100755 index 00000000..9255ff40 --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/transport.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. <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 syslog +import signal +import datetime +from Globals import * +from Protocol import * +from TransportAgent import * +from optparse import OptionParser + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def main(): + openLog(Globals.TRANSPORT_AGENT_LOG_FILE) + parser = OptionParser(version="%transport " + Globals.GLUSTER_PLATFORM_VERSION) + parser.add_option("-f", "--force", + action="store_true", dest="force", default=False, + help="Execute command forcefully") + + parser.add_option("-t", "--timeout", + type="int", nargs=1, dest="timeout", + help="Session time-out") + + parser.add_option("--debug", + action="store_true", dest="debug", default=False, + help="Enable debug mode") + (options, args) = parser.parse_args() + Globals.GLUSTER_DEBUG = options.debug + + if len(args) != 1: + #print "usage: Transport.py [-f | --force] [-t N | --timeout=N] [--debug] <input-file>" + log(syslog.LOG_ERR, "invalid arguments") + sys.exit(-1) + + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(options.timeout) + inputFile = args[0] + #outputFile = args[1] + try: + requestString = open(inputFile).read() + if not requestString: + sys.exit(-1) + fp = open("/tmp/transport.log", "a") + fp.write("\n%s: Send: %s\n" % (str(datetime.now()), requestString)) + fp.close() + except IOError: + log(syslog.LOG_ERR, "Unable to read input xml file %s" % inputFile) + sys.exit(-1) + + requestDom = RequestXml(requestString) + if not requestDom: + log(syslog.LOG_ERR, "error: invalid request: %s" % requestString) + sys.exit(-1) + + responseDom = processRequest(requestDom) + if not responseDom: + log(syslog.LOG_ERR, "command execution failed") + sys.exit(-1) + + #fp = open("/tmp/transport.log", "a") + #fp.write("%s: Receive: %s\n" % (str(datetime.now()), responseDom.toxml())) + #fp.close() + + #responseDom.writexml(outputFile) + print responseDom.toxml() + sys.exit(0) + +if __name__ == "__main__": + try: + main() + except TimeoutException: + log(syslog.LOG_ERR, "session timed out") + sys.exit(-1) diff --git a/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py b/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py new file mode 100755 index 00000000..6ac15fed --- /dev/null +++ b/src/com.gluster.storage.management.server.scripts/src/server/vmware-discover-servers.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. <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 socket +import signal +import struct +import syslog +import Globals +import Common + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if response and response[0].upper() != "SERVERDISCOVERY": + servers.append(response[0]) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Common.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + #fp = open(Globals.DISCOVERED_SERVER_LIST_FILENAME, "w") + #fp.writelines(list(servers)) + #fp.close() + for server in servers: + print server + except IOError: + Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + + #for serverName in servers: + # print serverName + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/.classpath b/src/com.gluster.storage.management.server/.classpath new file mode 100644 index 00000000..59631d14 --- /dev/null +++ b/src/com.gluster.storage.management.server/.classpath @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v7.0"> + <attributes> + <attribute name="owner.project.facets" value="jst.web"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/> + <classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/> + <classpathentry combineaccessrules="false" kind="src" path="/com.gluster.storage.management.core"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="output" path="WebContent/WEB-INF/classes"/> +</classpath> diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project new file mode 100644 index 00000000..86d34a3b --- /dev/null +++ b/src/com.gluster.storage.management.server/.project @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.gluster.storage.management.server</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.python.pydev.PyDevBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.jsdt.core.javascriptValidator</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.common.project.facet.core.builder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.validation.validationbuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jem.workbench.JavaEMFNature</nature> + <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature> + <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 new file mode 100644 index 00000000..a9cca037 --- /dev/null +++ b/src/com.gluster.storage.management.server/.pydevproject @@ -0,0 +1,7 @@ +<?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/.settings/.jsdtscope b/src/com.gluster.storage.management.server/.settings/.jsdtscope new file mode 100644 index 00000000..3a28de0c --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/.jsdtscope @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="WebContent"/> + <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject"> + <attributes> + <attribute name="hide" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/> + <classpathentry kind="output" path=""/> +</classpath> diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..476db350 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 29 14:57:23 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 00000000..5d9c71b6 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..bb2eaf45 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project-modules id="moduleCoreId" project-version="1.5.0"> + <wb-module deploy-name="com.gluster.storage.management.server"> + <wb-resource deploy-path="/" source-path="/WebContent"/> + <wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/> + <property name="java-output-path" value="/com.gluster.storage.management.server/build/classes"/> + <property name="context-root" value="glustermc"/> + </wb-module> +</project-modules> diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..8f960f27 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?><!-- + Copyright (c) 2011 IBM Corporation and others. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html + + Contributors: + IBM Corporation - initial API and implementation + --> + +<faceted-project> + <runtime name="Apache Tomcat v7.0"/> + <fixed facet="wst.jsdt.web"/> + <fixed facet="jst.web"/> + <fixed facet="java"/> + <installed facet="java" version="1.6"/> + <installed facet="jst.web" version="3.0"/> + <installed facet="wst.jsdt.web" version="1.0"/> +</faceted-project> diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..3bd5d0a4 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..05bd71b6 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs new file mode 100644 index 00000000..e5ca6272 --- /dev/null +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0
+Class-Path:
+
diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar Binary files differnew file mode 100644 index 00000000..578b1a0c --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar Binary files differnew file mode 100644 index 00000000..8217cae0 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar Binary files differnew file mode 100644 index 00000000..8758a96b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar Binary files differnew file mode 100644 index 00000000..dc8ae8df --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar Binary files differnew file mode 100644 index 00000000..ca367aae --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar Binary files differnew file mode 100644 index 00000000..a3248188 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar Binary files differnew file mode 100644 index 00000000..faf12cf6 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar Binary files differnew file mode 100644 index 00000000..ca612580 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar Binary files differnew file mode 100644 index 00000000..57c2c670 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar Binary files differnew file mode 100644 index 00000000..62f790fa --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar Binary files differnew file mode 100644 index 00000000..92b38466 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar Binary files differnew file mode 100644 index 00000000..01d8c83b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar Binary files differnew file mode 100644 index 00000000..a29d7409 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar Binary files differnew file mode 100644 index 00000000..c79b4490 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar Binary files differnew file mode 100644 index 00000000..e4e9c8c3 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar Binary files differnew file mode 100644 index 00000000..23782c02 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar Binary files differnew file mode 100644 index 00000000..ec8bc818 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar Binary files differnew file mode 100644 index 00000000..a5d37aa1 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..db6f529f --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..7cd3a626 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..11fc11b9 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..f2e2e927 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..bd1367d8 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..e46f9eb8 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..ea9500d6 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..6ef99d8d --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..e149290e --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..dcd1e4d9 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..f7a3b837 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..9cea2aef --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..d0550ccd --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..1688cf74 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd new file mode 100644 index 00000000..b3aa6af8 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd @@ -0,0 +1,21 @@ +Library-SymbolicName: org.springframework.spring +Library-Version: 3.0.5.RELEASE +Library-Name: Spring Framework +Import-Bundle: + org.springframework.aop;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.asm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.aspects;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.beans;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context.support;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.core;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.expression;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jdbc;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jms;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.orm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.oxm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.transaction;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.servlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.portlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + com.springsource.org.aopalliance;version="[1.0.0, 1.0.0]" diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..237995c5 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..2f52122b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..5a2381a0 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..6ec9d681 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..6d13bd40 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..e351ae7b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar Binary files differnew file mode 100644 index 00000000..56222cbf --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar Binary files differnew file mode 100644 index 00000000..d321e76c --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar Binary files differnew file mode 100644 index 00000000..e5bc672b --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..78818fc5 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..a8077d5d --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar Binary files differnew file mode 100644 index 00000000..26611b55 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.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 new file mode 100644 index 00000000..34337a5d --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + id="WebApp_ID" version="3.0"> + <display-name>com.gluster.storage.management.server</display-name> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + <welcome-file>index.htm</welcome-file> + <welcome-file>index.jsp</welcome-file> + <welcome-file>default.html</welcome-file> + <welcome-file>default.htm</welcome-file> + <welcome-file>default.jsp</welcome-file> + </welcome-file-list> + + <!-- Spring context loaded --> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value> + classpath:spring/gluster-server-security.xml + classpath:spring/gluster-server-base.xml + </param-value> + </context-param> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + <listener> + <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> + </listener> + + <!-- Jersey REST servlet --> + <servlet> + <servlet-name>gluster-resources</servlet-name> + <!-- servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class --> + <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> + <init-param> + <param-name>com.sun.jersey.config.property.packages</param-name> + <param-value>com.gluster.storage.management.server.resources</param-value> + </init-param> + <load-on-startup>1</load-on-startup> + </servlet> + <servlet-mapping> + <servlet-name>gluster-resources</servlet-name> + <url-pattern>/resources/*</url-pattern> + </servlet-mapping> + + <!-- JNLP download servlet --> + <servlet> + <servlet-name>JnlpDownloadServlet</servlet-name> + <servlet-class>jnlp.sample.servlet.JnlpDownloadServlet</servlet-class> + </servlet> + <servlet-mapping> + <servlet-name>JnlpDownloadServlet</servlet-name> + <url-pattern>*.jnlp</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>JnlpDownloadServlet</servlet-name> + <url-pattern>*.jar</url-pattern> + </servlet-mapping> + + <!-- Spring Security --> + <filter> + <filter-name>springSecurityFilterChain</filter-name> + <filter-class> + org.springframework.web.filter.DelegatingFilterProxy + </filter-class> + </filter> + <filter-mapping> + <filter-name>springSecurityFilterChain</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> +</web-app> diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Common.py b/src/com.gluster.storage.management.server/WebContent/scripts/Common.py new file mode 100644 index 00000000..60f200fe --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Common.py @@ -0,0 +1,34 @@ +# Copyright (c) 2009 Gluster, Inc. <http://www.gluster.com>
+# This file is part of GlusterSP.
+#
+# GlusterSP is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+#
+# GlusterSP is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import sys
+import syslog
+
+def log(priority, message=None):
+ if type(priority) == type(""):
+ logPriority = syslog.LOG_INFO
+ logMessage = priority
+ else:
+ logPriority = priority
+ logMessage = message
+ if not logMessage:
+ return
+ #if Globals.DEBUG:
+ # sys.stderr.write(logMessage)
+ else:
+ syslog.syslog(logPriority, logMessage)
+ return
diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py b/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py new file mode 100644 index 00000000..6e68adbd --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py @@ -0,0 +1,3 @@ +MULTICAST_GROUP = '224.224.1.1'
+MULTICAST_PORT = 5353
+DISCOVERED_SERVER_LIST_FILENAME = "/tmp/discovered-server-list"
diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py b/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py new file mode 100755 index 00000000..6ac15fed --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. <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 socket +import signal +import struct +import syslog +import Globals +import Common + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if response and response[0].upper() != "SERVERDISCOVERY": + servers.append(response[0]) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Common.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + #fp = open(Globals.DISCOVERED_SERVER_LIST_FILENAME, "w") + #fp.writelines(list(servers)) + #fp.close() + for server in servers: + print server + except IOError: + Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + + #for serverName in servers: + # print serverName + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/buckminster.cspex b/src/com.gluster.storage.management.server/buckminster.cspex new file mode 100644 index 00000000..31eb9d67 --- /dev/null +++ b/src/com.gluster.storage.management.server/buckminster.cspex @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<cspecExtension + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" + xmlns="http://www.eclipse.org/buckminster/CSpec-1.0"> + <dependencies> + <!-- Place your Dependencies here --> + </dependencies> + <generators> + <!-- Place your Generators here --> + </generators> + <artifacts> + <!-- Place your Artifacts here --> + </artifacts> + <actions> + <public name="archive" actor="ant"> + <actorProperties> + <property key="buildFile" value="build/glusterserver.ant"/> + </actorProperties> + </public> + </actions> + <groups> + <!-- Place your Groups here --> + </groups> + <alterDependencies> + <!-- Place your Dependency alterations here --> + </alterDependencies> + <alterArtifacts> + <!-- Place your Artifact alterations here --> + </alterArtifacts> + <alterActions> + <!-- Place your Action alterations here --> + </alterActions> + <alterGroups> + <!-- Place your Group alterations here --> + </alterGroups> +</cspecExtension> diff --git a/src/com.gluster.storage.management.server/build/glusterserver.ant b/src/com.gluster.storage.management.server/build/glusterserver.ant new file mode 100644 index 00000000..88602fb6 --- /dev/null +++ b/src/com.gluster.storage.management.server/build/glusterserver.ant @@ -0,0 +1,64 @@ +<project name="com.gluster.storage.management.server" basedir="." default="archive"> + <echo message="basedir=${basedir}" /> + <echo message="buckminster.output=${buckminster.output}" /> + <property name="WEB-INF" value="${basedir}/WebContent/WEB-INF" /> + <property name="OUT" value="${buckminster.output}/glusterserver/" /> + <property name="WAR_FILE_NAME" value="glustermc.war" /> + <property name="TEMP" value="${buckminster.output}/temp" /> + + <target name="help"> + <echo> + -------------------------------------------------- + compile - Compile + archive - Generate WAR file + -------------------------------------------------- + </echo> + </target> + + <target name="init"> + <delete dir="${WEB-INF}/classes" /> + <mkdir dir="${WEB-INF}/classes" /> + <mkdir dir="${WEB-INF}/classes/spring" /> + <mkdir dir="${WEB-INF}/classes/data" /> + </target> + + <target name="compile" depends="init"> + <!-- flatten=true means ignore directory structure and copy files directly to destination --> + <copy todir="${WEB-INF}/lib" flatten="true"> + <fileset dir="${buckminster.output}/.." casesensitive="yes"> + <include name="**/*.jar" /> + </fileset> + </copy> + <copy todir="${WEB-INF}/classes/spring"> + <fileset dir="${basedir}/src/spring" casesensitive="yes"> + <include name="**/*.xml" /> + </fileset> + </copy> + <copy todir="${WEB-INF}/classes/data"> + <fileset dir="${basedir}/src/data" casesensitive="yes"> + <include name="**/*.sql" /> + </fileset> + </copy> + <javac srcdir="${basedir}/src" destdir="${WEB-INF}/classes" classpathref="libs" /> + </target> + + <target name="archive" depends="compile"> + <delete dir="${OUT}" /> + <mkdir dir="${OUT}" /> + <delete dir="${TEMP}" /> + <mkdir dir="${TEMP}" /> + <copy todir="${TEMP}"> + <fileset dir="${basedir}/WebContent"> + <!-- servlet-api.jar is required during compilation. At runtime, it is picked from tomcat lib directory --> + <exclude name="**/servlet-api.jar" /> + </fileset> + </copy> + <war destfile="${OUT}/${WAR_FILE_NAME}" basedir="${TEMP}" compress="true" webxml="${TEMP}/WEB-INF/web.xml" /> + <delete dir="${TEMP}" /> + </target> + + <path id="libs"> + <fileset includes="*.jar" dir="${WEB-INF}/lib" /> + </path> + +</project>
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java new file mode 100644 index 00000000..384038f4 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java @@ -0,0 +1,120 @@ +/** + * DefaultVolumeOptions.java + * + * Copyright (c) 2011 Gluster, Inc. <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.constants; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +@XmlRootElement +public class VolumeOptionsDefaults { + @XmlElementWrapper(name = "volumeOptions") + @XmlElement(name = "volumeOption", type = VolumeOptionInfo.class) + public List<VolumeOptionInfo> options; + + public VolumeOptionsDefaults() { + } + + public VolumeOptionsDefaults getDefaults() { + options = getVolumeOptionsInfo(); + return this; + } + + /** + * Fetches the list of all volume options with their information from GlusterFS and returns the same + * + * @return List of volume option information objects + */ + private List<VolumeOptionInfo> getVolumeOptionsInfo() { + List<VolumeOptionInfo> volumeOptionsInfo = new ArrayList<VolumeOptionInfo>(); + + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.stripe-block-size", + "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " + + CoreConstants.NEWLINE + + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern <filename-pattern:blk-size>. ", + "*:128KB")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.self-heal-window-size", + "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", + "16")); + volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", + "cluster.data-self-heal-algorithm", "auto")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "network.frame-timeout", + "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", + "1800")); + volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", + "The time duration for which the client waits to check if the server is responsive.", "42")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", + "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", + "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.cache-refresh-timeout", + "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", + "1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", + "Size of the per-file write-behind buffer.", "1MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", + "performance.cache-max-file-size", "-1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", + "performance.cache-min-file-size", "0")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.io-thread-count", + " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", + "16")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "diagnostics.latency-measurement", + "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", + "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", + "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", + "Changes the log-level of the bricks (servers).", "NORMAL")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", + "Changes the log-level of the clients.", "NORMAL")); + volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", + "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", + "off")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "nfs.mem-factor", + "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", + "15")); + volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); + + return volumeOptionsInfo; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java new file mode 100644 index 00000000..e669a130 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java @@ -0,0 +1,48 @@ +/** + * GlusterDataSource.java + * + * Copyright (c) 2011 Gluster, Inc. <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.data; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.stereotype.Component; + +@Component +public class GlusterDataSource extends DriverManagerDataSource { + @Autowired + ServletContext servletContext; + + public GlusterDataSource() { + setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); + + setUsername("gluster"); + // TODO: change to a stronger (encrypted) password + setPassword("gluster"); + } + + public DriverManagerDataSource getDataSource() { + // Database directory = work/data relative to context root + setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); + + return this; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java new file mode 100644 index 00000000..004160a7 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java @@ -0,0 +1,79 @@ +/** + * AbstractServersResource.java + * + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.Server; + +/** + * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". + */ +public class AbstractServersResource { + // TODO: Used for generating dummy ip address. To be removed after implementing actual logic for fetching server + // details + private static int ipCount = 1; + + /** + * Fetch details of the given server. The server name must be populated in the object before calling this method. + * + * @param server + * Server whose details are to be fetched + */ + protected void fetchServerDetails(Server server) { + String serverName = server.getName(); + + // TODO: Fetch the server details and populate in the object. + // For now, populating dummy data. + populateDummyData(server); + } + + /** + * @param server + */ + private void populateDummyData(Server server) { + server.setNumOfCPUs((int) (Math.ceil(Math.random() * 8))); + server.setCpuUsage(Math.random() * 100); + server.setTotalMemory(Math.ceil(Math.random() * 8)); + server.setMemoryInUse(Math.random() * server.getTotalMemory()); + addDummyDisks(server); + addDummyNetworkInterfaces(server, (int) Math.ceil(Math.random() * 4)); + } + + private void addDummyNetworkInterfaces(Server server, int interfaceCount) { + for (int i = 0; i < interfaceCount; i++) { + server.addNetworkInterface(new NetworkInterface("eth" + i, server, "192.168.1." + ipCount++, + "255.255.255.0", "192.168.1.1")); + } + } + + /** + * @param server + */ + private void addDummyDisks(Server server) { + double dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sda", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sdb", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + dummyDiskSpace = Math.random() * 500; + server.addDisk(new Disk(server, "sdc", dummyDiskSpace, Math.random() * dummyDiskSpace, Disk.DISK_STATUS.READY)); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java new file mode 100644 index 00000000..5987857a --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerListResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.StringListResponse; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path("/discoveredservers") +public class DiscoveredServersResource extends AbstractServersResource { + private List<String> discoveredServerNames = new ArrayList<String>(); + + public List<String> getDiscoveredServerNames() { + return discoveredServerNames; + } + + @GET + @Produces(MediaType.TEXT_XML) + public Response getDiscoveredServers(@QueryParam("details") Boolean getDetails) { + if(getDetails != null && getDetails == true) { + return new ServerListResponse(Status.STATUS_SUCCESS, getDiscoveredServerDetails()); + } + return new StringListResponse(getDiscoveredServerNames()); + } + + private List<Server> getDiscoveredServerDetails() { + List<Server> discoveredServers = new ArrayList<Server>(); + List<String> serverNames = getDiscoveredServerNames(); + for (String serverName : serverNames) { + discoveredServers.add(getDiscoveredServer(serverName)); + } + return discoveredServers; + } + + public void setDiscoveredServerNames(List<String> discoveredServerNames) { + synchronized (discoveredServerNames) { + this.discoveredServerNames = discoveredServerNames; + } + } + + @Path("/{serverName}") + @GET + @Produces(MediaType.TEXT_XML) + public Server getDiscoveredServer(@PathParam("serverName") String serverName) { + Server server = new Server(serverName); + fetchServerDetails(server); + return server; + } + + public static void main(String[] args) { + StringListResponse listResponse = (StringListResponse)new DiscoveredServersResource().getDiscoveredServers(false); + for (String server : listResponse.getData()) { + System.out.println(server); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java new file mode 100644 index 00000000..6204bf9b --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.model.GlusterServerListResponse; +import com.gluster.storage.management.core.model.GlusterServerResponse; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.utils.GlusterUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path("/cluster/servers") +public class GlusterServersResource extends AbstractServersResource { + private GlusterUtil glusterUtil = new GlusterUtil(); + public static final String HOSTNAMETAG = "hostname:"; + + private List<GlusterServer> getServerDetails() { + List<GlusterServer> glusterServers = glusterUtil.getGlusterServers(); + for (GlusterServer server : glusterServers) { + if (server.getStatus() == SERVER_STATUS.ONLINE) { + fetchServerDetails(server); + // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); + } + } + return glusterServers; + } + + @GET + @Produces(MediaType.TEXT_XML) + public GlusterServerListResponse getGlusterServers() { + return new GlusterServerListResponse(Status.STATUS_SUCCESS, getServerDetails()); + } + + @GET + @Path("{serverName}") + @Produces(MediaType.TEXT_XML) + public GlusterServer getGlusterServer(@PathParam("serverName") String serverName) { + GlusterServer server = new GlusterServer(serverName); + fetchServerDetails(server); + // server.setPreferredNetworkInterface(server.getNetworkInterfaces().get(0)); + server.setStatus(SERVER_STATUS.ONLINE); + return server; + } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.server.resources.AbstractServersResource#fetchServerDetails(com.gluster.storage + * .management.core.model.Server) + */ + @Override + protected void fetchServerDetails(Server server) { + // fetch standard server details like cpu, disk, memory details + super.fetchServerDetails(server); + + // TODO: Fetch gluster server details like status + } + + @POST + @Produces(MediaType.TEXT_XML) + public GlusterServerResponse addServer(@FormParam("serverName") String serverName) { + ProcessResult result = glusterUtil.addServer(serverName); + + if (!result.isSuccess()) { + Status failure = new Status(Status.STATUS_CODE_FAILURE, "Add server [" + serverName + "] failed: [" + result.getExitValue() + + "][" + result.getOutput() + "]"); + return new GlusterServerResponse(failure, null); + } + return new GlusterServerResponse(Status.STATUS_SUCCESS, getGlusterServer(serverName)); + } + + public static void main(String[] args) { + GlusterServersResource glusterServersResource = new GlusterServersResource(); + System.out.println(glusterServersResource.getServerDetails()); + + // To add a server + GlusterServerResponse response = glusterServersResource.addServer("my-server"); + System.out.println(response.getData().getName()); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java new file mode 100644 index 00000000..4e379199 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/Hello.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +//Sets the path to base URL + /hello +@Path("/hello") +public class Hello { + // This method is called if TEXT_PLAIN is request + @GET + @Produces(MediaType.TEXT_PLAIN) + public String sayPlainTextHello() { + return "Hello Jersey"; + } + + // This method is called if XMLis request + @GET + @Produces(MediaType.TEXT_XML) + public String sayXMLHello() { + return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>"; + } + + // This method is called if HTML is request + @GET + @Produces(MediaType.TEXT_HTML) + public String sayHtmlHello() { + return "<html> " + "<title>" + "Hello Jersey" + "</title>" + + "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> "; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java new file mode 100644 index 00000000..2cec4c36 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/RunningTaskResource.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_RUNNING_TASKS; +import com.gluster.storage.management.core.model.Response; +import com.gluster.storage.management.core.model.RunningTask; +import com.gluster.storage.management.core.model.RunningTaskListResponse; +import com.gluster.storage.management.core.model.RunningTaskStatus; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.server.runningtasks.managers.RunningTaskManager; + +@Component +@Path(RESOURCE_PATH_RUNNING_TASKS) +public class RunningTaskResource { + + @GET + @Produces(MediaType.TEXT_XML) + public RunningTaskListResponse getRunningTasks() { + + RunningTaskStatus status = new RunningTaskStatus(); + List<RunningTask> runningTasks = new ArrayList<RunningTask>(); + + status.setCode(Status.STATUS_CODE_RUNNING); + status.setPercentageSupported(false); + + // Volume rebalance + RunningTask task = new RunningTask(); + task.setId("0001"); + task.setType("VolumeRebalance"); + task.setReference(""); + task.setDescription("Volume [Volume1] rebalance is running"); + task.setStatus(status); + runningTasks.add(task); + + task = new RunningTask(); + task.setId("0002"); + task.setType("VolumeRebalance"); + task.setReference(""); + task.setDescription("Volume [Volume2] rebalance is running"); + //task.setDescription("Error: volume rebalance operation failed at fd 0000 [/export/test-song-volume/mydirectory/test-video.avi"); + task.setStatus(status); + runningTasks.add(task); + + // MigrateDisk + task = new RunningTask(); + task.setId("0003"); + task.setType("MigrateDisk"); + task.setReference(""); + task.setDescription("Disk migration [Volume3/sda] is running"); + task.setStatus(status); + runningTasks.add(task); + + // FormatDisk + task = new RunningTask(); + task.setId("0004"); + task.setType("FormatDisk"); + task.setReference(""); + task.setDescription("Volume [vol1] rebalance is running"); + status.setPercentageSupported(true); + status.getPercentCompleted(45); + task.setStatus(status); + runningTasks.add(task); + return new RunningTaskListResponse(Status.STATUS_SUCCESS, runningTasks); + } + + @SuppressWarnings("rawtypes") + public Response startTask(@FormParam("taskType") String taskType) { + String managerClassName = "com.gluster.storage.management.server.runningtasks.managers." + taskType + "Manager"; + Class managerClass; + RunningTaskManager manager = null; + try { + managerClass = Class.forName(managerClassName); + manager = (RunningTaskManager) managerClass.newInstance(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + // TODO: set form params on the manager + Map params = null; + manager.setFormParams(params); + manager.start(); + return null; + } + + // TODO Remove the test script for production + public static void main(String[] args) { + RunningTaskResource rt = new RunningTaskResource(); + RunningTaskListResponse tasks = rt.getRunningTasks(); + List<RunningTask> runningTasks = tasks.getRunningTasks(); + for( RunningTask x : runningTasks) { + System.out.println( x.getId() + " : " + x.getType() + " : " + x.getDescription() ); + } + } +} + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java new file mode 100644 index 00000000..97b874e2 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ServerResource.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources;
+
+import java.io.File;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.gluster.storage.management.core.utils.FileUtil;
+import com.gluster.storage.management.core.utils.MD5Crypt;
+import com.gluster.storage.management.core.utils.ProcessResult;
+import com.gluster.storage.management.core.utils.ProcessUtil;
+
+@Path("/server")
+public class ServerResource {
+ // TODO: xml should be read from a "work" directory under the tomcat server.
+ // Use relative path - do not hard code the absolute path.
+ public static final String DISCOVERED_SERVERS_XML = "/GLUSTER/discovered-servers.xml";
+
+ /**
+ * Discover newly available servers
+ *
+ * @return list of discovered servers
+ */
+ private String GetDiscoveredServers() {
+ File discoveredServersFile = new File(DISCOVERED_SERVERS_XML);
+ String serverNames = new FileUtil().readFileAsString(discoveredServersFile);
+ return serverNames;
+ }
+
+ @Path("/discover")
+ @GET
+ @Produces(MediaType.TEXT_XML)
+ public String discoveredServers() {
+ return GetDiscoveredServers();
+ }
+
+ private String GetDetails() {
+ ProcessResult result = new ProcessUtil().executeCommand("get-server-details.py");
+ if (!result.isSuccess()) {
+ //TODO:Generate error message and return
+ }
+ return result.getOutput();
+ }
+
+ @Path("/details")
+ @GET
+ @Produces(MediaType.TEXT_XML)
+ public String serverDetails() {
+ return GetDetails();
+ }
+
+}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java new file mode 100644 index 00000000..51134317 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.encoding.PasswordEncoder; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.provisioning.JdbcUserDetailsManager; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Status; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Component +@Path("/users") +public class UsersResource { + @Autowired + private JdbcUserDetailsManager jdbcUserService; + + @Autowired + private PasswordEncoder passwordEncoder; + + /** + * Authenticates given user with given password for login on current system + * + * @param user + * @param password + * @return true is user can be successfully authenticated using given password, else false + */ + /* + * NOTE: This method is no more required as user authentication is performed on every request by the spring security + * framework. Can be removed after testing. + */ + /* + * private boolean authenticate(String user, String password) { String tmpFileName = "tmp"; File saltFile = new + * File(tmpFileName); ProcessResult result = new ProcessUtil().executeCommand("get-user-password.py", user, + * tmpFileName); if (result.isSuccess()) { String salt = new FileUtil().readFileAsString(saltFile); String + * encryptedPassword = MD5Crypt.crypt(password, salt); return encryptedPassword.equals(salt); } + * + * return false; } + */ + + @Path("{user}") + @GET + @Produces(MediaType.TEXT_XML) + public Status login(@PathParam("user") String user) { + // success only if the user passed in query is same as the one passed in security header + return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? Status.STATUS_SUCCESS + : Status.STATUS_FAILURE); + } + + @Path("{user}") + @PUT + @Produces(MediaType.TEXT_XML) + public Status changePassword(@FormParam("oldpassword") String oldPassword, + @FormParam("newpassword") String newPassword) { + try { + jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); + } catch (AuthenticationException ex) { + ex.printStackTrace(); + return new Status(Status.STATUS_CODE_FAILURE, "Could not change password: [" + ex.getMessage() + "]"); + } + return Status.STATUS_SUCCESS; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java new file mode 100644 index 00000000..dfa5a5cc --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -0,0 +1,93 @@ +/** + * VolumesResource.java + * + * Copyright (c) 2011 Gluster, Inc. <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.resources; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_START; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_STOP; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_VOLUMES; +import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_DEFAULT_OPTIONS; + +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.gluster.storage.management.core.model.GenericResponse; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.GlusterUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.server.constants.VolumeOptionsDefaults; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Path(RESOURCE_PATH_VOLUMES) +public class VolumesResource { + private final GlusterUtil glusterUtil = new GlusterUtil(); + + @POST + @Consumes(MediaType.TEXT_XML) + @Produces(MediaType.TEXT_XML) + public GenericResponse<String> createVolume(Volume volume) { + ProcessResult response = glusterUtil.createVolume(volume); + if (!response.isSuccess()) { + return new GenericResponse<String>(Status.STATUS_FAILURE, "Volume creation failed: [" + + response.getOutput() + "]"); + } + + response = glusterUtil.setVolumeAccessControl(volume); + + return new GenericResponse<String>(Status.STATUS_SUCCESS, response.getOutput()); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.TEXT_XML) + public Status performOperation(@FormParam(FORM_PARAM_OPERATION) String operation, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + + if (operation.equals(FORM_PARAM_VALUE_START)) { + return new Status(glusterUtil.startVolume(volumeName)); + } + if (operation.equals(FORM_PARAM_VALUE_STOP)) { + return new Status(glusterUtil.stopVolume(volumeName)); + } + return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + } + + @GET + @Path(SUBRESOURCE_DEFAULT_OPTIONS) + @Produces(MediaType.TEXT_XML) + public VolumeOptionsDefaults getDefaultOptions() { + // TODO: Fetch all volume options with their default values from GlusterFS + // whenever such a CLI command is made available in GlusterFS + return new VolumeOptionsDefaults().getDefaults(); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java new file mode 100644 index 00000000..37cc22f6 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/FormatDiskManager.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class FormatDiskManager implements RunningTaskManager { + + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java new file mode 100644 index 00000000..97916abe --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/MigrateDiskManager.java @@ -0,0 +1,50 @@ +package com.gluster.storage.management.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class MigrateDiskManager implements RunningTaskManager { + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java new file mode 100755 index 00000000..a21c6b81 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/RunningTaskManager.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <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.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public interface RunningTaskManager { + + public String getId(); + + public RunningTaskStatus start(); + + public RunningTaskStatus stop(); + + public RunningTaskStatus pause(); + + public RunningTaskStatus resume(); + + public RunningTaskStatus getStatus(); + + @SuppressWarnings("rawtypes") + public void setFormParams(Map params); + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java new file mode 100644 index 00000000..01a5dc25 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/runningtasks/managers/VolumeRebalanceManager.java @@ -0,0 +1,50 @@ +package com.gluster.storage.management.server.runningtasks.managers; + +import java.util.Map; + +import com.gluster.storage.management.core.model.RunningTaskStatus; + +public class VolumeRebalanceManager implements RunningTaskManager { + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus start() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus stop() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus pause() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RunningTaskStatus resume() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFormParams(Map params) { + // TODO Auto-generated method stub + + } + + @Override + public RunningTaskStatus getStatus() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java new file mode 100644 index 00000000..21c13a03 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java @@ -0,0 +1,31 @@ +/** + * GlusterUserDetailsService.java + * + * Copyright (c) 2011 Gluster, Inc. <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.security; + +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * + */ +public interface GlusterUserDetailsService extends UserDetailsService { + void changePassword(String username, String password); +} + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java new file mode 100644 index 00000000..cfc6e572 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java @@ -0,0 +1,42 @@ +/** + * UserAuthDao.java + * + * Copyright (c) 2011 Gluster, Inc. <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.security; + +import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; + +/** + * @author root + * + */ +public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.server.security.GlusterUserDetailsService#changePassword(java.lang.String, + * java.lang.String) + */ + @Override + public void changePassword(String username, String password) { + getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java new file mode 100644 index 00000000..d96db6ca --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java @@ -0,0 +1,99 @@ +/** + * GlusterServerInitializer.java + * + * Copyright (c) 2011 Gluster, Inc. <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.tasks; + +import java.io.ByteArrayOutputStream; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.apache.derby.tools.ij; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.security.authentication.encoding.PasswordEncoder; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.utils.FileUtil; + +/** + * Initializes the Gluster Management Server. + */ +public class InitServerTask extends JdbcDaoSupport { + @Autowired + private PasswordEncoder passwordEncoder; + + public void securePasswords() { + getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + String username = rs.getString(1); + String password = rs.getString(2); + String encodedPassword = passwordEncoder.encodePassword(password, null); + getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); + logger.debug("Updating password for username: " + username); + } + }); + } + + private void executeScript(String script) { + ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); + int numOfExceptions; + try { + numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), + new FileUtil().loadResource(script), CoreConstants.ENCODING_UTF8, sqlOut, + CoreConstants.ENCODING_UTF8); + String output = sqlOut.toString(); + sqlOut.close(); + logger.debug("Data script [" + script + "] returned with exit status [" + numOfExceptions + + "] and output [" + output + "]"); + if (numOfExceptions != 0) { + throw new GlusterRuntimeException("Server data initialization script [ " + script + "] failed with [" + + numOfExceptions + "] exceptions! [" + output + "]"); + } + } catch (Exception ex) { + ex.printStackTrace(); + throw new GlusterRuntimeException("Server data initialization script [" + script + "] failed!", ex); + } + } + + private void initDatabase() { + logger.debug("Initializing server data..."); + executeScript("data/scripts/security-schema.sql"); + executeScript("data/scripts/users-authorities-groups.sql"); + securePasswords(); // encrypt the passwords + } + + /** + * Initializes the server database, if running for the first time. + */ + public synchronized void initServer() { + try { + // Query to check whether the user table exists + getJdbcTemplate().queryForInt("select count(*) from users"); + logger.debug("Server data is already initialized!"); + } catch (DataAccessException ex) { + // Database not created yet. Create it! + initDatabase(); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java new file mode 100644 index 00000000..9fcb28e6 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java @@ -0,0 +1,75 @@ +/** + * ServerDiscoveryTask.java + * + * Copyright (c) 2011 Gluster, Inc. <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.tasks; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.server.resources.DiscoveredServersResource; +import com.gluster.storage.management.server.utils.ServerUtil; +import com.sun.jersey.spi.resource.Singleton; + +/** + * Task for auto-discovery of servers eligible to be added to the Gluster cluster. This task runs periodically and keeps + * the discovered server list at a common place. The server resource can then pick it and send to client whenever + * demanded. + */ +@Singleton +@Component +public class ServerDiscoveryTask { + private static final String ENV_AWS = "aws"; + private static final String ENV_VMWARE = "vmware"; + private static final String ENV_PHYCAL = "physical"; + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private ServletContext servletContext; + + @Autowired + private DiscoveredServersResource discoveredServersResource; + + @Autowired + private String environment; + + public void discoverServers() { + List<String> serverNameList = new ArrayList<String>(); + + ProcessResult result = serverUtil.executeGlusterScript(true, environment + SCRIPT_NAME_SFX, new ArrayList<String>()); + if(result.isSuccess()) { + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + serverNameList = Arrays.asList(parts); + } + + discoveredServersResource.setDiscoveredServerNames(serverNameList); + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java new file mode 100644 index 00000000..1d237461 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java @@ -0,0 +1,58 @@ +/** + * ServerUtil.java + * + * Copyright (c) 2011 Gluster, Inc. <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.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Component +public class ServerUtil { + @Autowired + ServletContext servletContext; + + private static final String SCRIPT_DIR = "scripts"; + private static final String SCRIPT_COMMAND = "python"; + + public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List<String> arguments) { + List<String> command = new ArrayList<String>(); + + command.add(SCRIPT_COMMAND); + command.add(getScriptPath(scriptName)); + command.addAll(arguments); + return new ProcessUtil().executeCommand(runInForeground, command); + } + + private String getScriptPath(String scriptName) { + String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; + return scriptPath; + } +}
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql b/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql new file mode 100644 index 00000000..fdde5823 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/data/scripts/security-schema.sql @@ -0,0 +1,26 @@ +create table users( + username varchar(50) not null primary key, + password varchar(50) not null, + enabled smallint not null + ); + + create table authorities ( + username varchar(50) not null, + authority varchar(50) not null, + constraint fk_authorities_users foreign key(username) references users(username)); + create unique index ix_auth_username on authorities (username,authority); + +create table groups ( + id bigint generated by default as identity(start with 0) primary key, + group_name varchar(50) not null); + +create table group_authorities ( + group_id bigint not null, + authority varchar(50) not null, + constraint fk_group_authorities_group foreign key(group_id) references groups(id)); + +create table group_members ( + id bigint generated by default as identity(start with 0) primary key, + username varchar(50) not null, + group_id bigint not null, + constraint fk_group_members_group foreign key(group_id) references groups(id)); diff --git a/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql b/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql new file mode 100644 index 00000000..35ccf965 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/data/scripts/users-authorities-groups.sql @@ -0,0 +1,21 @@ +-- Create users +insert into users(username, password, enabled) values ('gluster','gluster',1); +insert into users(username, password, enabled) values ('guest','guest',1); + +-- Assign authorities to users (to be removed after implementing user group functionality) +insert into authorities(username,authority) values ('gluster','ROLE_USER'); +insert into authorities(username,authority) values ('gluster','ROLE_ADMIN'); +insert into authorities(username,authority) values ('guest','ROLE_USER'); + +-- Create user groups +insert into groups(group_name) values ('Users'); +insert into groups(group_name) values ('Administrators'); + +-- Add authorities to groups (functionality not yet implemented in code) +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Users'; +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Administrators'; +insert into group_authorities(group_id, authority) select id,'ROLE_ADMIN' from groups where group_name='Administrators'; + +-- Assign group members +insert into group_members(group_id, username) select id,'guest' from groups where group_name='Users'; +insert into group_members(group_id, username) select id,'gluster' from groups where group_name='Administrators';
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml new file mode 100644 index 00000000..86a8708f --- /dev/null +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml @@ -0,0 +1,50 @@ + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" + xmlns:task="http://www.springframework.org/schema/task" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd + http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> + <context:component-scan base-package="com.gluster.storage.management.server" /> + <task:scheduler id="taskScheduler" /> + <task:executor id="taskExecutor" pool-size="1" /> + <task:annotation-driven executor="taskExecutor" + scheduler="taskScheduler" /> + + <task:scheduled-tasks> + <task:scheduled ref="serverDiscoveryTask" method="discoverServers" + fixed-delay="60000" /> + </task:scheduled-tasks> + + <bean id="environment" class="java.lang.String"> + <constructor-arg value="vmware" /> + </bean> + + <!-- Derby embedded data source --> + <!-- bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" + lazy-init="false"> <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" + /> <property name="url" value="jdbc:derby:work/data;create=true" /> <property + name="username" value="gluster" /> <property name="password" value="gluster" + /> </bean --> + + <bean id="dataSourceFactory" + class="com.gluster.storage.management.server.data.GlusterDataSource" /> + <bean id="dataSource" + class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> + <property name="targetObject"> + <ref local="dataSourceFactory" /> + </property> + <property name="targetMethod"> + <value>getDataSource</value> + </property> + </bean> + + <!-- bean id="dataSource" class="com.gluster.storage.management.server.data.GlusterDataSource" + lazy-init="false" autowire="byType" / --> + + <bean class="com.gluster.storage.management.server.tasks.InitServerTask" + init-method="initServer" depends-on="dataSource"> + <property name="dataSource" ref="dataSource" /> + </bean> +</beans>
\ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml new file mode 100644 index 00000000..0de97761 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans:beans xmlns="http://www.springframework.org/schema/security" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:jdbc="http://www.springframework.org/schema/jdbc" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd + http://www.springframework.org/schema/security + http://www.springframework.org/schema/security/spring-security-3.0.xsd + "> + + <http auto-config="true" use-expressions="true"> + <intercept-url pattern="/resources/*" + access="hasRole('ROLE_ADMIN') and fullyAuthenticated" /> + <intercept-url pattern="/*" access="permitAll" /> + <!-- SSL Protection --> + <!-- <intercept-url pattern="/resources/*" access="hasRole('ROLE_ADMIN') + and fullyAuthenticated" requires-channel="https"/> <intercept-url pattern="/*" + access="permitAll" requires-channel="any"/> --> + <port-mappings> + <port-mapping http="8080" https="8443" /> + </port-mappings> + + <!-- HTTP basic authentication --> + <http-basic /> + </http> + + <beans:bean + class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" + id="passwordEncoder" /> + + <authentication-manager alias="authenticationManager"> + <authentication-provider user-service-ref="jdbcUserService"> + <!-- Passwords are SHA encrypted --> + <password-encoder hash="sha" /> + </authentication-provider> + </authentication-manager> + + <beans:bean id="jdbcUserService" + class="org.springframework.security.provisioning.JdbcUserDetailsManager" + lazy-init="false"> + <beans:property name="dataSource" ref="dataSource" /> + <beans:property name="authenticationManager" ref="authenticationManager" /> + </beans:bean> +</beans:beans>
\ No newline at end of file diff --git a/src/com.sun.jersey/.project b/src/com.sun.jersey/.project new file mode 100644 index 00000000..52ec5691 --- /dev/null +++ b/src/com.sun.jersey/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>com.sun.jersey</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> |
