From 1c1911f078b81662590a68e15f1d916534e7524e Mon Sep 17 00:00:00 2001 From: Dhandapani Date: Fri, 1 Jul 2011 16:36:04 +0530 Subject: Volume Rebalance functionality enhancement --- .../storage/management/client/VolumesClient.java | 6 -- .../server/resources/GlusterServersResource.java | 15 ++--- .../server/resources/VolumesResource.java | 2 +- .../server/tasks/InitializeDiskTask.java | 45 +++++++++++--- .../server/tasks/RebalanceVolumeTask.java | 70 ++++++++++------------ .../storage/management/server/tasks/Task.java | 5 +- .../management/server/utils/GlusterUtil.java | 39 ++++++++++++ 7 files changed, 117 insertions(+), 65 deletions(-) (limited to 'src') 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 index b5d2711a..2866a8e1 100644 --- 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 @@ -241,12 +241,6 @@ public class VolumesClient extends AbstractClient { putRequest(volumeName, form); } - public void rebalanceStatus(String volumeName) { - Form form = new Form(); - form.add(RESTConstants.FORM_PARAM_OPERATION, RESTConstants.TASK_REBALANCE_STATUS); - putRequest(volumeName, form); - } - public void rebalanceStop(String volumeName) { Form form = new Form(); form.add(RESTConstants.FORM_PARAM_OPERATION, RESTConstants.TASK_REBALANCE_STOP); diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java index a9ef7fbb..e3bfe158 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java @@ -414,15 +414,12 @@ public class GlusterServersResource extends AbstractServersResource { return badRequestResponse("Disk name must not be empty!"); } - InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, diskName, serverName); - try { - initializeTask.start(); - taskResource.addTask(initializeTask); - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS - + "/" + initializeTask.getId()); - } catch (ConnectionException e) { - return errorResponse(e.getMessage()); - } + InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName); + initializeTask.start(); + taskResource.addTask(initializeTask); + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); } private void setGlusterUtil(GlusterUtil glusterUtil) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java index d568d519..4318945c 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -978,7 +978,7 @@ public class VolumesResource extends AbstractResource { return rebalanceStart(clusterName, volumeName, layout); } - public String rebalanceStart(String clusterName, String volumeName, String layout) { + private String rebalanceStart(String clusterName, String volumeName, String layout) { RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName); rebalanceTask.setLayout(layout); rebalanceTask.start(); diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java index 5f3f8e30..40d7877e 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java @@ -20,21 +20,26 @@ */ package com.gluster.storage.management.server.tasks; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskInfo; import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.utils.GlusterUtil; import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.core.util.Base64; public class InitializeDiskTask extends Task { private static final String INITIALIZE_DISK_SCRIPT = "initialize_disk.py"; - private static final String INITIALIZE_DISK_STATUS_SCRIPT = "initialize_disk_status.py"; private String serverName; private String diskName; private SshUtil sshUtil = new SshUtil(); + private GlusterUtil glusterUtil; public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName) { super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" @@ -50,7 +55,7 @@ public class InitializeDiskTask extends Task { @Override public String getId() { - return taskInfo.getType() + "-" + serverName + ":" + diskName; + return new String(Base64.encode(taskInfo.getType() + "-" + serverName + ":" + diskName)); } @Override @@ -85,17 +90,41 @@ public class InitializeDiskTask extends Task { @Override public void start() { - getTaskInfo().setStatus( - new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_SCRIPT + " " - + getDiskName())))); + try { + startInitializeDisk(getOnlineServer().getName()); + } catch(ConnectionException e) { + // online server might have gone offline. try with a new one + startInitializeDisk(getNewOnlineServer().getName()); + } + } + + private void startInitializeDisk(String serverName) { + ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_SCRIPT + " " + getDiskName()); + if (processResult.isSuccess()) { + // TODO: Message needs to change according to the script return + if (processResult.getOutput().trim().matches(".*has been successful$")) { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + return; + } + } + + // if we reach here, it means Initialize disk start failed. + throw new GlusterRuntimeException(processResult.toString()); + } @Override public TaskStatus checkStatus() { - return new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_STATUS_SCRIPT + " " - + getDiskName()))); + + try { + return glusterUtil.checkInitializeDiskStatus(getOnlineServer().getName(), getDiskName()); + } catch(ConnectionException e) { + // online server might have gone offline. try with a new one + return glusterUtil.checkInitializeDiskStatus(getNewOnlineServer().getName(), getDiskName()); + } } - + public void setDiskName(String diskName) { this.diskName = diskName; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java index 7f9fb6bf..33655b3f 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java @@ -28,33 +28,40 @@ import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; import com.gluster.storage.management.core.model.TaskStatus; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.utils.GlusterUtil; import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.core.util.Base64; public class RebalanceVolumeTask extends Task { private String layout; + private String serverName; private SshUtil sshUtil = new SshUtil(); + private GlusterUtil glusterUtil = new GlusterUtil(); public RebalanceVolumeTask(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { super(clusterService, clusterName, taskInfo); } public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName) { - super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume rebalance running on " + volumeName, false, true, false); + super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume rebalance running on " + + volumeName, false, true, false); } @Override public String getId() { - return taskInfo.getType() + "-" + taskInfo.getReference(); + return new String(Base64.encode(taskInfo.getType() + "-" + taskInfo.getReference())); } @Override public void start() { try { - startRebalance(getOnlineServer().getName()); + serverName = getOnlineServer().getName(); + startRebalance(serverName); } catch(ConnectionException e) { // online server might have gone offline. try with a new one - startRebalance(getNewOnlineServer().getName()); + serverName = getNewOnlineServer().getName(); + startRebalance(serverName); } } @@ -63,7 +70,9 @@ public class RebalanceVolumeTask extends Task { ProcessResult processResult = sshUtil.executeRemote(serverName, command); if (processResult.isSuccess()) { if (processResult.getOutput().trim().matches(".*has been successful$")) { - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + return; } } @@ -74,34 +83,34 @@ public class RebalanceVolumeTask extends Task { @Override public void resume() { getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, "Pause/Resume is not supported in Volume Rebalance"))); + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); } @Override public void stop() { try { - stopRebalance(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one - stopRebalance(getNewOnlineServer().getName()); + stopRebalance(serverName); + } catch (ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); } } private void stopRebalance(String serverName) { String command = "gluster volume rebalance " + getTaskInfo().getReference() + " stop"; ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { if (processResult.getOutput().trim().matches(".*has been successful$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, processResult.getOutput()))); + return; } - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); } - taskStatus.setMessage(processResult.getOutput()); // Common - getTaskInfo().setStatus(taskStatus); + + // if we reach here, it means rebalance stop failed. + throw new GlusterRuntimeException(processResult.toString()); } @Override @@ -113,31 +122,14 @@ public class RebalanceVolumeTask extends Task { @Override public TaskStatus checkStatus() { try { - return checkRebalanceStatus(getOnlineServer().getName()); + return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - return checkRebalanceStatus(getNewOnlineServer().getName()); + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + return getTaskInfo().getStatus(); } } - // TODO: This method should move to glusterUtil - private TaskStatus checkRebalanceStatus(String serverName) { - String command = "gluster volume rebalance " + getTaskInfo().getReference() + " status"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*rebalance completed$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - taskStatus.setMessage(processResult.getOutput()); // Common - return taskStatus; - } - public void setLayout(String layout) { this.layout = layout; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java index 49cd0b8b..c16c039a 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java @@ -33,7 +33,8 @@ public abstract class Task { protected String clusterName; private ClusterService clusterService; - public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, boolean canPause, boolean canStop, boolean canCommit) { + public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, + boolean canPause, boolean canStop, boolean canCommit) { TaskInfo taskInfo = new TaskInfo(); taskInfo.setType(type); taskInfo.setReference(reference); @@ -41,7 +42,7 @@ public abstract class Task { taskInfo.setCanPause(canPause); taskInfo.setCanStop(canStop); taskInfo.setCanCommit(canCommit); - + init(clusterService, clusterName, taskInfo); } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index 788e3eab..a09c7956 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -37,6 +37,7 @@ import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskStatus; 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; @@ -71,6 +72,8 @@ public class GlusterUtil { private static final String VOLUME_TYPE_REPLICATE = "Replicate"; private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); + + private static final String INITIALIZE_DISK_STATUS_SCRIPT = "initialize_disk_status.py"; @Autowired private SshUtil sshUtil; @@ -550,6 +553,42 @@ public class GlusterUtil { throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); } } + + public TaskStatus checkRebalanceStatus(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " status"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches("^rebalance completed.*")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if(processResult.getOutput().trim().matches(".*in progress:.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + return taskStatus; + } + + public TaskStatus checkInitializeDiskStatus(String serverName, String diskName) { + ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + diskName); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + // TODO: Message needs to change according to the script return + if (processResult.getOutput().trim().matches(".*Initailize completed$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); + return taskStatus; + } public static void main(String args[]) { // List names = new GlusterUtil().getGlusterServerNames(); -- cgit From 552e7c7f05bfd553c9d539926f4aca0f08c5c246 Mon Sep 17 00:00:00 2001 From: Selvasundaram Date: Fri, 1 Jul 2011 19:01:12 +0530 Subject: Task updates in UI --- .../management/client/GlusterDataModelManager.java | 19 +++-- .../storage/management/core/model/Cluster.java | 11 ++- .../storage/management/core/model/Event.java | 1 + .../storage/management/core/model/TaskInfo.java | 16 ++-- .../gui/actions/AbstractActionDelegate.java | 6 +- .../management/gui/actions/AddDiskAction.java | 38 ++------- .../management/gui/actions/AddServerAction.java | 27 ++---- .../management/gui/actions/ClearTaskAction.java | 27 ++---- .../management/gui/actions/CommitTaskAction.java | 44 +++++----- .../management/gui/actions/CreateVolumeAction.java | 32 +++---- .../management/gui/actions/DeleteVolumeAction.java | 97 ++++++++++------------ .../gui/actions/DownloadVolumeLogsAction.java | 7 -- .../management/gui/actions/MigrateDiskAction.java | 2 - .../management/gui/actions/PauseTaskAction.java | 31 +++---- .../gui/actions/RebalanceVolumeAction.java | 24 ++---- .../management/gui/actions/RemoveDiskAction.java | 66 ++++++--------- .../management/gui/actions/RemoveServerAction.java | 4 - .../management/gui/actions/ResumeTaskAction.java | 30 +++---- .../management/gui/actions/StartVolumeAction.java | 7 -- .../management/gui/actions/StopTaskAction.java | 28 +++---- .../management/gui/actions/StopVolumeAction.java | 45 +++++----- .../management/gui/views/pages/TasksPage.java | 24 +++++- .../management/server/tasks/MigrateDiskTask.java | 20 +++-- .../storage/management/server/tasks/Task.java | 6 +- 24 files changed, 263 insertions(+), 349 deletions(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index be7a9023..a1c7823a 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -162,8 +162,8 @@ public class GlusterDataModelManager { } public void initializeTasks(Cluster cluster) { - // List taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); - List taskInfoList = getDummyTasks(); + List taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); + // List taskInfoList = getDummyTasks(); cluster.setTaskInfoList(taskInfoList); } @@ -174,8 +174,8 @@ public class GlusterDataModelManager { TaskInfo taskInfo = new TaskInfo(); taskInfo.setType(TASK_TYPE.BRICK_MIGRATE); taskInfo.setName("Migrate Brick-music"); - taskInfo.setCanPause(true); - taskInfo.setCanStop(true); + taskInfo.setPauseSupported(true); + taskInfo.setStopSupported(true); taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, ""))); taskInfo.getStatus().setMessage("Migrating file xxxxx to yyyy"); @@ -185,8 +185,8 @@ public class GlusterDataModelManager { taskInfo = new TaskInfo(); taskInfo.setType(TASK_TYPE.DISK_FORMAT); taskInfo.setName("Format Disk-server1:sdc"); - taskInfo.setCanPause(false); - taskInfo.setCanStop(false); + taskInfo.setPauseSupported(false); + taskInfo.setStopSupported(false); taskInfo.setStatus( new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, ""))); taskInfo.getStatus().setMessage("Format completes 80% ..."); taskInfo.setDescription("Formatting disk server1:sdc."); @@ -407,6 +407,13 @@ public class GlusterDataModelManager { listener.volumeCreated(volume); } } + + public void updateVolumeBricks(Volume volume, List bricks) { + model.getCluster().updateVolume( volume.getName(), bricks ); + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICK_REPLACED , bricks)); + } + } public void addTask(TaskInfo taskInfo) { Cluster cluster = model.getCluster(); 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 index d6757cba..56b52659 100644 --- 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 @@ -55,7 +55,7 @@ public class Cluster extends Entity { } public void deleteVolume(Volume volume) { - volumes.remove(volume); + volumes.remove(volume); } public void setServers(List servers) { @@ -93,6 +93,15 @@ public class Cluster extends Entity { public void addVolume(Volume volume) { this.volumes.add(volume); } + + public void updateVolume(String volumeName, List bricks) { + for (Volume volume : volumes) { + if (volume.getName().equals(volumeName)) { + volume.setBricks(bricks); + return; + } + } + } public Cluster(String name, Entity parent) { super(name, parent); 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 index 99594b5d..1e172d1c 100644 --- 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 @@ -22,6 +22,7 @@ public class Event { public enum EVENT_TYPE { BRICKS_ADDED, BRICKS_REMOVED, + BRICK_REPLACED, NETWORK_INTERFACE_ADDED, NETWORK_INTERFACE_REMOVED, VOLUME_STATUS_CHANGED, diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java index 1ce2fa04..d3267ec4 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java @@ -78,28 +78,28 @@ public class TaskInfo extends Entity { public void setStatus(TaskStatus status) { this.status = status; } - - public Boolean canPause() { + + public Boolean getPauseSupported() { return pauseSupported; } - public void setCanPause(Boolean canPause) { + public void setPauseSupported(Boolean canPause) { this.pauseSupported = canPause; } - public Boolean canStop() { + public Boolean getStopSupported() { return stopSupported; } - - public void setCanStop(Boolean canStop) { + + public void setStopSupported(Boolean canStop) { this.stopSupported = canStop; } - public Boolean canCommit() { + public Boolean getCommitSupported() { return this.commitSupported; } - public void setCanCommit(Boolean canCommit) { + public void setCommitSupported(Boolean canCommit) { this.commitSupported = canCommit; } 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 index 859d76db..6498d902 100644 --- 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 @@ -18,8 +18,6 @@ *******************************************************************************/ package com.gluster.storage.management.gui.actions; -import java.util.Set; - import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; @@ -31,13 +29,13 @@ import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.internal.UIPlugin; import com.gluster.storage.management.core.model.Entity; -import com.gluster.storage.management.gui.utils.GUIHelper; /** * 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. */ +@SuppressWarnings("restriction") public abstract class AbstractActionDelegate implements IWorkbenchWindowActionDelegate { protected IWorkbenchWindow window; @@ -56,7 +54,7 @@ public abstract class AbstractActionDelegate implements IWorkbenchWindowActionDe }); } - abstract protected void performAction(IAction action); + abstract protected void performAction(final IAction action); @Override public void selectionChanged(IAction action, ISelection selection) { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java index cc57c541..be2cacee 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java @@ -24,7 +24,6 @@ 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.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.Volume; @@ -34,43 +33,24 @@ public class AddDiskAction extends AbstractActionDelegate { private Volume volume; private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); - /* (non-Javadoc) - * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() - */ @Override public void dispose() { window = null; } - /* (non-Javadoc) - * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) - */ @Override protected void performAction(IAction action) { - //TODO: open a dialog box - // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + volume.getName()); - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - AddDiskWizard wizard = new AddDiskWizard(volume); // Also add single page - - WizardDialog dialog = new WizardDialog(getShell(), wizard); - dialog.create(); - dialog.getShell().setSize(1024, 600); - dialog.open(); - } - }); + // TODO: open a dialog box + // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + + // volume.getName()); + AddDiskWizard wizard = new AddDiskWizard(volume); // Also add single page + + WizardDialog dialog = new WizardDialog(getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(1024, 600); + dialog.open(); } - - /* - * (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); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java index 4d1a87c9..0e6cd6b2 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java @@ -30,8 +30,6 @@ import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.response.GlusterServerResponse; import com.gluster.storage.management.gui.utils.GUIHelper; public class AddServerAction extends AbstractActionDelegate { @@ -52,37 +50,24 @@ public class AddServerAction extends AbstractActionDelegate { String partErrMsg = ""; for (Server server : selectedServers) { guiHelper.setStatusMessage("Adding server [" + server.getName() + "]..."); - + try { glusterServersClient.addServer(server); modelManager.removeDiscoveredServer(server); modelManager.addGlusterServer(glusterServersClient.getGlusterServer(server.getName())); successServers.add(server); - } catch(Exception e) { + } catch (Exception e) { // TODO: Handle error conditions } - -// Status status = response.getStatus(); -// if (status.isSuccess()) { -// modelManager.removeDiscoveredServer(server); -// modelManager.addGlusterServer(response.getGlusterServer()); -// successServers.add(server); -// } else if (status.isPartSuccess()) { -// modelManager.removeDiscoveredServer(server); -// modelManager.addGlusterServer(response.getGlusterServer()); -// partSuccessServers.add(server); -// partErrMsg += "[" + server.getName() + "] : " + status; -// } else { -// errMsg += "[" + server.getName() + "] : " + status; -// } } guiHelper.clearStatusMessage(); - showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, errMsg, partErrMsg); + showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, errMsg, + partErrMsg); } }; - - BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { @Override public void run() { Display.getDefault().asyncExec(addServerThread); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java index f1eb8a94..6fff4f44 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java @@ -2,7 +2,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -15,23 +14,15 @@ public class ClearTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - // TODO Update taskInfo in the model - // modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); - modelManager.removeTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be cleared! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + modelManager.removeTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be cleared! Error: [" + e.getMessage() + "]"); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java index 9655b2b3..d353898c 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java @@ -2,13 +2,14 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; +import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskInfo; import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; public class CommitTaskAction extends AbstractActionDelegate { private TaskInfo taskInfo; @@ -16,23 +17,19 @@ public class CommitTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().commitTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, taskInfo.getName() - + " is commited"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + try { + new TasksClient().commitTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, "Committed"))); + modelManager.removeTask(taskInfo); + Volume volume = (new VolumesClient()).getVolume( taskInfo.getReference()); + modelManager.updateVolumeBricks(getVolume(taskInfo.getReference()), volume.getBricks()); + + showInfoDialog(actionDesc, "Commit successful"); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be Committed! Error: [" + e.getMessage() + "]"); + } } @Override @@ -41,7 +38,7 @@ public class CommitTaskAction extends AbstractActionDelegate { action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canCommit() + action.setEnabled(taskInfo.getCommitSupported() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_COMMIT_PENDING); } } @@ -50,5 +47,14 @@ public class CommitTaskAction extends AbstractActionDelegate { public void dispose() { } + + private Volume getVolume(String volumeName) { + for (Volume volume : modelManager.getModel().getCluster().getVolumes() ) { + if (volume.getName().equals(volumeName)) { + return volume; + } + } + return null; + } } 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 index 1b412617..2cfa0916 100644 --- 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 @@ -33,27 +33,21 @@ import com.gluster.storage.management.gui.dialogs.CreateVolumeWizard; public class CreateVolumeAction extends AbstractActionDelegate { @Override protected void performAction(IAction action) { - Display.getDefault().asyncExec(new Runnable() { - + CreateVolumeWizard wizard = new CreateVolumeWizard(); + + WizardDialog dialog = new WizardDialog(getShell(), wizard) { @Override - public void run() { - CreateVolumeWizard wizard = new CreateVolumeWizard(); - - WizardDialog dialog = new WizardDialog(getShell(), wizard) { - @Override - protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { - Button button = super.createButton(parent, id, label, defaultButton); - if(id == IDialogConstants.FINISH_ID) { - button.setText("&Create"); - } - return button; - } - }; - dialog.create(); - dialog.getShell().setSize(500, 550); - dialog.open(); + protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { + Button button = super.createButton(parent, id, label, defaultButton); + if (id == IDialogConstants.FINISH_ID) { + button.setText("&Create"); + } + return button; } - }); + }; + dialog.create(); + dialog.getShell().setSize(500, 550); + dialog.open(); } @Override 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 index eca8e789..0d61b21f 100644 --- 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 @@ -21,11 +21,9 @@ 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; import com.gluster.storage.management.gui.IImageKeys; @@ -37,66 +35,57 @@ public class DeleteVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - - final String actionDesc = action.getDescription(); + String warningMessage; + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + warningMessage = "Are you sure to delete the Volume[" + volume.getName() + "] ?"; + } else { + warningMessage = "Volume [" + volume.getName() + "] is online, \nAre you sure to continue?"; + } - String warningMessage; - if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { - warningMessage = "Are you sure to delete the Volume[" + volume.getName() + "] ?"; - } else { - warningMessage = "Volume [" + volume.getName() + "] is online, \nAre you sure to continue?"; - } + Integer deleteOption = new MessageDialog(getShell(), "Delete Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), warningMessage, MessageDialog.QUESTION, new String[] { "Cancel", + "Delete volume and data", "Delete volume, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } - Integer deleteOption = new MessageDialog(getShell(), "Delete Volume", GUIHelper.getInstance().getImage( - IImageKeys.VOLUME), warningMessage, MessageDialog.QUESTION, new String[] { "Cancel", - "Delete volume and data", "Delete volume, keep data" }, -1).open(); - if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) - return; - } + VolumesClient client = new VolumesClient(); - VolumesClient client = new VolumesClient(); + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { // To stop the volume service, if running + try { + client.stopVolume(volume.getName()); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); + return; + } + } - Status status; - if (volume.getStatus() == VOLUME_STATUS.ONLINE) { // To stop the volume service, if running - try { - client.stopVolume(volume.getName()); - } catch(Exception e) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() + "] could not be stopped! Error: [" - + e.getMessage() + "]"); - return; - } - } + boolean confirmDelete = false; + if (deleteOption == 1) { + confirmDelete = true; + } - boolean confirmDelete = false; - if (deleteOption == 1) { - confirmDelete = true; - } + try { + client.deleteVolume(volume, confirmDelete); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] deleted successfully!"); + modelManager.deleteVolume(volume); + } catch (Exception e) { + showErrorDialog(actionDesc, e.getMessage()); - try { - client.deleteVolume(volume, confirmDelete); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] deleted successfully!"); - modelManager.deleteVolume(volume); - } catch(Exception e) { - showErrorDialog(actionDesc, e.getMessage()); - - // there is a possibility that the error was in post-delete operation, which means - // volume was deleted, but some other error happened. check if this is the case, - // and if so, update the model manager - if(client.volumeExists(volume.getName())) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() + "] could not be deleted! Error: [" - + e.getMessage() + "]"); - } else { - modelManager.deleteVolume(volume); - showWarningDialog(actionDesc, "Volume deleted, but following error(s) occured: " + e.getMessage()); - } - } + // there is a possibility that the error was in post-delete operation, which means + // volume was deleted, but some other error happened. check if this is the case, + // and if so, update the model manager + if (client.volumeExists(volume.getName())) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be deleted! Error: [" + e.getMessage() + "]"); + } else { + modelManager.deleteVolume(volume); + showWarningDialog(actionDesc, "Volume deleted, but following error(s) occured: " + e.getMessage()); } - }); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java index d7f68646..226e4d00 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java @@ -34,20 +34,13 @@ import com.gluster.storage.management.gui.utils.GUIHelper; public class DownloadVolumeLogsAction extends AbstractActionDelegate { private GUIHelper guiHelper = GUIHelper.getInstance(); - /* (non-Javadoc) - * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() - */ @Override public void dispose() { } - /* (non-Javadoc) - * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) - */ @Override protected void performAction(IAction action) { final VolumesClient client = new VolumesClient(); - final Runnable downloadLogsThread = new Runnable() { @Override 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 index 56ea8179..2512a188 100644 --- 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 @@ -61,7 +61,5 @@ public class MigrateDiskAction extends AbstractActionDelegate { @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/PauseTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java index b36b7855..e3a4b835 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java @@ -22,7 +22,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -37,33 +36,25 @@ public class PauseTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); + final String actionDesc = action.getDescription(); - try { - new TasksClient().pauseTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, taskInfo.getName() - + " is Paused"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Paused! Error: [" + e.getMessage() + "]"); - } - } - }); + try { + new TasksClient().pauseTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, "Paused"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Paused! Error: [" + e.getMessage() + "]"); + } } - - + @Override public void selectionChanged(IAction action, ISelection selection) { super.selectionChanged(action, selection); action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canPause() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING); + action.setEnabled(taskInfo.getPauseSupported() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING); } } 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 index 33ca0e5b..a203dfb4 100644 --- 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 @@ -20,7 +20,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.widgets.Display; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Volume; @@ -30,22 +29,15 @@ public class RebalanceVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + try { + new VolumesClient().rebalanceStart(volume.getName(), false, false, false); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] rebalance started successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume rebalance could not be started on [" + volume.getName() + "]! Error: [" + + e.getMessage() + "]"); + } - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - try { - new VolumesClient().rebalanceStart(volume.getName(), false, false, false); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] rebalance started successfully!"); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Volume rebalance could not be started on [" + volume.getName() + "]! Error: [" + e.getMessage() + "]"); - } - - } - }); } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java index b79a4ee4..d4c5a54a 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java @@ -1,14 +1,12 @@ package com.gluster.storage.management.gui.actions; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPart; @@ -16,8 +14,6 @@ import org.eclipse.ui.IWorkbenchPart; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.utils.StringUtil; import com.gluster.storage.management.gui.IImageKeys; @@ -33,48 +29,38 @@ public class RemoveDiskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { + final String actionDesc = action.getDescription(); + List brickList = getBrickList(bricks); + Integer deleteOption = new MessageDialog(getShell(), "Remove Bricks(s)", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), "Are you sure you want to remove following bricks from volume [" + volume.getName() + + "] ? \n" + StringUtil.collectionToString(brickList, ", "), MessageDialog.QUESTION, new String[] { + "Cancel", "Remove bricks, delete data", "Remove bricks, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } - @Override + if (deleteOption == 1) { + confirmDelete = true; + } + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { public void run() { + VolumesClient client = new VolumesClient(); + try { + client.removeBricks(volume.getName(), bricks, confirmDelete); + // Remove the bricks from the volume object + for (Brick brick : bricks) { + volume.removeBrick(brick); + } + // Update model with removed bricks in the volume + modelManager.removeBricks(volume, bricks); - final String actionDesc = action.getDescription(); - List brickList = getBrickList(bricks); - Integer deleteOption = new MessageDialog(getShell(), "Remove Bricks(s)", GUIHelper.getInstance() - .getImage(IImageKeys.VOLUME), "Are you sure you want to remove following bricks from volume [" - + volume.getName() + "] ? \n" + StringUtil.collectionToString(brickList, ", "), - MessageDialog.QUESTION, new String[] { "Cancel", "Remove bricks, delete data", - "Remove bricks, keep data" }, -1).open(); - if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) - return; - } - - if (deleteOption == 1) { - confirmDelete = true; + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] bricks(s) removed successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume [" + volume.getName() + + "] bricks(s) could not be removed! Error: [" + e.getMessage() + "]"); } - BusyIndicator.showWhile(Display.getDefault(), new Runnable() { - public void run() { - VolumesClient client = new VolumesClient(); - try { - client.removeBricks(volume.getName(), bricks, confirmDelete); - // Remove the bricks from the volume object - for (Brick brick : bricks) { - volume.removeBrick(brick); - } - // Update model with removed bricks in the volume - modelManager.removeBricks(volume, bricks); - - showInfoDialog(actionDesc, "Volume [" + volume.getName() - + "] bricks(s) removed successfully!"); - } catch (Exception e) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() - + "] bricks(s) could not be removed! Error: [" + e.getMessage() + "]"); - } - } - }); } }); - } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java index 911c57a8..4862b7b1 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java @@ -29,16 +29,12 @@ import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.PlatformUI; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.gui.utils.GUIHelper; -import com.gluster.storage.management.gui.views.NavigationView; public class RemoveServerAction extends AbstractActionDelegate { private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java index fc80b04d..d8f1b955 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java @@ -2,7 +2,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -16,23 +15,16 @@ public class ResumeTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, taskInfo.getName() - + " is Resumed"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Resumed! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, "Resumed"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Resumed! Error: [" + e.getMessage() + "]"); + } } @Override @@ -47,9 +39,7 @@ public class ResumeTaskAction extends AbstractActionDelegate { @Override public void dispose() { - } - } 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 index c259c661..322a87f9 100644 --- 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 @@ -53,13 +53,6 @@ public class StartVolumeAction extends AbstractActionDelegate { } - /* - * (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); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java index abde4e57..12d14b43 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java @@ -16,22 +16,16 @@ public class StopTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - taskInfo.setStatus( new TaskStatus( new Status(Status.STATUS_CODE_SUCCESS, taskInfo.getName() + " is Stopped"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, "Stopped"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); + } } @Override @@ -40,7 +34,7 @@ public class StopTaskAction extends AbstractActionDelegate { action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canStop() + action.setEnabled(taskInfo.getStopSupported() && (taskInfo.getStatus().getCode() == Status.STATUS_CODE_PAUSE || taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING)); } 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 index d4e3d363..62c690e2 100644 --- 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 @@ -21,7 +21,6 @@ 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; @@ -36,34 +35,28 @@ public class StopVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { - showWarningDialog(actionDesc, "Volume [" + volume.getName() + "] is already offline!"); - return; // Volume already offline. Don't do anything. - } + final String actionDesc = action.getDescription(); + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + showWarningDialog(actionDesc, "Volume [" + volume.getName() + "] is already offline!"); + return; // Volume already offline. Don't do anything. + } - Integer deleteOption = new MessageDialog(getShell(), "Stop Volume", GUIHelper.getInstance().getImage( - IImageKeys.VOLUME), "Are you sure you want to stop the volume [" + volume.getName() + "] ?", - MessageDialog.QUESTION, new String[] { "No", "Yes" }, -1).open(); + Integer deleteOption = new MessageDialog(getShell(), "Stop Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), "Are you sure you want to stop the volume [" + volume.getName() + "] ?", + MessageDialog.QUESTION, new String[] { "No", "Yes" }, -1).open(); - if (deleteOption <= 0) { - return; - } + if (deleteOption <= 0) { + return; + } - try { - new VolumesClient().stopVolume(volume.getName()); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] stopped successfully!"); - modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + try { + new VolumesClient().stopVolume(volume.getName()); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] stopped successfully!"); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java index ce68e22f..8d48af76 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java @@ -32,7 +32,10 @@ import org.eclipse.ui.IWorkbenchSite; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; import com.gluster.storage.management.gui.TasksTableLabelProvider; public class TasksPage extends AbstractTableViewerPage { @@ -45,10 +48,9 @@ public class TasksPage extends AbstractTableViewerPage { private static final String[] TASK_TABLE_COLUMN_NAMES = new String[] { "Task", "Status"}; - @SuppressWarnings("unchecked") - public TasksPage(IWorkbenchSite site, Composite parent, int style, Object taskInfo) { + public TasksPage(IWorkbenchSite site, Composite parent, int style, List taskInfo) { super(site, parent, style, false, false, taskInfo); - this.taskInfoList = (List) taskInfo; + this.taskInfoList = taskInfo; } /* (non-Javadoc) @@ -67,10 +69,26 @@ public class TasksPage extends AbstractTableViewerPage { refreshViewer(); } + @Override + public void taskUpdated(TaskInfo taskInfo) { + refreshViewer(); + } + private void refreshViewer() { tableViewer.refresh(); parent.update(); } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + if (event.getEventType() == EVENT_TYPE.BRICK_REPLACED) { + if (!tableViewer.getControl().isDisposed()) { + tableViewer.refresh(); + } + } + } + }; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java index 9bdc9c94..88de96da 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java @@ -122,7 +122,7 @@ public class MigrateDiskTask extends Task { ProcessResult processResult = sshUtil.executeRemote(onlineServer, command); TaskStatus taskStatus = new TaskStatus(); if (processResult.isSuccess()) { - if (processResult.getOutput().matches("*pause")) { //TODO replace correct pattern to identify the pause status + if (processResult.getOutput().trim().matches(".*paused successfully$")) { //TODO replace correct pattern to identify the pause status taskStatus.setCode(Status.STATUS_CODE_PAUSE); taskStatus.setMessage(processResult.getOutput()); getTaskInfo().setStatus(taskStatus); @@ -172,8 +172,8 @@ public class MigrateDiskTask extends Task { taskStatus.setMessage(processResult.getOutput()); getTaskInfo().setStatus(taskStatus); return; - } - } + } + } // if we reach here, it means rebalance start failed. throw new GlusterRuntimeException(processResult.toString()); @@ -212,8 +212,14 @@ public class MigrateDiskTask extends Task { private TaskStatus checkMigrationStatus(String serverName) { + // TODO: If the task is already paused return the same status till FS gives correct status + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE ) { + return getTaskInfo().getStatus(); + } + String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " status"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); TaskStatus taskStatus = new TaskStatus(); if (processResult.isSuccess()) { @@ -221,8 +227,13 @@ public class MigrateDiskTask extends Task { taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); if (autoCommit) { commitMigration(serverName); + return getTaskInfo().getStatus(); // return the committed status + } else { + taskStatus.setMessage(processResult.getOutput().trim() + .replaceAll("Migration complete", "Commit pending")); } - } else if ( processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { + return taskStatus; + } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { taskStatus.setCode(Status.STATUS_CODE_RUNNING); } else { taskStatus.setCode(Status.STATUS_CODE_FAILURE); @@ -230,7 +241,6 @@ public class MigrateDiskTask extends Task { } else { taskStatus.setCode(Status.STATUS_CODE_FAILURE); } - taskStatus.setMessage(processResult.getOutput()); // common taskInfo.setStatus(taskStatus); // Update the task status return taskStatus; diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java index 49cd0b8b..4fa6e08c 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java @@ -38,9 +38,9 @@ public abstract class Task { taskInfo.setType(type); taskInfo.setReference(reference); taskInfo.setDescription(desc); - taskInfo.setCanPause(canPause); - taskInfo.setCanStop(canStop); - taskInfo.setCanCommit(canCommit); + taskInfo.setPauseSupported(canPause); + taskInfo.setStopSupported(canStop); + taskInfo.setCommitSupported(canCommit); init(clusterService, clusterName, taskInfo); -- cgit From 0b60788162f3920df3b62f39088334f0ce90ee41 Mon Sep 17 00:00:00 2001 From: Dhandapani Date: Fri, 1 Jul 2011 16:36:04 +0530 Subject: Volume Rebalance functionality enhancement --- .../server/resources/GlusterServersResource.java | 12 ++++--- .../server/tasks/InitializeDiskTask.java | 37 ++++++++++++---------- .../server/tasks/RebalanceVolumeTask.java | 36 ++++++--------------- .../management/server/utils/GlusterUtil.java | 12 +++++++ 4 files changed, 49 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java index e3bfe158..1f4b15de 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java @@ -415,11 +415,15 @@ public class GlusterServersResource extends AbstractServersResource { } InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName); - initializeTask.start(); - taskResource.addTask(initializeTask); + try { + initializeTask.start(); + taskResource.addTask(initializeTask); - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + initializeTask.getId()); + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } } private void setGlusterUtil(GlusterUtil glusterUtil) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java index 40d7877e..4592b759 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java @@ -55,22 +55,29 @@ public class InitializeDiskTask extends Task { @Override public String getId() { - return new String(Base64.encode(taskInfo.getType() + "-" + serverName + ":" + diskName)); + return new String( + Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); } @Override public void resume() { - getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not resume disk initialization"))); + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); } @Override public void stop() { - getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not stop disk initialization"))); + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); } @Override public void pause() { - getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not suspend disk initialization"))); + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); } @Override @@ -91,24 +98,20 @@ public class InitializeDiskTask extends Task { @Override public void start() { try { - startInitializeDisk(getOnlineServer().getName()); + startInitializeDisk(serverName); } catch(ConnectionException e) { - // online server might have gone offline. try with a new one - startInitializeDisk(getNewOnlineServer().getName()); + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); } } private void startInitializeDisk(String serverName) { ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_SCRIPT + " " + getDiskName()); if (processResult.isSuccess()) { - // TODO: Message needs to change according to the script return - if (processResult.getOutput().trim().matches(".*has been successful$")) { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); - return; - } + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + return; } - + // if we reach here, it means Initialize disk start failed. throw new GlusterRuntimeException(processResult.toString()); @@ -118,10 +121,10 @@ public class InitializeDiskTask extends Task { public TaskStatus checkStatus() { try { - return glusterUtil.checkInitializeDiskStatus(getOnlineServer().getName(), getDiskName()); + return glusterUtil.checkInitializeDiskStatus(serverName, getDiskName()); } catch(ConnectionException e) { - // online server might have gone offline. try with a new one - return glusterUtil.checkInitializeDiskStatus(getNewOnlineServer().getName(), getDiskName()); + // online server might have gone offline. update the failure status + return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java index 33655b3f..f94613e0 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java @@ -44,13 +44,13 @@ public class RebalanceVolumeTask extends Task { } public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName) { - super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume rebalance running on " - + volumeName, false, true, false); + super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName + + " Rebalance", false, true, false); } @Override public String getId() { - return new String(Base64.encode(taskInfo.getType() + "-" + taskInfo.getReference())); + return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); } @Override @@ -69,13 +69,10 @@ public class RebalanceVolumeTask extends Task { String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; ProcessResult processResult = sshUtil.executeRemote(serverName, command); if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*has been successful$")) { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); - return; - } + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + return; } - + // if we reach here, it means rebalance start failed. throw new GlusterRuntimeException(processResult.toString()); } @@ -90,33 +87,18 @@ public class RebalanceVolumeTask extends Task { @Override public void stop() { try { - stopRebalance(serverName); + glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); } catch (ConnectionException e) { // online server might have gone offline. update the failure status getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); } } - private void stopRebalance(String serverName) { - String command = "gluster volume rebalance " + getTaskInfo().getReference() + " stop"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*has been successful$")) { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, processResult.getOutput()))); - return; - } - } - - // if we reach here, it means rebalance stop failed. - throw new GlusterRuntimeException(processResult.toString()); - } - @Override public void pause() { getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, "Pause/Resume is not supported in Volume Rebalance"))); + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); } @Override diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index a09c7956..1dc5eb1a 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -573,6 +573,16 @@ public class GlusterUtil { return taskStatus; } + public void stopRebalance(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " stop"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + } + } + public TaskStatus checkInitializeDiskStatus(String serverName, String diskName) { ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + diskName); TaskStatus taskStatus = new TaskStatus(); @@ -581,7 +591,9 @@ public class GlusterUtil { if (processResult.getOutput().trim().matches(".*Initailize completed$")) { taskStatus.setCode(Status.STATUS_CODE_SUCCESS); } else { + // TODO: Percentage completed needs to be set, according to the script output taskStatus.setCode(Status.STATUS_CODE_RUNNING); + // taskStatus.setPercentCompleted(processResult.getOutput()); } } else { taskStatus.setCode(Status.STATUS_CODE_FAILURE); -- cgit From 342312744669f57cf88eea6e9e6b4e6a2b755d50 Mon Sep 17 00:00:00 2001 From: Dhandapani Date: Mon, 4 Jul 2011 18:53:18 +0530 Subject: Wrong method name issue fix in create volume --- .../gluster/storage/management/server/resources/VolumesResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java index 4318945c..1f645b4f 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -208,7 +208,7 @@ public class VolumesResource extends AbstractResource { } try { - createVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, + performCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); return createdResponse(volumeName); } catch (Exception e) { -- cgit From 45ca89a241e826d80802d9e3e93d28f8cd026316 Mon Sep 17 00:00:00 2001 From: Selvasundaram Date: Fri, 1 Jul 2011 19:01:12 +0530 Subject: Task updates in UI --- .../management/client/GlusterDataModelManager.java | 19 +- .../storage/management/core/model/Cluster.java | 16 +- .../storage/management/core/model/Event.java | 1 + .../storage/management/core/model/TaskInfo.java | 16 +- .../core/response/TaskInfoListResponse.java | 3 +- src/com.gluster.storage.management.gui/plugin.xml | 10 +- .../gui/actions/AbstractActionDelegate.java | 6 +- .../management/gui/actions/AddBrickAction.java | 64 +++++ .../management/gui/actions/AddDiskAction.java | 84 ------- .../management/gui/actions/AddServerAction.java | 27 +- .../management/gui/actions/ClearTaskAction.java | 27 +- .../management/gui/actions/CommitTaskAction.java | 37 ++- .../management/gui/actions/CreateVolumeAction.java | 32 +-- .../management/gui/actions/DeleteVolumeAction.java | 97 ++++---- .../gui/actions/DownloadVolumeLogsAction.java | 7 - .../management/gui/actions/MigrateBrickAction.java | 65 +++++ .../management/gui/actions/MigrateDiskAction.java | 67 ----- .../management/gui/actions/PauseTaskAction.java | 31 +-- .../gui/actions/RebalanceVolumeAction.java | 24 +- .../management/gui/actions/RemoveBrickAction.java | 94 +++++++ .../management/gui/actions/RemoveDiskAction.java | 108 -------- .../management/gui/actions/RemoveServerAction.java | 4 - .../management/gui/actions/ResumeTaskAction.java | 30 +-- .../management/gui/actions/StartVolumeAction.java | 7 - .../management/gui/actions/StopTaskAction.java | 28 +-- .../management/gui/actions/StopVolumeAction.java | 45 ++-- .../management/gui/dialogs/AddBrickPage.java | 170 +++++++++++++ .../management/gui/dialogs/AddBrickWizard.java | 102 ++++++++ .../management/gui/dialogs/AddDiskPage.java | 170 ------------- .../management/gui/dialogs/AddDiskWizard.java | 102 -------- .../management/gui/dialogs/MigrateBrickPage1.java | 276 +++++++++++++++++++++ .../management/gui/dialogs/MigrateBrickWizard.java | 74 ++++++ .../management/gui/dialogs/MigrateDiskPage1.java | 273 -------------------- .../management/gui/dialogs/MigrateDiskWizard.java | 74 ------ .../management/gui/views/pages/TasksPage.java | 24 +- .../server/resources/VolumesResource.java | 4 +- .../management/server/tasks/MigrateBrickTask.java | 224 +++++++++++++++++ .../management/server/tasks/MigrateDiskTask.java | 238 ------------------ .../storage/management/server/tasks/Task.java | 6 +- .../management/server/utils/GlusterUtil.java | 33 +-- 40 files changed, 1299 insertions(+), 1420 deletions(-) create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddBrickAction.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateBrickAction.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickPage1.java create mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickWizard.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java delete mode 100644 src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java (limited to 'src') diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index be7a9023..a1c7823a 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -162,8 +162,8 @@ public class GlusterDataModelManager { } public void initializeTasks(Cluster cluster) { - // List taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); - List taskInfoList = getDummyTasks(); + List taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); + // List taskInfoList = getDummyTasks(); cluster.setTaskInfoList(taskInfoList); } @@ -174,8 +174,8 @@ public class GlusterDataModelManager { TaskInfo taskInfo = new TaskInfo(); taskInfo.setType(TASK_TYPE.BRICK_MIGRATE); taskInfo.setName("Migrate Brick-music"); - taskInfo.setCanPause(true); - taskInfo.setCanStop(true); + taskInfo.setPauseSupported(true); + taskInfo.setStopSupported(true); taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, ""))); taskInfo.getStatus().setMessage("Migrating file xxxxx to yyyy"); @@ -185,8 +185,8 @@ public class GlusterDataModelManager { taskInfo = new TaskInfo(); taskInfo.setType(TASK_TYPE.DISK_FORMAT); taskInfo.setName("Format Disk-server1:sdc"); - taskInfo.setCanPause(false); - taskInfo.setCanStop(false); + taskInfo.setPauseSupported(false); + taskInfo.setStopSupported(false); taskInfo.setStatus( new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, ""))); taskInfo.getStatus().setMessage("Format completes 80% ..."); taskInfo.setDescription("Formatting disk server1:sdc."); @@ -407,6 +407,13 @@ public class GlusterDataModelManager { listener.volumeCreated(volume); } } + + public void updateVolumeBricks(Volume volume, List bricks) { + model.getCluster().updateVolume( volume.getName(), bricks ); + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICK_REPLACED , bricks)); + } + } public void addTask(TaskInfo taskInfo) { Cluster cluster = model.getCluster(); 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 index d6757cba..33343726 100644 --- 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 @@ -55,7 +55,7 @@ public class Cluster extends Entity { } public void deleteVolume(Volume volume) { - volumes.remove(volume); + volumes.remove(volume); } public void setServers(List servers) { @@ -93,6 +93,11 @@ public class Cluster extends Entity { public void addVolume(Volume volume) { this.volumes.add(volume); } + + public void updateVolume(String volumeName, List bricks) { + Volume volume = getVolume(volumeName); + volume.setBricks(bricks); + } public Cluster(String name, Entity parent) { super(name, parent); @@ -156,4 +161,13 @@ public class Cluster extends Entity { } return null; } + + public Volume getVolume(String volumeName) { + for (Volume volume : getVolumes() ) { + if (volume.getName().equals(volumeName)) { + return volume; + } + } + return null; + } } \ No newline at end of file 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 index 99594b5d..1e172d1c 100644 --- 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 @@ -22,6 +22,7 @@ public class Event { public enum EVENT_TYPE { BRICKS_ADDED, BRICKS_REMOVED, + BRICK_REPLACED, NETWORK_INTERFACE_ADDED, NETWORK_INTERFACE_REMOVED, VOLUME_STATUS_CHANGED, diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java index 1ce2fa04..d3267ec4 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/TaskInfo.java @@ -78,28 +78,28 @@ public class TaskInfo extends Entity { public void setStatus(TaskStatus status) { this.status = status; } - - public Boolean canPause() { + + public Boolean getPauseSupported() { return pauseSupported; } - public void setCanPause(Boolean canPause) { + public void setPauseSupported(Boolean canPause) { this.pauseSupported = canPause; } - public Boolean canStop() { + public Boolean getStopSupported() { return stopSupported; } - - public void setCanStop(Boolean canStop) { + + public void setStopSupported(Boolean canStop) { this.stopSupported = canStop; } - public Boolean canCommit() { + public Boolean getCommitSupported() { return this.commitSupported; } - public void setCanCommit(Boolean canCommit) { + public void setCommitSupported(Boolean canCommit) { this.commitSupported = canCommit; } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java index 0ab27c35..ba1c4f9f 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java @@ -20,6 +20,7 @@ */ package com.gluster.storage.management.core.response; +import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; @@ -29,7 +30,7 @@ import com.gluster.storage.management.core.model.TaskInfo; @XmlRootElement(name = "tasks") public class TaskInfoListResponse { - private List taskInfoList; + private List taskInfoList = new ArrayList(); public TaskInfoListResponse() { diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index 5b18421f..b0dfa9a9 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -476,7 +476,7 @@ visible="false"> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ + +package com.gluster.storage.management.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.AddBrickWizard; + +public class AddBrickAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + public void dispose() { + window = null; + } + + @Override + protected void performAction(IAction action) { + // TODO: open a dialog box + // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + + // volume.getName()); + AddBrickWizard wizard = new AddBrickWizard(volume); // Also add single page + + WizardDialog dialog = new WizardDialog(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) { + this.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/AddDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java deleted file mode 100644 index cc57c541..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * AddDiskAction.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ - -package com.gluster.storage.management.gui.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.client.GlusterDataModelManager; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.gui.dialogs.AddDiskWizard; - -public class AddDiskAction extends AbstractActionDelegate { - private Volume volume; - private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); - - /* (non-Javadoc) - * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() - */ - @Override - public void dispose() { - window = null; - } - - /* (non-Javadoc) - * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) - */ - @Override - protected void performAction(IAction action) { - //TODO: open a dialog box - // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + volume.getName()); - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - AddDiskWizard wizard = new AddDiskWizard(volume); // Also add single page - - WizardDialog dialog = new WizardDialog(getShell(), wizard); - dialog.create(); - dialog.getShell().setSize(1024, 600); - dialog.open(); - } - }); - } - - - /* - * (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) { - this.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/AddServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java index 4d1a87c9..0e6cd6b2 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddServerAction.java @@ -30,8 +30,6 @@ import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.response.GlusterServerResponse; import com.gluster.storage.management.gui.utils.GUIHelper; public class AddServerAction extends AbstractActionDelegate { @@ -52,37 +50,24 @@ public class AddServerAction extends AbstractActionDelegate { String partErrMsg = ""; for (Server server : selectedServers) { guiHelper.setStatusMessage("Adding server [" + server.getName() + "]..."); - + try { glusterServersClient.addServer(server); modelManager.removeDiscoveredServer(server); modelManager.addGlusterServer(glusterServersClient.getGlusterServer(server.getName())); successServers.add(server); - } catch(Exception e) { + } catch (Exception e) { // TODO: Handle error conditions } - -// Status status = response.getStatus(); -// if (status.isSuccess()) { -// modelManager.removeDiscoveredServer(server); -// modelManager.addGlusterServer(response.getGlusterServer()); -// successServers.add(server); -// } else if (status.isPartSuccess()) { -// modelManager.removeDiscoveredServer(server); -// modelManager.addGlusterServer(response.getGlusterServer()); -// partSuccessServers.add(server); -// partErrMsg += "[" + server.getName() + "] : " + status; -// } else { -// errMsg += "[" + server.getName() + "] : " + status; -// } } guiHelper.clearStatusMessage(); - showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, errMsg, partErrMsg); + showStatusMessage(action.getDescription(), selectedServers, successServers, partSuccessServers, errMsg, + partErrMsg); } }; - - BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { @Override public void run() { Display.getDefault().asyncExec(addServerThread); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java index f1eb8a94..6fff4f44 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java @@ -2,7 +2,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -15,23 +14,15 @@ public class ClearTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - // TODO Update taskInfo in the model - // modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); - modelManager.removeTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be cleared! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + modelManager.removeTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be cleared! Error: [" + e.getMessage() + "]"); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java index 9655b2b3..86e3032e 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/CommitTaskAction.java @@ -2,13 +2,14 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; +import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskInfo; import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; public class CommitTaskAction extends AbstractActionDelegate { private TaskInfo taskInfo; @@ -16,23 +17,20 @@ public class CommitTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().commitTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, taskInfo.getName() - + " is commited"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + try { + new TasksClient().commitTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, "Committed"))); + modelManager.removeTask(taskInfo); + Volume volume = (new VolumesClient()).getVolume(taskInfo.getReference()); + modelManager.updateVolumeBricks(modelManager.getModel().getCluster().getVolume(taskInfo.getReference()), + volume.getBricks()); + + showInfoDialog(actionDesc, "Commit successful"); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be Committed! Error: [" + e.getMessage() + "]"); + } } @Override @@ -41,7 +39,7 @@ public class CommitTaskAction extends AbstractActionDelegate { action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canCommit() + action.setEnabled(taskInfo.getCommitSupported() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_COMMIT_PENDING); } } @@ -50,5 +48,4 @@ public class CommitTaskAction extends AbstractActionDelegate { public void dispose() { } - } 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 index 1b412617..2cfa0916 100644 --- 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 @@ -33,27 +33,21 @@ import com.gluster.storage.management.gui.dialogs.CreateVolumeWizard; public class CreateVolumeAction extends AbstractActionDelegate { @Override protected void performAction(IAction action) { - Display.getDefault().asyncExec(new Runnable() { - + CreateVolumeWizard wizard = new CreateVolumeWizard(); + + WizardDialog dialog = new WizardDialog(getShell(), wizard) { @Override - public void run() { - CreateVolumeWizard wizard = new CreateVolumeWizard(); - - WizardDialog dialog = new WizardDialog(getShell(), wizard) { - @Override - protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { - Button button = super.createButton(parent, id, label, defaultButton); - if(id == IDialogConstants.FINISH_ID) { - button.setText("&Create"); - } - return button; - } - }; - dialog.create(); - dialog.getShell().setSize(500, 550); - dialog.open(); + protected Button createButton(Composite parent, int id, String label, boolean defaultButton) { + Button button = super.createButton(parent, id, label, defaultButton); + if (id == IDialogConstants.FINISH_ID) { + button.setText("&Create"); + } + return button; } - }); + }; + dialog.create(); + dialog.getShell().setSize(500, 550); + dialog.open(); } @Override 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 index eca8e789..0d61b21f 100644 --- 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 @@ -21,11 +21,9 @@ 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; import com.gluster.storage.management.gui.IImageKeys; @@ -37,66 +35,57 @@ public class DeleteVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - - final String actionDesc = action.getDescription(); + String warningMessage; + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + warningMessage = "Are you sure to delete the Volume[" + volume.getName() + "] ?"; + } else { + warningMessage = "Volume [" + volume.getName() + "] is online, \nAre you sure to continue?"; + } - String warningMessage; - if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { - warningMessage = "Are you sure to delete the Volume[" + volume.getName() + "] ?"; - } else { - warningMessage = "Volume [" + volume.getName() + "] is online, \nAre you sure to continue?"; - } + Integer deleteOption = new MessageDialog(getShell(), "Delete Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), warningMessage, MessageDialog.QUESTION, new String[] { "Cancel", + "Delete volume and data", "Delete volume, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } - Integer deleteOption = new MessageDialog(getShell(), "Delete Volume", GUIHelper.getInstance().getImage( - IImageKeys.VOLUME), warningMessage, MessageDialog.QUESTION, new String[] { "Cancel", - "Delete volume and data", "Delete volume, keep data" }, -1).open(); - if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) - return; - } + VolumesClient client = new VolumesClient(); - VolumesClient client = new VolumesClient(); + if (volume.getStatus() == VOLUME_STATUS.ONLINE) { // To stop the volume service, if running + try { + client.stopVolume(volume.getName()); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); + return; + } + } - Status status; - if (volume.getStatus() == VOLUME_STATUS.ONLINE) { // To stop the volume service, if running - try { - client.stopVolume(volume.getName()); - } catch(Exception e) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() + "] could not be stopped! Error: [" - + e.getMessage() + "]"); - return; - } - } + boolean confirmDelete = false; + if (deleteOption == 1) { + confirmDelete = true; + } - boolean confirmDelete = false; - if (deleteOption == 1) { - confirmDelete = true; - } + try { + client.deleteVolume(volume, confirmDelete); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] deleted successfully!"); + modelManager.deleteVolume(volume); + } catch (Exception e) { + showErrorDialog(actionDesc, e.getMessage()); - try { - client.deleteVolume(volume, confirmDelete); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] deleted successfully!"); - modelManager.deleteVolume(volume); - } catch(Exception e) { - showErrorDialog(actionDesc, e.getMessage()); - - // there is a possibility that the error was in post-delete operation, which means - // volume was deleted, but some other error happened. check if this is the case, - // and if so, update the model manager - if(client.volumeExists(volume.getName())) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() + "] could not be deleted! Error: [" - + e.getMessage() + "]"); - } else { - modelManager.deleteVolume(volume); - showWarningDialog(actionDesc, "Volume deleted, but following error(s) occured: " + e.getMessage()); - } - } + // there is a possibility that the error was in post-delete operation, which means + // volume was deleted, but some other error happened. check if this is the case, + // and if so, update the model manager + if (client.volumeExists(volume.getName())) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be deleted! Error: [" + e.getMessage() + "]"); + } else { + modelManager.deleteVolume(volume); + showWarningDialog(actionDesc, "Volume deleted, but following error(s) occured: " + e.getMessage()); } - }); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java index d7f68646..226e4d00 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/DownloadVolumeLogsAction.java @@ -34,20 +34,13 @@ import com.gluster.storage.management.gui.utils.GUIHelper; public class DownloadVolumeLogsAction extends AbstractActionDelegate { private GUIHelper guiHelper = GUIHelper.getInstance(); - /* (non-Javadoc) - * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() - */ @Override public void dispose() { } - /* (non-Javadoc) - * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) - */ @Override protected void performAction(IAction action) { final VolumesClient client = new VolumesClient(); - final Runnable downloadLogsThread = new Runnable() { @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateBrickAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateBrickAction.java new file mode 100644 index 00000000..41770d98 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateBrickAction.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.gui.actions; + +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; + +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.MigrateBrickWizard; +import com.gluster.storage.management.gui.utils.GUIHelper; + +public class MigrateBrickAction extends AbstractActionDelegate { + private Volume volume; + private Brick brick; + + @Override + protected void performAction(IAction action) { + MigrateBrickWizard wizard = new MigrateBrickWizard(volume, brick); + + 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); + Set bricks; + if (selectedEntity instanceof Volume) { + volume = (Volume) selectedEntity; + } + + action.setEnabled(false); + if (selectedEntity instanceof Brick) { + bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); + brick = (Brick) bricks.iterator().next(); + action.setEnabled(brick != null); + } + } + + @Override + public void dispose() { + } +} 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 deleted file mode 100644 index 56ea8179..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/MigrateDiskAction.java +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.gui.actions; - -import java.util.Set; - -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.wizard.WizardDialog; - -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.gui.dialogs.MigrateDiskWizard; -import com.gluster.storage.management.gui.utils.GUIHelper; - -public class MigrateDiskAction extends AbstractActionDelegate { - private Volume volume; - private Brick brick; - - @Override - protected void performAction(IAction action) { - MigrateDiskWizard wizard = new MigrateDiskWizard(volume, brick); - - 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); - Set bricks; - if (selectedEntity instanceof Volume) { - volume = (Volume) selectedEntity; - } - - action.setEnabled(false); - if (selectedEntity instanceof Brick) { - bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); - brick = (Brick) bricks.iterator().next(); - action.setEnabled(brick != null); - } - } - - @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/PauseTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java index b36b7855..e3a4b835 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java @@ -22,7 +22,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -37,33 +36,25 @@ public class PauseTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); + final String actionDesc = action.getDescription(); - try { - new TasksClient().pauseTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, taskInfo.getName() - + " is Paused"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Paused! Error: [" + e.getMessage() + "]"); - } - } - }); + try { + new TasksClient().pauseTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_PAUSE, "Paused"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Paused! Error: [" + e.getMessage() + "]"); + } } - - + @Override public void selectionChanged(IAction action, ISelection selection) { super.selectionChanged(action, selection); action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canPause() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING); + action.setEnabled(taskInfo.getPauseSupported() && taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING); } } 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 index 33ca0e5b..a203dfb4 100644 --- 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 @@ -20,7 +20,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.widgets.Display; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Volume; @@ -30,22 +29,15 @@ public class RebalanceVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + try { + new VolumesClient().rebalanceStart(volume.getName(), false, false, false); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] rebalance started successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume rebalance could not be started on [" + volume.getName() + "]! Error: [" + + e.getMessage() + "]"); + } - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - try { - new VolumesClient().rebalanceStart(volume.getName(), false, false, false); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] rebalance started successfully!"); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Volume rebalance could not be started on [" + volume.getName() + "]! Error: [" + e.getMessage() + "]"); - } - - } - }); } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java new file mode 100644 index 00000000..0f411a59 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java @@ -0,0 +1,94 @@ +package com.gluster.storage.management.gui.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.StringUtil; +import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.VolumeBricksView; + +public class RemoveBrickAction extends AbstractActionDelegate { + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + private GUIHelper guiHelper = GUIHelper.getInstance(); + private Set bricks; + private Volume volume; + boolean confirmDelete = false; + + @Override + protected void performAction(final IAction action) { + final String actionDesc = action.getDescription(); + List brickList = getBrickList(bricks); + Integer deleteOption = new MessageDialog(getShell(), "Remove Bricks(s)", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), "Are you sure you want to remove following bricks from volume [" + volume.getName() + + "] ? \n" + StringUtil.collectionToString(brickList, ", "), MessageDialog.QUESTION, new String[] { + "Cancel", "Remove bricks, delete data", "Remove bricks, keep data" }, -1).open(); + if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) + return; + } + + if (deleteOption == 1) { + confirmDelete = true; + } + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + public void run() { + VolumesClient client = new VolumesClient(); + try { + client.removeBricks(volume.getName(), bricks, confirmDelete); + // Remove the bricks from the volume object + for (Brick brick : bricks) { + volume.removeBrick(brick); + } + // Update model with removed bricks in the volume + modelManager.removeBricks(volume, bricks); + + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] bricks(s) removed successfully!"); + } catch (Exception e) { + showErrorDialog(actionDesc, "Volume [" + volume.getName() + + "] bricks(s) could not be removed! Error: [" + e.getMessage() + "]"); + } + } + }); + } + + @Override + public void dispose() { + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + action.setEnabled(false); + volume = (Volume) guiHelper.getSelectedEntity(window, Volume.class); + if (volume != null) { + // a volume is selected on navigation tree. Let's check if the currently open view is volume disks view + IWorkbenchPart view = guiHelper.getActiveView(); + if (view instanceof VolumeBricksView) { + // volume disks view is open. check if any brick is selected + bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); + action.setEnabled(bricks.size() > 0); + } + } + } + + private List getBrickList(Set bricks) { + List brickList = new ArrayList(); + for (Brick brick : bricks) { + brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); + } + return brickList; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java deleted file mode 100644 index b79a4ee4..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveDiskAction.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.gluster.storage.management.gui.actions; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.custom.BusyIndicator; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IWorkbenchPart; - -import com.gluster.storage.management.client.GlusterDataModelManager; -import com.gluster.storage.management.client.VolumesClient; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.utils.StringUtil; -import com.gluster.storage.management.gui.IImageKeys; -import com.gluster.storage.management.gui.utils.GUIHelper; -import com.gluster.storage.management.gui.views.VolumeBricksView; - -public class RemoveDiskAction extends AbstractActionDelegate { - private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); - private GUIHelper guiHelper = GUIHelper.getInstance(); - private Set bricks; - private Volume volume; - boolean confirmDelete = false; - - @Override - protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - - final String actionDesc = action.getDescription(); - List brickList = getBrickList(bricks); - Integer deleteOption = new MessageDialog(getShell(), "Remove Bricks(s)", GUIHelper.getInstance() - .getImage(IImageKeys.VOLUME), "Are you sure you want to remove following bricks from volume [" - + volume.getName() + "] ? \n" + StringUtil.collectionToString(brickList, ", "), - MessageDialog.QUESTION, new String[] { "Cancel", "Remove bricks, delete data", - "Remove bricks, keep data" }, -1).open(); - if (deleteOption <= 0) { // By Cancel button(0) or Escape key(-1) - return; - } - - if (deleteOption == 1) { - confirmDelete = true; - } - BusyIndicator.showWhile(Display.getDefault(), new Runnable() { - public void run() { - VolumesClient client = new VolumesClient(); - try { - client.removeBricks(volume.getName(), bricks, confirmDelete); - // Remove the bricks from the volume object - for (Brick brick : bricks) { - volume.removeBrick(brick); - } - // Update model with removed bricks in the volume - modelManager.removeBricks(volume, bricks); - - showInfoDialog(actionDesc, "Volume [" + volume.getName() - + "] bricks(s) removed successfully!"); - } catch (Exception e) { - showErrorDialog(actionDesc, "Volume [" + volume.getName() - + "] bricks(s) could not be removed! Error: [" + e.getMessage() + "]"); - } - } - }); - } - }); - - } - - @Override - public void dispose() { - } - - @Override - public void selectionChanged(IAction action, ISelection selection) { - super.selectionChanged(action, selection); - - action.setEnabled(false); - volume = (Volume) guiHelper.getSelectedEntity(window, Volume.class); - if (volume != null) { - // a volume is selected on navigation tree. Let's check if the currently open view is volume disks view - IWorkbenchPart view = guiHelper.getActiveView(); - if (view instanceof VolumeBricksView) { - // volume disks view is open. check if any brick is selected - bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); - action.setEnabled(bricks.size() > 0); - } - } - } - - private List getBrickList(Set bricks) { - List brickList = new ArrayList(); - for (Brick brick : bricks) { - brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); - } - return brickList; - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java index 911c57a8..4862b7b1 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveServerAction.java @@ -29,16 +29,12 @@ import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.PlatformUI; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.gui.utils.GUIHelper; -import com.gluster.storage.management.gui.views.NavigationView; public class RemoveServerAction extends AbstractActionDelegate { private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java index fc80b04d..d8f1b955 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java @@ -2,7 +2,6 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; 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.TasksClient; @@ -16,23 +15,16 @@ public class ResumeTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, taskInfo.getName() - + " is Resumed"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Resumed! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, "Resumed"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Resumed! Error: [" + e.getMessage() + "]"); + } } @Override @@ -47,9 +39,7 @@ public class ResumeTaskAction extends AbstractActionDelegate { @Override public void dispose() { - } - } 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 index c259c661..322a87f9 100644 --- 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 @@ -53,13 +53,6 @@ public class StartVolumeAction extends AbstractActionDelegate { } - /* - * (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); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java index abde4e57..12d14b43 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java @@ -16,22 +16,16 @@ public class StopTaskAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - - try { - new TasksClient().resumeTask(taskInfo.getName()); - taskInfo.setStatus( new TaskStatus( new Status(Status.STATUS_CODE_SUCCESS, taskInfo.getName() + " is Stopped"))); - modelManager.updateTask(taskInfo); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Task [" + taskInfo.getName() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + final String actionDesc = action.getDescription(); + + try { + new TasksClient().resumeTask(taskInfo.getName()); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_SUCCESS, "Stopped"))); + modelManager.updateTask(taskInfo); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getDescription() + "] could not be Stopped! Error: [" + e.getMessage() + "]"); + } } @Override @@ -40,7 +34,7 @@ public class StopTaskAction extends AbstractActionDelegate { action.setEnabled(false); if (selectedEntity instanceof TaskInfo) { taskInfo = (TaskInfo) selectedEntity; - action.setEnabled(taskInfo.canStop() + action.setEnabled(taskInfo.getStopSupported() && (taskInfo.getStatus().getCode() == Status.STATUS_CODE_PAUSE || taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING)); } 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 index d4e3d363..62c690e2 100644 --- 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 @@ -21,7 +21,6 @@ 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; @@ -36,34 +35,28 @@ public class StopVolumeAction extends AbstractActionDelegate { @Override protected void performAction(final IAction action) { - Display.getDefault().asyncExec(new Runnable() { - - @Override - public void run() { - final String actionDesc = action.getDescription(); - if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { - showWarningDialog(actionDesc, "Volume [" + volume.getName() + "] is already offline!"); - return; // Volume already offline. Don't do anything. - } + final String actionDesc = action.getDescription(); + if (volume.getStatus() == VOLUME_STATUS.OFFLINE) { + showWarningDialog(actionDesc, "Volume [" + volume.getName() + "] is already offline!"); + return; // Volume already offline. Don't do anything. + } - Integer deleteOption = new MessageDialog(getShell(), "Stop Volume", GUIHelper.getInstance().getImage( - IImageKeys.VOLUME), "Are you sure you want to stop the volume [" + volume.getName() + "] ?", - MessageDialog.QUESTION, new String[] { "No", "Yes" }, -1).open(); + Integer deleteOption = new MessageDialog(getShell(), "Stop Volume", GUIHelper.getInstance().getImage( + IImageKeys.VOLUME), "Are you sure you want to stop the volume [" + volume.getName() + "] ?", + MessageDialog.QUESTION, new String[] { "No", "Yes" }, -1).open(); - if (deleteOption <= 0) { - return; - } + if (deleteOption <= 0) { + return; + } - try { - new VolumesClient().stopVolume(volume.getName()); - showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] stopped successfully!"); - modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); - } catch (Exception e) { - showErrorDialog(actionDesc, - "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); - } - } - }); + try { + new VolumesClient().stopVolume(volume.getName()); + showInfoDialog(actionDesc, "Volume [" + volume.getName() + "] stopped successfully!"); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Volume [" + volume.getName() + "] could not be stopped! Error: [" + e.getMessage() + "]"); + } } @Override diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java new file mode 100644 index 00000000..961dca88 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java @@ -0,0 +1,170 @@ +/** + * AddDiskPage.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.gui.dialogs; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; +import com.richclientgui.toolbox.duallists.IRemovableContentProvider; + +/** + * @author root + * + */ +public class AddBrickPage extends WizardPage { + private List availableDisks = new ArrayList(); + private List selectedDisks = new ArrayList(); + private Volume volume = null; + private BricksSelectionPage page = null; + + + public static final String PAGE_NAME = "add.disk.volume.page"; + + /** + * @param pageName + */ + protected AddBrickPage(Volume volume) { + super(PAGE_NAME); + this.volume = volume; + setTitle("Add Brick"); + + String description = "Add bricks to [" + volume.getName() + "] "; + if ( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + description += "(in multiples of " + volume.getReplicaCount() + ")"; + } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + description += "(in multiples of " + volume.getStripeCount() + ")"; + } + setDescription(description); + + availableDisks = getAvailableDisks(volume); + + setPageComplete(false); + setErrorMessage("Please select bricks to be added to the volume [" + volume.getName() +"]"); + } + + + private boolean isDiskUsed(Volume volume, Disk disk){ + for (Brick volumeBrick : volume.getBricks()) { // expected form of volumeBrick is "server:/export/diskName/volumeName" + if ( disk.getQualifiedBrickName(volume.getName()).equals(volumeBrick.getQualifiedName())) { + return true; + } + } + return false; + } + + protected List getAvailableDisks(Volume volume) { + List availableDisks = new ArrayList(); + for (Disk disk : GlusterDataModelManager.getInstance().getReadyDisksOfAllServers()) { + if ( ! isDiskUsed(volume, disk) ) { + availableDisks.add(disk); + } + } + return availableDisks; + } + + + public List getChosenDisks( ) { + return page.getChosenDisks(); + } + + public List getChosenBricks( String volumeName ) { + return page.getChosenBricks(volumeName); + } + + private boolean isValidDiskSelection(int diskCount) { + if ( diskCount == 0) { + return false; + } + switch (volume.getVolumeType()) { + case DISTRIBUTED_MIRROR: + return (diskCount % volume.getReplicaCount() == 0); + case DISTRIBUTED_STRIPE: + return (diskCount % volume.getStripeCount() == 0); + } + return true; + } + + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createControl(Composite parent) { + getShell().setText("Add Brick"); + List chosenDisks = new ArrayList(); // or volume.getDisks(); + + page = new BricksSelectionPage(parent, SWT.NONE, availableDisks, chosenDisks, volume.getName()); + page.addDiskSelectionListener(new ListContentChangedListener() { + @Override + public void listContentChanged(IRemovableContentProvider contentProvider) { + List newChosenDisks = page.getChosenDisks(); + + // validate chosen disks + if(isValidDiskSelection(newChosenDisks.size())) { + clearError(); + } else { + setError(); + } + } + }); + setControl(page); + } + + private void setError() { + String errorMessage = null; + if ( volume.getVolumeType() == VOLUME_TYPE.PLAIN_DISTRIBUTE) { + errorMessage = "Please select at least one brick!"; + } else if( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + errorMessage = "Please select bricks in multiples of " + volume.getReplicaCount(); + } else { + errorMessage = "Please select bricks in multiples of " + volume.getStripeCount(); + } + + setPageComplete(false); + setErrorMessage(errorMessage); + } + + private void clearError() { + setErrorMessage(null); + setPageComplete(true); + } + + public BricksSelectionPage getDialogPage() { + return this.page; + } + + public void setPageComplete() { + + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java new file mode 100644 index 00000000..bcb3ce3d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java @@ -0,0 +1,102 @@ +/** + * AddDiskWizard.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.gui.dialogs; + +import java.util.ArrayList; +import java.util.List; + +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.Brick; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.core.utils.StringUtil; + +/** + * + */ +public class AddBrickWizard extends Wizard { + private AddBrickPage page; + private Volume volume; + + public AddBrickWizard(Volume volume) { + setWindowTitle("Gluster Management Console - Add Brick"); + setHelpAvailable(false); // TODO: Introduce wizard help + this.volume = volume; + } + + public void addPages() { + page = new AddBrickPage(volume); + addPage(page); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + List bricks = page.getChosenBricks(volume.getName()); + VolumesClient volumeClient = new VolumesClient(); + try { + List brickList = getBrickList(bricks); + + volumeClient.addBricks(volume.getName(), brickList); + List disks = page.getChosenDisks(); + volume.addDisks(GlusterCoreUtil.getQualifiedDiskNames(disks)); + volume.addBricks(bricks); + + // Update model with new bricks in the volume + GlusterDataModelManager.getInstance().addBricks(volume, bricks); + + MessageDialog.openInformation(getShell(), "Add brick(s) to Volume", "Volume [" + volume.getName() + + "] is expanded with bricks [" + StringUtil.collectionToString(brickList, ", ") + "]"); + return true; + } catch (Exception e) { + MessageDialog.openError(getShell(), "Add brick(s) to Volume", e.getMessage()); + return false; + } + } + + private List getBrickList(List bricks) { + List brickList = new ArrayList(); + for(Brick brick : bricks) { + brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); + } + return brickList; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#canFinish() + */ + @Override + public boolean canFinish() { + return super.canFinish() && page.isPageComplete(); + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java deleted file mode 100644 index 48a46c84..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * AddDiskPage.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.gui.dialogs; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; - -import com.gluster.storage.management.client.GlusterDataModelManager; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Disk; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; -import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; -import com.richclientgui.toolbox.duallists.IRemovableContentProvider; - -/** - * @author root - * - */ -public class AddDiskPage extends WizardPage { - private List availableDisks = new ArrayList(); - private List selectedDisks = new ArrayList(); - private Volume volume = null; - private BricksSelectionPage page = null; - - - public static final String PAGE_NAME = "add.disk.volume.page"; - - /** - * @param pageName - */ - protected AddDiskPage(Volume volume) { - super(PAGE_NAME); - this.volume = volume; - setTitle("Add Brick"); - - String description = "Add bricks to [" + volume.getName() + "] "; - if ( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - description += "(in multiples of " + volume.getReplicaCount() + ")"; - } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - description += "(in multiples of " + volume.getStripeCount() + ")"; - } - setDescription(description); - - availableDisks = getAvailableDisks(volume); - - setPageComplete(false); - setErrorMessage("Please select bricks to be added to the volume [" + volume.getName() +"]"); - } - - - private boolean isDiskUsed(Volume volume, Disk disk){ - for (Brick volumeBrick : volume.getBricks()) { // expected form of volumeBrick is "server:/export/diskName/volumeName" - if ( disk.getQualifiedBrickName(volume.getName()).equals(volumeBrick.getQualifiedName())) { - return true; - } - } - return false; - } - - protected List getAvailableDisks(Volume volume) { - List availableDisks = new ArrayList(); - for (Disk disk : GlusterDataModelManager.getInstance().getReadyDisksOfAllServers()) { - if ( ! isDiskUsed(volume, disk) ) { - availableDisks.add(disk); - } - } - return availableDisks; - } - - - public List getChosenDisks( ) { - return page.getChosenDisks(); - } - - public List getChosenBricks( String volumeName ) { - return page.getChosenBricks(volumeName); - } - - private boolean isValidDiskSelection(int diskCount) { - if ( diskCount == 0) { - return false; - } - switch (volume.getVolumeType()) { - case DISTRIBUTED_MIRROR: - return (diskCount % volume.getReplicaCount() == 0); - case DISTRIBUTED_STRIPE: - return (diskCount % volume.getStripeCount() == 0); - } - return true; - } - - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) - */ - @Override - public void createControl(Composite parent) { - getShell().setText("Add Brick"); - List chosenDisks = new ArrayList(); // or volume.getDisks(); - - page = new BricksSelectionPage(parent, SWT.NONE, availableDisks, chosenDisks, volume.getName()); - page.addDiskSelectionListener(new ListContentChangedListener() { - @Override - public void listContentChanged(IRemovableContentProvider contentProvider) { - List newChosenDisks = page.getChosenDisks(); - - // validate chosen disks - if(isValidDiskSelection(newChosenDisks.size())) { - clearError(); - } else { - setError(); - } - } - }); - setControl(page); - } - - private void setError() { - String errorMessage = null; - if ( volume.getVolumeType() == VOLUME_TYPE.PLAIN_DISTRIBUTE) { - errorMessage = "Please select at least one brick!"; - } else if( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - errorMessage = "Please select bricks in multiples of " + volume.getReplicaCount(); - } else { - errorMessage = "Please select bricks in multiples of " + volume.getStripeCount(); - } - - setPageComplete(false); - setErrorMessage(errorMessage); - } - - private void clearError() { - setErrorMessage(null); - setPageComplete(true); - } - - public BricksSelectionPage getDialogPage() { - return this.page; - } - - public void setPageComplete() { - - } - -} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java deleted file mode 100644 index bb55ece1..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * AddDiskWizard.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.gui.dialogs; - -import java.util.ArrayList; -import java.util.List; - -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.Brick; -import com.gluster.storage.management.core.model.Disk; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.utils.GlusterCoreUtil; -import com.gluster.storage.management.core.utils.StringUtil; - -/** - * - */ -public class AddDiskWizard extends Wizard { - private AddDiskPage page; - private Volume volume; - - public AddDiskWizard(Volume volume) { - setWindowTitle("Gluster Management Console - Add Brick"); - setHelpAvailable(false); // TODO: Introduce wizard help - this.volume = volume; - } - - public void addPages() { - page = new AddDiskPage(volume); - addPage(page); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.wizard.Wizard#performFinish() - */ - @Override - public boolean performFinish() { - List bricks = page.getChosenBricks(volume.getName()); - VolumesClient volumeClient = new VolumesClient(); - try { - List brickList = getBrickList(bricks); - - volumeClient.addBricks(volume.getName(), brickList); - List disks = page.getChosenDisks(); - volume.addDisks(GlusterCoreUtil.getQualifiedDiskNames(disks)); - volume.addBricks(bricks); - - // Update model with new bricks in the volume - GlusterDataModelManager.getInstance().addBricks(volume, bricks); - - MessageDialog.openInformation(getShell(), "Add brick(s) to Volume", "Volume [" + volume.getName() - + "] is expanded with bricks [" + StringUtil.collectionToString(brickList, ", ") + "]"); - return true; - } catch (Exception e) { - MessageDialog.openError(getShell(), "Add brick(s) to Volume", e.getMessage()); - return false; - } - } - - private List getBrickList(List bricks) { - List brickList = new ArrayList(); - for(Brick brick : bricks) { - brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); - } - return brickList; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.wizard.Wizard#canFinish() - */ - @Override - public boolean canFinish() { - return super.canFinish() && page.isPageComplete(); - } -} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickPage1.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickPage1.java new file mode 100644 index 00000000..f7ce744f --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickPage1.java @@ -0,0 +1,276 @@ +/** + * MigrateBrickPage1.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ + +package com.gluster.storage.management.gui.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.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +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.Button; +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.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Disk; +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 MigrateBrickPage1 extends WizardPage { + private static final String PAGE_NAME = "migrate.disk.page.1"; + + private enum DISK_TABLE_COLUMN_INDICES { + SERVER, BRICK_DIRECTORY, FREE_SPACE, TOTAL_SPACE + } + + private static final String[] DISK_TABLE_COLUMN_NAMES = { "Server", "Brick Directory", "Free Space (GB)", "Total Space (GB)" }; + + private Volume volume; + private Brick fromBrick; + private static final GUIHelper guiHelper = GUIHelper.getInstance(); + + private TableViewer tableViewerTo; + + private TableViewer tableViewerFrom; + + private Button autoCompleteCheckbox; + + private ITableLabelProvider getDiskLabelProvider(final String volumeName) { + 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.BRICK_DIRECTORY.ordinal() ? disk.getMountPoint() + "/" + volumeName + : columnIndex == DISK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? NumberUtil + .formatNumber(disk.getFreeSpace() / 1024 ) /* Coverted to GB */ + : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil + .formatNumber(disk.getSpace() / 1024) : "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.BRICK_DIRECTORY, SWT.CENTER, 100); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.FREE_SPACE, SWT.CENTER, 90); + setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE, 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 MigrateBrickPage1(Volume volume, Brick brick) { + super(PAGE_NAME); + this.volume = volume; + this.fromBrick = brick; + setTitle("Migrate Brick [" + volume.getName() + "]"); + setPageDescription(null, null); + setPageComplete(false); + } + + private void setPageDescription(String source, String target) { + if (source == null || source == "") { + source = "From Brick"; + } + if (target == null || target == "") { + target = "To Brick"; + } + setDescription("Migrate volume data from \"" + source + "\" to \"" + target + "\""); + } + + private Disk getSelectedDisk(TableViewer tableViewer) { + TableItem[] selectedItems = tableViewer.getTable().getSelection(); + Disk selectedDisk = null; + for (TableItem item : selectedItems) { + selectedDisk = (Disk) item.getData(); + } + return selectedDisk; + } + + 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; + } + + public String getSourceBrickDir() { + Disk sourceDisk = getSelectedDisk(tableViewerFrom); + return sourceDisk.getQualifiedBrickName(volume.getName()); + } + + public String getTargetBrickDir() { + Disk targetDisk = getSelectedDisk(tableViewerTo); + return targetDisk.getQualifiedBrickName(volume.getName()); + } + + public Boolean getAutoCommitSelection() { + return autoCompleteCheckbox.getSelection(); + } + + /** + * 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 Brick:"); + lblFromDisk.setLayoutData(labelLayoutData); + Label lblToDisk = new Label(container, SWT.NONE); + lblToDisk.setText("To Brick:"); + lblToDisk.setLayoutData(labelLayoutData); + + Text txtFilterFrom = guiHelper.createFilterText(container); + Text txtFilterTo = guiHelper.createFilterText(container); + + ITableLabelProvider diskLabelProvider = getDiskLabelProvider(volume.getName()); + + GlusterDataModelManager glusterDataModelManager = GlusterDataModelManager.getInstance(); + List fromBricks = glusterDataModelManager.getReadyDisksOfVolume(volume); + List toDisks = glusterDataModelManager.getReadyDisksOfAllServersExcluding( fromBricks ); + + tableViewerFrom = createTableViewer(container, diskLabelProvider, fromBricks, txtFilterFrom); + + if(fromBrick != null) { + setFromDisk(tableViewerFrom, fromBrick); + } + tableViewerTo = createTableViewer(container, diskLabelProvider, toDisks, txtFilterTo); + + // Auto commit selection field + Composite autoCommitContainer = new Composite(container, SWT.NONE); + GridData data = new GridData(); + data.horizontalSpan = 2; + autoCommitContainer.setLayoutData(data); + autoCompleteCheckbox = new Button(autoCommitContainer, SWT.CHECK); + autoCompleteCheckbox.setSelection(true); + Label lblAutoComplete = new Label(autoCommitContainer, SWT.NONE); + lblAutoComplete.setText("Auto commit on migration complete"); + autoCommitContainer.setLayout( container.getLayout()); + } + + private void setFromDisk(TableViewer tableViewer, Brick brickToSelect) { + Table table = tableViewer.getTable(); + for (int i = 0; i < table.getItemCount(); i++) { + TableItem item = table.getItem(i); + if (item.getData() == brickToSelect) { + table.select(i); + return; + } + } + } + + private void refreshButtonStatus() { + if(tableViewerFrom.getSelection().isEmpty() || tableViewerTo.getSelection().isEmpty()) { + setPageComplete(false); + } else { + setPageComplete(true); + } + } + + private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, + List bricks, 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(bricks.toArray()); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + refreshButtonStatus(); + } + }); + return tableViewer; + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickWizard.java new file mode 100644 index 00000000..4693726b --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateBrickWizard.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.gui.dialogs; + +import java.net.URI; + +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.TasksClient; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.Volume; + +public class MigrateBrickWizard extends Wizard { + private Volume volume; + private Brick brick; + private MigrateBrickPage1 page; + + public MigrateBrickWizard(Volume volume, Brick brick) { + setWindowTitle("Gluster Management Console - Migrate Brick [" + volume.getName() + "]"); + this.volume = volume; + this.brick = brick; + setHelpAvailable(false); // TODO: Introduce wizard help + } + + @Override + public void addPages() { + page = new MigrateBrickPage1(volume, brick); + addPage(page); + } + + @Override + public boolean performFinish() { + + String sourceDir = page.getSourceBrickDir(); + String targetDir = page.getTargetBrickDir(); + Boolean autoCommit = page.getAutoCommitSelection(); + VolumesClient volumesClient = new VolumesClient(); + + try { + URI uri = volumesClient.startMigration(volume.getName(), sourceDir, targetDir, autoCommit); + + // To get the object + TasksClient taskClient = new TasksClient(); + TaskInfo taskInfo = taskClient.getTaskInfo(uri); + if (taskInfo != null && taskInfo instanceof TaskInfo) { + GlusterDataModelManager.getInstance().getModel().getCluster().addTaskInfo(taskInfo); + } + MessageDialog.openInformation(getShell(), "Brick migration", "Brick migration started successfully"); + } catch (Exception e) { + MessageDialog.openError(getShell(), "Error: Migrate brick", e.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 deleted file mode 100644 index 4533ca23..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskPage1.java +++ /dev/null @@ -1,273 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.gui.dialogs; - -import java.util.List; - -import org.eclipse.jface.layout.TableColumnLayout; -import org.eclipse.jface.viewers.ArrayContentProvider; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -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.Button; -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.client.GlusterDataModelManager; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Disk; -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, BRICK_DIRECTORY, FREE_SPACE, TOTAL_SPACE - } - - private static final String[] DISK_TABLE_COLUMN_NAMES = { "Server", "Brick Directory", "Free Space (GB)", "Total Space (GB)" }; - - private Volume volume; - private Brick fromBrick; - private static final GUIHelper guiHelper = GUIHelper.getInstance(); - - private TableViewer tableViewerTo; - - private TableViewer tableViewerFrom; - - private Button autoCompleteCheckbox; - - private ITableLabelProvider getDiskLabelProvider(final String volumeName) { - 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.BRICK_DIRECTORY.ordinal() ? disk.getMountPoint() + "/" + volumeName - : columnIndex == DISK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? NumberUtil - .formatNumber(disk.getFreeSpace() / 1024 ) /* Coverted to GB */ - : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil - .formatNumber(disk.getSpace() / 1024) : "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.BRICK_DIRECTORY, SWT.CENTER, 100); - setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.FREE_SPACE, SWT.CENTER, 90); - setColumnProperties(table, DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE, 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, Brick brick) { - super(PAGE_NAME); - this.volume = volume; - this.fromBrick = brick; - setTitle("Migrate Brick [" + volume.getName() + "]"); - setPageDescription(null, null); - setPageComplete(false); - } - - private void setPageDescription(String source, String target) { - if (source == null || source == "") { - source = "From Brick"; - } - if (target == null || target == "") { - target = "To Brick"; - } - setDescription("Migrate volume data from \"" + source + "\" to \"" + target + "\""); - } - - private Disk getSelectedDisk(TableViewer tableViewer) { - TableItem[] selectedItems = tableViewer.getTable().getSelection(); - Disk selectedDisk = null; - for (TableItem item : selectedItems) { - selectedDisk = (Disk) item.getData(); - } - return selectedDisk; - } - - 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; - } - - public String getSourceBrickDir() { - Disk sourceDisk = getSelectedDisk(tableViewerFrom); - return sourceDisk.getQualifiedBrickName(volume.getName()); - } - - public String getTargetBrickDir() { - Disk targetDisk = getSelectedDisk(tableViewerTo); - return targetDisk.getQualifiedBrickName(volume.getName()); - } - - public Boolean getAutoCommitSelection() { - return autoCompleteCheckbox.getSelection(); - } - - /** - * 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 Brick:"); - lblFromDisk.setLayoutData(labelLayoutData); - Label lblToDisk = new Label(container, SWT.NONE); - lblToDisk.setText("To Brick:"); - lblToDisk.setLayoutData(labelLayoutData); - - Text txtFilterFrom = guiHelper.createFilterText(container); - Text txtFilterTo = guiHelper.createFilterText(container); - - ITableLabelProvider diskLabelProvider = getDiskLabelProvider(volume.getName()); - - GlusterDataModelManager glusterDataModelManager = GlusterDataModelManager.getInstance(); - List fromBricks = glusterDataModelManager.getReadyDisksOfVolume(volume); - List toDisks = glusterDataModelManager.getReadyDisksOfAllServersExcluding( fromBricks ); - - tableViewerFrom = createTableViewer(container, diskLabelProvider, fromBricks, txtFilterFrom); - - if(fromBrick != null) { - setFromDisk(tableViewerFrom, fromBrick); - } - tableViewerTo = createTableViewer(container, diskLabelProvider, toDisks, txtFilterTo); - - // Auto commit selection field - Composite autoCommitContainer = new Composite(container, SWT.NONE); - GridData data = new GridData(); - data.horizontalSpan = 2; - autoCommitContainer.setLayoutData(data); - autoCompleteCheckbox = new Button(autoCommitContainer, SWT.CHECK); - autoCompleteCheckbox.setSelection(true); - Label lblAutoComplete = new Label(autoCommitContainer, SWT.NONE); - lblAutoComplete.setText("Auto commit on migration complete"); - autoCommitContainer.setLayout( container.getLayout()); - } - - private void setFromDisk(TableViewer tableViewer, Brick brickToSelect) { - Table table = tableViewer.getTable(); - for (int i = 0; i < table.getItemCount(); i++) { - TableItem item = table.getItem(i); - if (item.getData() == brickToSelect) { - table.select(i); - return; - } - } - } - - private void refreshButtonStatus() { - if(tableViewerFrom.getSelection().isEmpty() || tableViewerTo.getSelection().isEmpty()) { - setPageComplete(false); - } else { - setPageComplete(true); - } - } - - private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, - List bricks, 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(bricks.toArray()); - - tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent event) { - refreshButtonStatus(); - } - }); - 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 deleted file mode 100644 index 2d65a869..00000000 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/MigrateDiskWizard.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.gui.dialogs; - -import java.net.URI; - -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.TasksClient; -import com.gluster.storage.management.client.VolumesClient; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.Volume; - -public class MigrateDiskWizard extends Wizard { - private Volume volume; - private Brick brick; - private MigrateDiskPage1 page; - - public MigrateDiskWizard(Volume volume, Brick brick) { - setWindowTitle("Gluster Management Console - Migrate Brick [" + volume.getName() + "]"); - this.volume = volume; - this.brick = brick; - setHelpAvailable(false); // TODO: Introduce wizard help - } - - @Override - public void addPages() { - page = new MigrateDiskPage1(volume, brick); - addPage(page); - } - - @Override - public boolean performFinish() { - - String sourceDir = page.getSourceBrickDir(); - String targetDir = page.getTargetBrickDir(); - Boolean autoCommit = page.getAutoCommitSelection(); - VolumesClient volumesClient = new VolumesClient(); - - try { - URI uri = volumesClient.startMigration(volume.getName(), sourceDir, targetDir, autoCommit); - - // To get the object - TasksClient taskClient = new TasksClient(); - TaskInfo taskInfo = taskClient.getTaskInfo(uri); - if (taskInfo != null && taskInfo instanceof TaskInfo) { - GlusterDataModelManager.getInstance().getModel().getCluster().addTaskInfo(taskInfo); - } - MessageDialog.openInformation(getShell(), "Brick migration", "Brick migration started successfully"); - } catch (Exception e) { - MessageDialog.openError(getShell(), "Error: Migrate brick", e.getMessage()); - } - return true; - } -} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java index ce68e22f..8d48af76 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java @@ -32,7 +32,10 @@ import org.eclipse.ui.IWorkbenchSite; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; import com.gluster.storage.management.gui.TasksTableLabelProvider; public class TasksPage extends AbstractTableViewerPage { @@ -45,10 +48,9 @@ public class TasksPage extends AbstractTableViewerPage { private static final String[] TASK_TABLE_COLUMN_NAMES = new String[] { "Task", "Status"}; - @SuppressWarnings("unchecked") - public TasksPage(IWorkbenchSite site, Composite parent, int style, Object taskInfo) { + public TasksPage(IWorkbenchSite site, Composite parent, int style, List taskInfo) { super(site, parent, style, false, false, taskInfo); - this.taskInfoList = (List) taskInfo; + this.taskInfoList = taskInfo; } /* (non-Javadoc) @@ -67,10 +69,26 @@ public class TasksPage extends AbstractTableViewerPage { refreshViewer(); } + @Override + public void taskUpdated(TaskInfo taskInfo) { + refreshViewer(); + } + private void refreshViewer() { tableViewer.refresh(); parent.update(); } + + @Override + public void volumeChanged(Volume volume, Event event) { + super.volumeChanged(volume, event); + if (event.getEventType() == EVENT_TYPE.BRICK_REPLACED) { + if (!tableViewer.getControl().isDisposed()) { + tableViewer.refresh(); + } + } + } + }; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java index d568d519..6a22f806 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -102,7 +102,7 @@ import com.gluster.storage.management.core.utils.ProcessUtil; import com.gluster.storage.management.server.constants.VolumeOptionsDefaults; import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.tasks.MigrateDiskTask; +import com.gluster.storage.management.server.tasks.MigrateBrickTask; import com.gluster.storage.management.server.tasks.RebalanceVolumeTask; import com.gluster.storage.management.server.utils.GlusterUtil; import com.gluster.storage.management.server.utils.ServerUtil; @@ -956,7 +956,7 @@ public class VolumesResource extends AbstractResource { private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, Boolean autoCommit) { - MigrateDiskTask migrateDiskTask = new MigrateDiskTask(clusterService, clusterName, volumeName, fromBrick, + MigrateBrickTask migrateDiskTask = new MigrateBrickTask(clusterService, clusterName, volumeName, fromBrick, toBrick); migrateDiskTask.setAutoCommit(autoCommit); migrateDiskTask.start(); diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java new file mode 100644 index 00000000..bd612ace --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java @@ -0,0 +1,224 @@ +/** + * MigrateDiskTask.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.server.tasks; + +import java.util.concurrent.ExecutionException; + +import org.apache.derby.iapi.sql.execute.ExecPreparedStatement; + +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.core.util.Base64; + +public class MigrateBrickTask extends Task { + + private String fromBrick; + private String toBrick; + private Boolean autoCommit; + private GlusterUtil glusterUtil = new GlusterUtil(); + + private SshUtil sshUtil = new SshUtil(); + + public String getFromBrick() { + return fromBrick; + } + + public void setFromBrick(String fromBrick) { + this.fromBrick = fromBrick; + } + + public String getToBrick() { + return toBrick; + } + + public void setToBrick(String toBrick) { + this.toBrick = toBrick; + } + + public Boolean getAutoCommit() { + return autoCommit; + } + + public void setAutoCommit(Boolean autoCommit) { + this.autoCommit = autoCommit; + } + + public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, + String toBrick) { + super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" + + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); + setFromBrick(fromBrick); + setToBrick(toBrick); + taskInfo.setName(getId()); + } + + public MigrateBrickTask(ClusterService clusterService, String clusterName, TaskInfo info) { + super(clusterService, clusterName, info); + } + + @Override + public String getId() { + return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + + toBrick)); + } + + @Override + public void start() { + try { + startMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + startMigration(getNewOnlineServer().getName()); + } + } + + private void startMigration(String onlineServerName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServerName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "start"); + if (processResult.getOutput().trim().matches(".*started successfully$")) { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); + return; + } + } + + @Override + public void pause() { + try { + pauseMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + pauseMigration(getNewOnlineServer().getName()); + } + } + + private void pauseMigration(String onlineServer) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServer, taskInfo.getReference(), + getFromBrick(), getToBrick(), "pause"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*paused successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_PAUSE); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + return; + } + } + + @Override + public void resume() { + start(); + } + + @Override + public void commit() { + try { + commitMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + commitMigration(getNewOnlineServer().getName()); + } + } + + @Override + public void stop() { + try { + stopMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + stopMigration(getNewOnlineServer().getName()); + } + } + + private void stopMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, taskInfo.getReference(), getFromBrick(), + getToBrick(), "abort"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*aborted successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + } + } + + @Override + public TaskStatus checkStatus() { + try { + return checkMigrationStatus(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + return checkMigrationStatus(getNewOnlineServer().getName()); + } + } + + public void commitMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "commit"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches(".*commit successful$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); // Common + getTaskInfo().setStatus(taskStatus); + } + } + } + + private TaskStatus checkMigrationStatus(String serverName) { + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE) { + return getTaskInfo().getStatus(); + } + + TaskStatus taskStatus = new TaskStatus(); + try { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "status"); + if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$")) { + taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); + if (autoCommit) { + commitMigration(serverName); + return getTaskInfo().getStatus(); // return the committed status + } else { + taskStatus.setMessage(processResult.getOutput().trim() + .replaceAll("Migration complete", "Commit pending")); + } + } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); + } catch (Exception e) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(e.getMessage()); + } + + taskInfo.setStatus(taskStatus); // Update the task status + return taskStatus; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java deleted file mode 100644 index 9bdc9c94..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java +++ /dev/null @@ -1,238 +0,0 @@ -/** - * MigrateDiskTask.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.server.tasks; - -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.core.util.Base64; - -public class MigrateDiskTask extends Task { - - private String fromBrick; - private String toBrick; - private Boolean autoCommit; - - private SshUtil sshUtil = new SshUtil(); - - public String getFromBrick() { - return fromBrick; - } - - public void setFromBrick(String fromBrick) { - this.fromBrick = fromBrick; - } - - public String getToBrick() { - return toBrick; - } - - public void setToBrick(String toBrick) { - this.toBrick = toBrick; - } - - public Boolean getAutoCommit() { - return autoCommit; - } - - public void setAutoCommit(Boolean autoCommit) { - this.autoCommit = autoCommit; - } - - public MigrateDiskTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, String toBrick) { - super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" - + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); - setFromBrick(fromBrick); - setToBrick(toBrick); - taskInfo.setName(getId()); - } - - public MigrateDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { - super(clusterService, clusterName, info); - } - - @Override - public String getId() { - return new String( Base64.encode( taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + toBrick )); - } - - @Override - public void start() { - try { - startMigration(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - startMigration(getNewOnlineServer().getName()); - } - } - - private void startMigration(String onlineServerName) { - String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " - + getToBrick() + " start"; - ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*started successfully$")) { - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); - return; - } - } - - // if we come here, it means task couldn't be started successfully. - throw new GlusterRuntimeException(processResult.toString()); - } - - @Override - public void pause() { - try { - pauseMigration(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - pauseMigration(getNewOnlineServer().getName()); - } - } - - private void pauseMigration(String onlineServer) { - String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() - + " pause"; - - ProcessResult processResult = sshUtil.executeRemote(onlineServer, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().matches("*pause")) { //TODO replace correct pattern to identify the pause status - taskStatus.setCode(Status.STATUS_CODE_PAUSE); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - return; - } - } - - // if we reach here, it means rebalance start failed. - throw new GlusterRuntimeException(processResult.toString()); - } - - - @Override - public void resume() { - start(); - } - - @Override - public void commit() { - try { - commitMigration(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - commitMigration(getNewOnlineServer().getName()); - } - } - - @Override - public void stop() { - try { - stopMigration(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - stopMigration(getNewOnlineServer().getName()); - } - } - - private void stopMigration(String serverName) { - String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() - + " abort"; - - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*aborted successfully$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - return; - } - } - - // if we reach here, it means rebalance start failed. - throw new GlusterRuntimeException(processResult.toString()); - } - - - @Override - public TaskStatus checkStatus() { - try { - return checkMigrationStatus(getOnlineServer().getName()); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one. - return checkMigrationStatus(getNewOnlineServer().getName()); - } - } - - - public void commitMigration(String serverName) { - String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " - + getToBrick() + " commit"; - - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*commit successful$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); // Common - getTaskInfo().setStatus(taskStatus); - return; - } - } - - // if we reach here, it means rebalance start failed. - throw new GlusterRuntimeException(processResult.toString()); - } - - - private TaskStatus checkMigrationStatus(String serverName) { - String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " - + getToBrick() + " status"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$")) { - taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); - if (autoCommit) { - commitMigration(serverName); - } - } else if ( processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - - taskStatus.setMessage(processResult.getOutput()); // common - taskInfo.setStatus(taskStatus); // Update the task status - return taskStatus; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java index 49cd0b8b..4fa6e08c 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java @@ -38,9 +38,9 @@ public abstract class Task { taskInfo.setType(type); taskInfo.setReference(reference); taskInfo.setDescription(desc); - taskInfo.setCanPause(canPause); - taskInfo.setCanStop(canStop); - taskInfo.setCanCommit(canCommit); + taskInfo.setPauseSupported(canPause); + taskInfo.setStopSupported(canStop); + taskInfo.setCommitSupported(canCommit); init(clusterService, clusterName, taskInfo); diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index 788e3eab..d670027b 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -36,7 +36,6 @@ import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo; 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; @@ -45,8 +44,6 @@ import com.gluster.storage.management.core.utils.GlusterCoreUtil; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.core.utils.StringUtil; import com.gluster.storage.management.server.resources.TasksResource; -import com.gluster.storage.management.server.tasks.MigrateDiskTask; -import com.gluster.storage.management.server.tasks.RebalanceVolumeTask; import com.sun.jersey.api.core.InjectParam; @Component @@ -388,26 +385,7 @@ public class GlusterUtil { } private void addBrickToVolume(Volume volume, String serverName, String brickDir) { - // TODO: Brick status should be same as the server status (online/offline) - System.out.println(brickDir); volume.addBrick(new Brick(serverName, BRICK_STATUS.ONLINE, brickDir.split("/")[2].trim(), brickDir)); - - // volume.getBricks().get(0).getName(); - // - // try { - // volume.addDisk(serverName + ":" + brickDir.split("/")[2].trim()); - // } catch (ArrayIndexOutOfBoundsException e) { - // // brick directory of a different form, most probably created manually - // // connect to the server and get disk for the brick directory - // Status status = new ServerUtil().getDiskForDir(serverName, brickDir); - // if (status.isSuccess()) { - // volume.addDisk(serverName + ":" + status.getMessage()); - // } else { - // // Couldn't fetch disk for the brick directory. Log error and add "unknown" as disk name. - // System.out.println("Couldn't fetch disk name for brick [" + serverName + ":" + brickDir + "]"); - // volume.addDisk(serverName + ":unknown"); - // } - // } } private boolean readBrickGroup(String line) { @@ -550,6 +528,17 @@ public class GlusterUtil { throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); } } + + + public ProcessResult executeBrickMigration(String onlineServerName, String volumeName, String fromBrick, + String toBrick, String operation) { + String command = "gluster volume replace-brick " + volumeName + " " + fromBrick + " " + toBrick + " " + operation; + ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); + if (!processResult.isSuccess()) { + throw new GlusterRuntimeException(processResult.toString()); + } + return processResult; + } public static void main(String args[]) { // List names = new GlusterUtil().getGlusterServerNames(); -- cgit From 428b944c60244d4a7dd37fb69ae125272525d7ea Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Fri, 1 Jul 2011 20:29:40 +0530 Subject: Task#111 - Auto-refresh of data in views --- .../management/client/GlusterDataModelManager.java | 173 +++++++++++++++++++-- .../storage/management/client/VolumesClient.java | 2 +- .../storage/management/core/model/Brick.java | 30 +++- .../management/core/model/ClusterListener.java | 2 + .../core/model/DefaultClusterListener.java | 40 ++--- .../storage/management/core/model/Disk.java | 29 +++- .../storage/management/core/model/Event.java | 11 +- .../management/core/model/GlusterDummyModel.java | 49 ------ .../management/core/model/GlusterServer.java | 52 +++---- .../management/core/model/NetworkInterface.java | 19 ++- .../storage/management/core/model/Server.java | 69 ++++++-- .../storage/management/core/model/Volume.java | 111 +++++++------ .../management/core/model/VolumeOptions.java | 28 +++- .../management/core/utils/GlusterCoreUtil.java | 55 +++++-- .../gui/VolumeOptionsTableLabelProvider.java | 5 +- .../management/gui/actions/RemoveBrickAction.java | 4 - .../management/gui/dialogs/AddBrickPage.java | 9 +- .../management/gui/dialogs/AddBrickWizard.java | 17 +- .../gui/dialogs/BricksSelectionPage.java | 6 +- .../management/gui/dialogs/SelectDisksDialog.java | 4 +- .../management/gui/views/NavigationView.java | 2 +- 21 files changed, 484 insertions(+), 233 deletions(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index a9c966c3..221651a3 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -20,6 +20,7 @@ package com.gluster.storage.management.client; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -29,7 +30,6 @@ import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.Disk; import com.gluster.storage.management.core.model.Disk.DISK_STATUS; -import com.gluster.storage.management.core.model.Entity; import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.Event.EVENT_TYPE; import com.gluster.storage.management.core.model.GlusterDataModel; @@ -111,44 +111,173 @@ public class GlusterDataModelManager { private void updateModel(GlusterDataModel model) { updateVolumes(model); - updateServers(model); - // TODO: Update other entities like discovered servers + updateGlusterServers(model); + updateDiscoveredServers(model); } - private void updateServers(GlusterDataModel newModel) { + private void updateDiscoveredServers(GlusterDataModel newModel) { + List oldServers = model.getCluster().getAutoDiscoveredServers(); + List newServers = newModel.getCluster().getAutoDiscoveredServers(); + + Set addedServers = GlusterCoreUtil.getAddedEntities(oldServers, newServers, true); + for (Server addedServer : addedServers) { + addDiscoveredServer(addedServer); + } + + Set removedServers = GlusterCoreUtil.getAddedEntities(newServers, oldServers, true); + for (Server removedServer : removedServers) { + removeDiscoveredServer(removedServer); + } + + Map modifiedServers = GlusterCoreUtil.getModifiedEntities(oldServers, newServers); + for(Entry entry : modifiedServers.entrySet()) { + discoveredServerChanged(entry.getKey(), entry.getValue()); + } + } + + private void updateGlusterServers(GlusterDataModel newModel) { List oldServers = model.getCluster().getServers(); List newServers = newModel.getCluster().getServers(); - List addedServers = GlusterCoreUtil.getAddedEntities(oldServers, newServers, true); + Set addedServers = GlusterCoreUtil.getAddedEntities(oldServers, newServers, true); for (GlusterServer addedServer : addedServers) { addGlusterServer(addedServer); } - List removedServers = GlusterCoreUtil.getAddedEntities(newServers, oldServers, true); + Set removedServers = GlusterCoreUtil.getAddedEntities(newServers, oldServers, true); for (GlusterServer removedServer : removedServers) { removeGlusterServer(removedServer); } - // TODO: Refresh "modified" servers + Map modifiedServers = GlusterCoreUtil.getModifiedEntities(oldServers, newServers); + for(Entry entry : modifiedServers.entrySet()) { + glusterServerChanged(entry.getKey(), entry.getValue()); + } + } + + public void glusterServerChanged(GlusterServer oldServer, GlusterServer newServer) { + oldServer.copyFrom(newServer); + for (ClusterListener listener : listeners) { + listener.serverChanged(oldServer, new Event(EVENT_TYPE.GLUSTER_SERVER_CHANGED, newServer)); + } + + updateDisks(oldServer, oldServer.getDisks(), newServer.getDisks()); + } + + private void updateDisks(Server server, List oldDisks, List newDisks) { + Set addedDisks = GlusterCoreUtil.getAddedEntities(oldDisks, newDisks, false); + addDisks(server, addedDisks); + + Set removedDisks = GlusterCoreUtil.getAddedEntities(newDisks, oldDisks, false); + removeDisks(server, removedDisks); + + Map modifiedDisks = GlusterCoreUtil.getModifiedEntities(oldDisks, newDisks); + disksChanged(server, modifiedDisks); + } + + private void disksChanged(Server server, Map modifiedDisks) { + if(modifiedDisks.size() == 0) { + return; + } + + for (Entry entry : modifiedDisks.entrySet()) { + entry.getKey().copyFrom(entry.getValue()); + } + for (ClusterListener listener : listeners) { + if (server instanceof GlusterServer) { + listener.serverChanged((GlusterServer) server, new Event(EVENT_TYPE.DISKS_CHANGED, modifiedDisks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DISKS_CHANGED, modifiedDisks)); + } + } + } + + public void addDisks(Server server, Set disks) { + if(disks.size() == 0) { + return; + } + + server.addDisks(disks); + for (ClusterListener listener : listeners) { + if(server instanceof GlusterServer) { + listener.serverChanged((GlusterServer)server, new Event(EVENT_TYPE.DISKS_ADDED, disks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DISKS_ADDED, disks)); + } + } + } + + public void removeDisks(Server server, Set disks) { + if(disks.size() == 0) { + return; + } + + for(Disk disk : disks) { + server.removeDisk(disk); + } + + for (ClusterListener listener : listeners) { + if(server instanceof GlusterServer) { + listener.serverChanged((GlusterServer)server, new Event(EVENT_TYPE.DISKS_REMOVED, disks)); + } else { + listener.discoveredServerChanged(server, new Event(EVENT_TYPE.DISKS_REMOVED, disks)); + } + } } private void updateVolumes(GlusterDataModel newModel) { List oldVolumes = model.getCluster().getVolumes(); List newVolumes = newModel.getCluster().getVolumes(); - List addedVolumes = GlusterCoreUtil.getAddedEntities(oldVolumes, newVolumes, false); + Set addedVolumes = GlusterCoreUtil.getAddedEntities(oldVolumes, newVolumes, false); for (Volume addedVolume : addedVolumes) { addVolume(addedVolume); } - List removedVolumes = GlusterCoreUtil.getAddedEntities(newVolumes, oldVolumes, false); + Set removedVolumes = GlusterCoreUtil.getAddedEntities(newVolumes, oldVolumes, false); for (Volume removedVolume : removedVolumes) { deleteVolume(removedVolume); } - // TODO: Refresh "modified" volumes + Map modifiedVolumes = GlusterCoreUtil.getModifiedEntities(oldVolumes, newVolumes); + for(Entry entry : modifiedVolumes.entrySet()) { + volumeChanged(entry.getKey(), entry.getValue()); + } } + private void volumeChanged(Volume oldVolume, Volume newVolume) { + oldVolume.copyFrom(newVolume); + for (ClusterListener listener : listeners) { + listener.volumeChanged(oldVolume, new Event(EVENT_TYPE.VOLUME_CHANGED, newVolume)); + } + updateBricks(oldVolume, oldVolume.getBricks(), newVolume.getBricks()); + } + + private void updateBricks(Volume volume, List oldBricks, List newBricks) { + Set addedBricks = GlusterCoreUtil.getAddedEntities(oldBricks, newBricks, false); + addBricks(volume, addedBricks); + + Set removedBricks = GlusterCoreUtil.getAddedEntities(newBricks, oldBricks, false); + removeBricks(volume, removedBricks); + + Map modifiedBricks = GlusterCoreUtil.getModifiedEntities(oldBricks, newBricks); + bricksChanged(volume, modifiedBricks); + } + + public void bricksChanged(Volume volume, Map modifiedBricks) { + if(modifiedBricks.size() == 0) { + return; + } + + for(Entry entry : modifiedBricks.entrySet()) { + entry.getKey().copyFrom(entry.getValue()); + } + + for (ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_CHANGED, modifiedBricks)); + } + } + private void initializeGlusterServers(Cluster cluster) { cluster.setServers(new GlusterServersClient().getServers()); } @@ -341,6 +470,14 @@ public class GlusterDataModelManager { } } + public void discoveredServerChanged(Server oldServer, Server newServer) { + oldServer.copyFrom(newServer); + for (ClusterListener listener : listeners) { + listener.discoveredServerChanged(oldServer, new Event(EVENT_TYPE.DISCOVERED_SERVER_CHANGED, newServer)); + } + updateDisks(oldServer, oldServer.getDisks(), newServer.getDisks()); + } + public void removeDiscoveredServer(String serverName) { Cluster cluster = model.getCluster(); // TODO: Move auto-discovered servers outside the cluster @@ -398,13 +535,27 @@ public class GlusterDataModelManager { } } - public void addBricks(Volume volume, List bricks) { + public void addBricks(Volume volume, Set bricks) { + if(bricks.size() == 0) { + return; + } + + volume.addBricks(bricks); for (ClusterListener listener : listeners) { listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_ADDED, bricks)); } } public void removeBricks(Volume volume, Set bricks) { + if(bricks.size() == 0) { + return; + } + + // Remove the bricks from the volume object + for (Brick brick : bricks) { + volume.removeBrick(brick); + } + for (ClusterListener listener : listeners) { listener.volumeChanged(volume, new Event(EVENT_TYPE.BRICKS_REMOVED, bricks)); } 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 index 2866a8e1..7beb8433 100644 --- 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 @@ -139,7 +139,7 @@ public class VolumesClient extends AbstractClient { VolumeOptionInfoListResponse.class)).getOptions(); } - public void addBricks(String volumeName, List brickList) { + public void addBricks(String volumeName, Set brickList) { String bricks = StringUtil.collectionToString(brickList, ","); Form form = new Form(); form.add(RESTConstants.FORM_PARAM_BRICKS, bricks); diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Brick.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Brick.java index fef8f969..0b330514 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Brick.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Brick.java @@ -19,6 +19,7 @@ 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; @@ -35,6 +36,12 @@ public class Brick extends Entity { public Brick() { } + @Override + @XmlTransient + public String getName() { + return getQualifiedName(); + } + public BRICK_STATUS getStatus() { return status; } @@ -83,7 +90,7 @@ public class Brick extends Entity { } public boolean filter(String filterString, boolean caseSensitive) { - return StringUtil.filterString(getServerName() + getBrickDirectory() + getDiskName(), filterString, + return StringUtil.filterString(getServerName() + getBrickDirectory() + getDiskName() + getStatusStr(), filterString, caseSensitive); } @@ -91,4 +98,25 @@ public class Brick extends Entity { public String toString() { return getQualifiedName(); } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Brick)) { + return false; + } + + Brick brick = (Brick)obj; + if(getQualifiedName().equals(brick.getQualifiedName()) && getStatus() == brick.getStatus()) { + return true; + } + + return false; + } + + public void copyFrom(Brick newBrick) { + setServerName(newBrick.getServerName()); + setBrickDirectory(newBrick.getBrickDirectory()); + setDiskName(newBrick.getDiskName()); + setStatus(newBrick.getStatus()); + } } 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 index 71de5e23..350c9102 100644 --- 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 @@ -27,6 +27,8 @@ public interface ClusterListener { public void discoveredServerRemoved(Server server); + public void discoveredServerChanged(Server server, Event event); + public void serverAdded(GlusterServer server); public void serverRemoved(GlusterServer server); 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 index d3b0e42e..c530fde4 100644 --- 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 @@ -26,79 +26,83 @@ public class DefaultClusterListener implements ClusterListener { @Override public void serverAdded(GlusterServer server) { - clusterChanged(); + modelChanged(); } @Override public void serverRemoved(GlusterServer server) { - clusterChanged(); + modelChanged(); } @Override public void serverChanged(GlusterServer server, Event event) { - clusterChanged(); + modelChanged(); } @Override public void volumeAdded(Volume volume) { - clusterChanged(); + modelChanged(); } @Override public void volumeRemoved(Volume volume) { - clusterChanged(); + modelChanged(); } @Override public void volumeChanged(Volume volume, Event event) { - clusterChanged(); + modelChanged(); } @Override public void discoveredServerAdded(Server server) { - clusterChanged(); + modelChanged(); } @Override public void discoveredServerRemoved(Server server) { - clusterChanged(); + modelChanged(); } @Override public void volumeCreated(Volume volume) { - clusterChanged(); + modelChanged(); } @Override public void volumeDeleted(Volume volume) { - clusterChanged(); + modelChanged(); } @Override public void taskAdded(TaskInfo taskInfo) { - clusterChanged(); + modelChanged(); } @Override public void taskRemoved(TaskInfo taskInfo) { - clusterChanged(); + modelChanged(); } @Override public void taskUpdated(TaskInfo taskInfo) { - clusterChanged(); + modelChanged(); } - + /** * 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. + * task on any change happening in the 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 data model changes. */ - public void clusterChanged() { + public void modelChanged() { } - + + @Override + public void discoveredServerChanged(Server server, Event event) { + modelChanged(); + } } 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 index a399a03a..ecc3a278 100644 --- 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 @@ -132,4 +132,31 @@ public class Disk extends Entity { public String getQualifiedBrickName(String volumeName) { return getServerName() + ":" + getMountPoint() + File.separator + volumeName; } -} + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Disk)) { + return false; + } + Disk disk = (Disk)obj; + + if (getName().equals(disk.getName()) && getServerName().equals(disk.getServerName()) + && getMountPoint().equals(disk.getMountPoint()) && getDescription().equals(disk.getDescription()) + && getStatus() == disk.getStatus() && getSpace() == disk.getSpace() + && getSpaceInUse() == disk.getSpaceInUse()) { + return true; + } + + return false; + } + + public void copyFrom(Disk newDisk) { + setName(newDisk.getName()); + setDescription(newDisk.getDescription()); + setMountPoint(newDisk.getMountPoint()); + setServerName(newDisk.getServerName()); + setStatus(newDisk.getStatus()); + setSpace(newDisk.getSpace()); + setSpaceInUse(newDisk.getSpaceInUse()); + } +} \ No newline at end of file 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 index 1e172d1c..62f70040 100644 --- 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 @@ -22,12 +22,17 @@ public class Event { public enum EVENT_TYPE { BRICKS_ADDED, BRICKS_REMOVED, + BRICKS_CHANGED, BRICK_REPLACED, - NETWORK_INTERFACE_ADDED, - NETWORK_INTERFACE_REMOVED, VOLUME_STATUS_CHANGED, VOLUME_OPTIONS_RESET, - VOLUME_OPTION_SET + VOLUME_OPTION_SET, + VOLUME_CHANGED, + GLUSTER_SERVER_CHANGED, + DISKS_ADDED, + DISKS_REMOVED, + DISKS_CHANGED, + DISCOVERED_SERVER_CHANGED } private EVENT_TYPE eventType; 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 index 8324b22d..f2ccc5db 100644 --- 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 @@ -88,7 +88,6 @@ public class GlusterDummyModel { initializeAutoDiscoveredServers(cluster); initializeDisks(); addDisksToServers(); - addDisksToVolumes(); addVolumeOptions(); createDummyLogMessages(); @@ -170,27 +169,6 @@ public class GlusterDummyModel { server5.addDisk(s5db); } - private void addDisksToVolumes() { - volume1.addDisk("server1:sda"); - - volume2.addDisk("server2:sda"); - volume2.addDisk("server1:sdb"); - volume2.addDisk("server3:sda"); - volume2.addDisk("server4:sda"); - - volume3.addDisk("server2:sdb"); - volume3.addDisk("server4:sda"); - volume3.addDisk("server5:sda"); - - volume4.addDisk("server1:sda"); - volume4.addDisk("server3:sda"); - volume4.addDisk("server4:sda"); - volume4.addDisk("server5:sdb"); - - volume5.addDisk("server2:sda"); - volume5.addDisk("server5:sdb"); - } - private void initializeGlusterServers(Cluster cluster) { List servers = new ArrayList(); server1 = addGlusterServer(servers, cluster, "Server1", SERVER_STATUS.ONLINE, "eth0", 4, 56.3, 16, 8.4); @@ -254,33 +232,6 @@ public class GlusterDummyModel { return null; } - public List getReadyDisksOfVolume(Volume volume) { - // List disks = new ArrayList(); - // for (Disk disk : volume.getDisks()) { - // if (disk.isReady()) { - // disks.add(disk); - // } - // } - // return disks; - Disk disk = null; - List volumeDisks = new ArrayList(); - for (String volumeDisk : volume.getDisks()) { - disk = getVolumeDisk(volumeDisk); - if (disk != null && disk.isReady()) { - volumeDisks.add(disk); - } - } - return volumeDisks; - } - - public List getReadyDisksOfAllVolumes() { - List disks = new ArrayList(); - for (Volume volume : ((Cluster) model.getChildren().get(0)).getVolumes()) { - disks.addAll(getReadyDisksOfVolume(volume)); - } - return disks; - } - public List getReadyDisksOfAllServers() { return getReadyDisksOfAllServersExcluding(new ArrayList()); } 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 index a9455f48..d6105f23 100644 --- 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 @@ -33,7 +33,6 @@ public class GlusterServer extends Server { private String uuid; private SERVER_STATUS status; - private Cluster cluster; public GlusterServer() { } @@ -48,12 +47,6 @@ public class GlusterServer extends Server { 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 Boolean isOnline() { return getStatus() == SERVER_STATUS.ONLINE; } @@ -78,32 +71,31 @@ public class GlusterServer extends Server { 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 + * Filter matches if any of the properties name and status contains the filter string */ @Override public boolean filter(String filterString, boolean caseSensitive) { return StringUtil.filterString(getName() + getStatusStr(), filterString, caseSensitive); } -} + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof GlusterServer)) { + return false; + } + GlusterServer server = (GlusterServer)obj; + + if(super.equals(server) && getUuid().equals(server.getUuid()) && getStatus() == server.getStatus()){ + return true; + } + + return false; + } + + public void copyFrom(GlusterServer server) { + super.copyFrom(server); + setUuid(server.getUuid()); + setStatus(server.getStatus()); + } +} \ No newline at end of file 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 index c0521ef3..181b8e66 100644 --- 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 @@ -92,4 +92,21 @@ public class NetworkInterface extends Entity { this.speed = speed; } -} + @Override + public boolean equals(Object obj) { + if (!(obj instanceof NetworkInterface)) { + return false; + } + + NetworkInterface networkInterface = (NetworkInterface) obj; + if (getName().equals(networkInterface.getName()) && getHwAddr().equals(networkInterface.getHwAddr()) + && getIpAddress().equals(networkInterface.getIpAddress()) + && getDefaultGateway().equals(networkInterface.getDefaultGateway()) + && getNetMask().equals(networkInterface.getNetMask()) && getSpeed().equals(networkInterface.getSpeed()) + && getModel().equals(networkInterface.getModel())) { + return true; + } + + return false; + } +} \ 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 index 487733c3..9e9212dc 100644 --- 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 @@ -19,17 +19,18 @@ package com.gluster.storage.management.core.model; import java.util.ArrayList; +import java.util.Collection; 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.GlusterCoreUtil; import com.gluster.storage.management.core.utils.StringUtil; @XmlRootElement(name = "server") public class Server extends Entity { - private List networkInterfaces = new ArrayList(); private int numOfCPUs; private double cpuUsage; private double totalMemory; @@ -37,6 +38,7 @@ public class Server extends Entity { private double totalDiskSpace = 0; private double diskSpaceInUse = 0; private List disks = new ArrayList(); + private List networkInterfaces = new ArrayList(); public Server() { @@ -143,7 +145,7 @@ public class Server extends Entity { } } - public void addDisks(List disks) { + public void addDisks(Collection disks) { for (Disk disk : disks) { addDisk(disk); } @@ -184,19 +186,54 @@ public class Server extends Entity { public boolean filter(String filterString, boolean caseSensitive) { return StringUtil.filterString(getName() + getIpAddressesAsString(), filterString, caseSensitive); } - + + /** + * Note: this method doesn't copy the disks. Clients should write separate code to identify added/removed/modified + * disks and update the server disks appropriately. + * + * @param server + */ @SuppressWarnings("unchecked") public void copyFrom(Server server) { - this.setName(server.getName()); - this.setParent(server.getParent()); - this.setChildren(( List) server.getChildren()); - this.setNetworkInterfaces(server.getNetworkInterfaces()); - this.setNumOfCPUs(server.getNumOfCPUs()); - this.setCpuUsage(server.getCpuUsage()); - this.setTotalMemory(server.getTotalMemory()); - this.setMemoryInUse(server.getMemoryInUse()); - this.setTotalDiskSpace(server.getTotalDiskSpace()); - this.setDiskSpaceInUse(server.getDiskSpaceInUse()); - this.setDisks(server.getDisks()); - } -} + setName(server.getName()); + setParent(server.getParent()); + setChildren((List) server.getChildren()); + setNetworkInterfaces(server.getNetworkInterfaces()); + setNumOfCPUs(server.getNumOfCPUs()); + setCpuUsage(server.getCpuUsage()); + setTotalMemory(server.getTotalMemory()); + setMemoryInUse(server.getMemoryInUse()); + setTotalDiskSpace(server.getTotalDiskSpace()); + setDiskSpaceInUse(server.getDiskSpaceInUse()); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Server)) { + return false; + } + Server server = (Server)obj; + + if (!(getName().equals(server.getName()) && getNumOfCPUs() == server.getNumOfCPUs() + && getCpuUsage() == server.getCpuUsage() && getTotalMemory() == server.getTotalMemory() + && getMemoryInUse() == server.getMemoryInUse() && getDisks().size() == server.getDisks().size() && getNetworkInterfaces() + .size() == server.getNetworkInterfaces().size())) { + return false; + } + + for(Disk disk : getDisks()) { + if (!disk.equals(GlusterCoreUtil.getEntity(server.getDisks(), disk.getName(), false))) { + return false; + } + } + + for (NetworkInterface networkInterface : getNetworkInterfaces()) { + if (!networkInterface.equals(GlusterCoreUtil.getEntity(server.getNetworkInterfaces(), + networkInterface.getName(), false))) { + return false; + } + } + + return true; + } +} \ No newline at end of file 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 index 1d5b2fec..006202fb 100644 --- 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 @@ -20,6 +20,7 @@ package com.gluster.storage.management.core.model; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -30,6 +31,7 @@ import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; import com.gluster.storage.management.core.utils.StringUtil; @XmlRootElement @@ -62,16 +64,12 @@ public class Volume extends Entity { 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 VolumeOptions options = new VolumeOptions(); - - private double totalDiskSpace = 0; - private List disks = new ArrayList(); private List bricks = new ArrayList(); public Volume() { @@ -105,10 +103,6 @@ public class Volume extends Entity { return STATUS_STR[getStatus().ordinal()]; } - public int getNumOfDisks() { - return disks.size(); - } - public int getNumOfBricks() { return bricks.size(); } @@ -164,15 +158,6 @@ public class Volume extends Entity { this.status = status; } - @XmlTransient - public Cluster getCluster() { - return cluster; - } - - public void setCluster(Cluster cluster) { - this.cluster = cluster; - } - @XmlElementWrapper(name = "nasProtocols") @XmlElement(name = "nasProtocol", type=NAS_PROTOCOL.class) public Set getNASProtocols() { @@ -214,38 +199,11 @@ public class Volume extends Entity { this.options.setOptionsMap(options); } - public double getTotalDiskSpace() { - return totalDiskSpace; - } - - public List getDisks() { - return disks; - } - - public void addDisk(String disk) { - disks.add(disk); - } - - public void addDisks(List disks) { - for (String disk : disks) { - addDisk(disk); - } - } - - public void removeDisk(String disk) { - disks.remove(disk); - } - - public void removeAllDisks() { - disks.clear(); - totalDiskSpace = 0; - } - public void addBrick(Brick brick) { bricks.add(brick); } - public void addBricks(List bricks) { + public void addBricks(Collection bricks) { this.bricks.addAll(bricks); } @@ -264,11 +222,6 @@ public class Volume extends Entity { return bricks; } - public void setDisks(List disks) { - removeAllDisks(); - addDisks(disks); - } - public void enableNFS() { nasProtocols.add(NAS_PROTOCOL.NFS); } @@ -284,13 +237,6 @@ public class Volume extends Entity { 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 @@ -298,7 +244,7 @@ public class Volume extends Entity { @Override public boolean filter(String filterString, boolean caseSensitive) { return StringUtil.filterString(getName() + getVolumeTypeStr() + getTransportTypeStr() + getStatusStr() - + getNumOfDisks(), filterString, caseSensitive); + + getNumOfBricks(), filterString, caseSensitive); } public List getBrickDirectories() { @@ -308,4 +254,51 @@ public class Volume extends Entity { } return brickDirectories; } -} + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Volume)) { + return false; + } + + Volume volume = (Volume)obj; + + if (!(getName().equals(volume.getName()) && getVolumeType() == volume.getVolumeType() + && getTransportType() == volume.getTransportType() && getStatus() == volume.getStatus() + && getReplicaCount() == volume.getReplicaCount() && getStripeCount() == volume.getStripeCount()) + && getOptions().equals(volume.getOptions())) { + return false; + } + + for(NAS_PROTOCOL nasProtocol : getNASProtocols()) { + if(!(volume.getNASProtocols().contains(nasProtocol))) { + return false; + } + } + + for (Brick brick : getBricks()) { + if (!(brick.equals(GlusterCoreUtil.getEntity(volume.getBricks(), brick.getName(), false)))) { + return false; + } + } + + return true; + } + + /** + * Note: this method doesn't copy the bricks. Clients should write separate code to identify added/removed/modified + * bricks and update the volume bricks appropriately. + * + * @param newVolume + */ + public void copyFrom(Volume newVolume) { + setName(newVolume.getName()); + setVolumeType(newVolume.getVolumeType()); + setTransportType(newVolume.getTransportType()); + setStatus(newVolume.getStatus()); + setReplicaCount(newVolume.getReplicaCount()); + setStripeCount(newVolume.getStripeCount()); + setNASProtocols(newVolume.getNASProtocols()); + getOptions().copyFrom(newVolume.getOptions()); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptions.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptions.java index f16dd809..f928c241 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptions.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/VolumeOptions.java @@ -86,4 +86,30 @@ public class VolumeOptions { public boolean containsKey(String key) { return optionsMap.containsKey(key); } -} + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof VolumeOptions)) { + return false; + } + + VolumeOptions options = (VolumeOptions)obj; + if(getOptions().size() != options.size()) { + return false; + } + + for(VolumeOption option : getOptions()) { + if(!(option.getValue().equals(options.get(option.getKey())))) { + return false; + } + } + + return true; + } + + public void copyFrom(VolumeOptions options) { + for(Entry entry : options.entrySet()) { + optionsMap.put(entry.getKey(), entry.getValue()); + } + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java index 76a7fbfc..838612be 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java @@ -21,7 +21,10 @@ package com.gluster.storage.management.core.utils; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import com.gluster.storage.management.core.model.Brick; @@ -47,6 +50,25 @@ public class GlusterCoreUtil { return qualifiedBricks; } + /** + * Compares the two entity lists and returns the list of entities from first list that have been modified in the second + * + * @param oldEntities + * @param newEntities + * @return List of entities that have been modified + */ + public static Map getModifiedEntities(List oldEntities, List newEntities) { + Map modifiedEntities = new HashMap(); + for (T oldEntity : oldEntities) { + T newEntity = getEntity(newEntities, oldEntity.getName(), false); + if(newEntity != null && !oldEntity.equals(newEntity)) { + // old and new entities differ. mark it as modified. + modifiedEntities.put(oldEntity, newEntity); + } + } + return modifiedEntities; + } + /** * Compares the two entity lists and returns the list of entities present only in the second argument * newEntities @@ -56,10 +78,11 @@ public class GlusterCoreUtil { * @param caseInsensitive If true, the entity name comparison will be done in case insensitive manner * @return List of entities that are present only in the second argument newEntities */ - public static List getAddedEntities(List oldEntities, List newEntities, boolean caseInsensitive) { - List addedEntities = new ArrayList(); - for(T newEntity : newEntities) { - if(!containsEntity(oldEntities, newEntity, caseInsensitive)) { + public static Set getAddedEntities(List oldEntities, List newEntities, + boolean caseInsensitive) { + Set addedEntities = new HashSet(); + for (T newEntity : newEntities) { + if (!containsEntity(oldEntities, newEntity, caseInsensitive)) { // old entity list doesn't contain this entity. mark it as new. addedEntities.add(newEntity); } @@ -67,22 +90,26 @@ public class GlusterCoreUtil { return addedEntities; } - public static boolean containsEntity(List entityList, Entity searchEntity, boolean caseInsensitive) { - String searchEntityName = searchEntity.getName(); - if(caseInsensitive) { + public static boolean containsEntity(List entityList, Entity searchEntity, + boolean caseInsensitive) { + return getEntity(entityList, searchEntity.getName(), caseInsensitive) != null; + } + + public static T getEntity(List entityList, String searchEntityName, boolean caseInsensitive) { + if (caseInsensitive) { searchEntityName = searchEntityName.toUpperCase(); } - - for(T entity : entityList) { + + for (T entity : entityList) { String nextEntityName = entity.getName(); - if(caseInsensitive) { + if (caseInsensitive) { nextEntityName = nextEntityName.toUpperCase(); } - if(nextEntityName.equals(searchEntityName)) { - return true; + if (nextEntityName.equals(searchEntityName)) { + return entity; } } - - return false; + + return null; } } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java index 007c7adb..cd85d22b 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/VolumeOptionsTableLabelProvider.java @@ -20,19 +20,16 @@ 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.pages.VolumeOptionsPage.OPTIONS_TABLE_COLUMN_INDICES; public class VolumeOptionsTableLabelProvider extends TableLabelProviderAdapter { - private GUIHelper guiHelper = GUIHelper.getInstance(); - @Override public String getColumnText(Object element, int columnIndex) { if (!(element instanceof Entry)) { return null; } - Entry entry = (Entry) element; + Entry entry = (Entry) element; String key = entry.getKey(); String value = entry.getValue(); return (columnIndex == OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal() ? key diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java index 0f411a59..f7d1207c 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/RemoveBrickAction.java @@ -47,10 +47,6 @@ public class RemoveBrickAction extends AbstractActionDelegate { VolumesClient client = new VolumesClient(); try { client.removeBricks(volume.getName(), bricks, confirmDelete); - // Remove the bricks from the volume object - for (Brick brick : bricks) { - volume.removeBrick(brick); - } // Update model with removed bricks in the volume modelManager.removeBricks(volume, bricks); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java index 961dca88..bd36ff7c 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickPage.java @@ -21,7 +21,9 @@ package com.gluster.storage.management.gui.dialogs; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; @@ -90,12 +92,11 @@ public class AddBrickPage extends WizardPage { return availableDisks; } - - public List getChosenDisks( ) { - return page.getChosenDisks(); + public Set getChosenDisks() { + return new HashSet(page.getChosenDisks()); } - public List getChosenBricks( String volumeName ) { + public Set getChosenBricks( String volumeName ) { return page.getChosenBricks(volumeName); } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java index bcb3ce3d..58255f8c 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddBrickWizard.java @@ -20,8 +20,9 @@ */ package com.gluster.storage.management.gui.dialogs; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.Wizard; @@ -29,10 +30,7 @@ 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.Brick; -import com.gluster.storage.management.core.model.Disk; -import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.utils.GlusterCoreUtil; import com.gluster.storage.management.core.utils.StringUtil; /** @@ -60,15 +58,12 @@ public class AddBrickWizard extends Wizard { */ @Override public boolean performFinish() { - List bricks = page.getChosenBricks(volume.getName()); + Set bricks = page.getChosenBricks(volume.getName()); VolumesClient volumeClient = new VolumesClient(); try { - List brickList = getBrickList(bricks); + Set brickList = getBrickList(bricks); volumeClient.addBricks(volume.getName(), brickList); - List disks = page.getChosenDisks(); - volume.addDisks(GlusterCoreUtil.getQualifiedDiskNames(disks)); - volume.addBricks(bricks); // Update model with new bricks in the volume GlusterDataModelManager.getInstance().addBricks(volume, bricks); @@ -82,8 +77,8 @@ public class AddBrickWizard extends Wizard { } } - private List getBrickList(List bricks) { - List brickList = new ArrayList(); + private Set getBrickList(Set bricks) { + Set brickList = new HashSet(); for(Brick brick : bricks) { brickList.add(brick.getServerName() + ":" + brick.getBrickDirectory()); } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/BricksSelectionPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/BricksSelectionPage.java index fbfb52d1..db963b18 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/BricksSelectionPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/BricksSelectionPage.java @@ -19,7 +19,9 @@ package com.gluster.storage.management.gui.dialogs; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.swt.SWT; @@ -314,11 +316,11 @@ public class BricksSelectionPage extends Composite { return null; } - public List getChosenBricks(String volumeName) { + public Set getChosenBricks(String volumeName) { Object[] bricksArr = (Object[]) chosenBricksContentProvider.getElements(dualTableViewer); if (bricksArr != null) { - List bricks = new ArrayList(); + Set bricks = new HashSet(); for (Object disk : bricksArr) { bricks.add(new Brick(((Disk) disk).getServerName(), BRICK_STATUS.ONLINE, ((Disk) disk).getName(), ((Disk) disk).getMountPoint() + "/" + volumeName)); // Assumption mount point is not having 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 index a4152899..e010ed5c 100644 --- 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 @@ -18,8 +18,8 @@ *******************************************************************************/ package com.gluster.storage.management.gui.dialogs; -import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; @@ -112,7 +112,7 @@ public class SelectDisksDialog extends Dialog { return disksPage.getChosenDisks(); } - public List getSelectedBricks(String volumeName) { + public Set getSelectedBricks(String volumeName) { return disksPage.getChosenBricks(volumeName); } } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java index 458dcf61..8acb4a75 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java @@ -82,7 +82,7 @@ public class NavigationView extends ViewPart implements ISelectionListener { // Refresh the navigation tree whenever there is a change to the data model GlusterDataModelManager.getInstance().addClusterListener(new DefaultClusterListener() { - public void clusterChanged() { + public void modelChanged() { treeViewer.refresh(); } -- cgit From 1ac92cc69244163d38175b496bdd5729b58fa42a Mon Sep 17 00:00:00 2001 From: Selvasundaram Date: Tue, 5 Jul 2011 13:03:52 +0530 Subject: Server uuid issue and server disk details issue fixes --- .../management/core/constants/GlusterConstants.java | 1 - .../storage/management/core/model/GlusterServer.java | 2 +- .../storage/management/server/utils/GlusterUtil.java | 14 +++++++++++++- .../storage/management/server/utils/ServerUtil.java | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java index 064037ec..f48f33cf 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java @@ -31,5 +31,4 @@ public class GlusterConstants { }; public static final List VOLUME_LOG_LEVELS_ARR = StringUtil.enumToArray(VOLUME_LOG_LEVELS.values()); - } 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 index d6105f23..025db809 100644 --- 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 @@ -86,7 +86,7 @@ public class GlusterServer extends Server { } GlusterServer server = (GlusterServer)obj; - if(super.equals(server) && getUuid().equals(server.getUuid()) && getStatus() == server.getStatus()){ + if (super.equals(server) && getUuid().equals(server.getUuid()) && getStatus() == server.getStatus()) { return true; } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index f4eac91d..2a86a690 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -67,6 +67,7 @@ public class GlusterUtil { private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; private static final String VOLUME_TYPE_REPLICATE = "Replicate"; + private static final String GLUSTERD_INFO_FILE = "/etc/glusterd/glusterd.info"; private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); @@ -112,6 +113,15 @@ public class GlusterUtil { } return null; } + + private String getUuid(String serverName) { + ProcessResult result = getSshUtil().executeRemote(serverName, "cat " + GLUSTERD_INFO_FILE); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't read file [" + GLUSTERD_INFO_FILE + "]. Error: " + + result.toString()); + } + return result.getOutput().split("=")[1]; + } public List getGlusterServers(GlusterServer knownServer) { String output = getPeerStatus(knownServer.getName()); @@ -119,9 +129,11 @@ public class GlusterUtil { return null; } + knownServer.setUuid(getUuid(knownServer.getName())); + List glusterServers = new ArrayList(); - // TODO: Append the known server. But where? Order matters in replication/striping glusterServers.add(knownServer); + GlusterServer server = null; boolean foundHost = false; boolean foundUuid = false; 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 index ed77def3..2e78b57b 100644 --- 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 @@ -91,6 +91,7 @@ public class ServerUtil { throw new GlusterRuntimeException(((Status)response).getMessage()); } server.copyFrom((Server) response); // Update the details in object + server.setDisks(((Server) response).getDisks()); } /** -- cgit From 429d3149d5cf042f1aabc5836d7df451c7da06bd Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Tue, 5 Jul 2011 13:16:45 +0530 Subject: Changed base URI of REST resources to include the API version --- .../storage/management/client/UsersClient.java | 41 +- .../client/constants/ClientConstants.java | 2 +- .../management/client/utils/ClientUtil.java | 2 +- src/com.gluster.storage.management.core/.classpath | 1 + .../META-INF/MANIFEST.MF | 5 +- .../build.properties | 5 +- .../lib/log4j-1.2.16.jar | Bin 0 -> 481534 bytes .../storage/management/core/model/User.java | 3 + .../WebContent/WEB-INF/web.xml | 8 +- .../server/resources/AbstractResource.java | 184 ---- .../server/resources/AbstractServersResource.java | 38 - .../server/resources/AlertsResource.java | 82 -- .../server/resources/ClustersResource.java | 141 --- .../resources/DiscoveredServersResource.java | 141 --- .../server/resources/GlusterServersResource.java | 444 --------- .../management/server/resources/TasksResource.java | 175 ---- .../management/server/resources/UsersResource.java | 87 -- .../server/resources/VolumesResource.java | 1025 -------------------- .../server/resources/v1_0/AbstractResource.java | 173 ++++ .../resources/v1_0/AbstractServersResource.java | 38 + .../server/resources/v1_0/AlertsResource.java | 82 ++ .../server/resources/v1_0/ClustersResource.java | 141 +++ .../resources/v1_0/DiscoveredServersResource.java | 141 +++ .../resources/v1_0/GlusterServersResource.java | 444 +++++++++ .../server/resources/v1_0/TasksResource.java | 175 ++++ .../server/resources/v1_0/UsersResource.java | 91 ++ .../server/resources/v1_0/VolumesResource.java | 1025 ++++++++++++++++++++ .../server/tasks/ServerDiscoveryTask.java | 2 +- .../management/server/utils/GlusterUtil.java | 2 +- .../src/spring/gluster-server-security.xml | 2 +- 30 files changed, 2353 insertions(+), 2347 deletions(-) create mode 100644 src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java (limited to 'src') 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 index c839a15a..6dc251dc 100644 --- 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 @@ -22,6 +22,8 @@ import java.net.ConnectException; import javax.ws.rs.core.Response; +import org.apache.log4j.Logger; + import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Status; import com.sun.jersey.api.client.UniformInterfaceException; @@ -32,6 +34,7 @@ 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 static final Logger logger = Logger.getLogger(UsersClient.class); private String generateSecurityToken(String user, String password) { return new String(Base64.encode(user + ":" + password)); @@ -44,7 +47,7 @@ public class UsersClient extends AbstractClient { public void authenticate(String user, String password) { setSecurityToken(generateSecurityToken(user, password)); try { - fetchSubResource(user, String.class); + fetchSubResource(user, Status.class); } catch (RuntimeException e) { Throwable cause = e.getCause(); if(cause == null) { @@ -58,14 +61,16 @@ public class UsersClient extends AbstractClient { setSecurityToken(null); throw new GlusterRuntimeException("Invalid user id or password!"); } else { - // TODO: Log the exception - throw new GlusterRuntimeException("Exception during authentication: [" - + e1.getResponse().getStatus() + "]"); + String errMsg = "Exception during authentication: [" + e1.getResponse().getStatus() + "]"; + logger.error(errMsg); + throw new GlusterRuntimeException(errMsg); } } else if(cause instanceof ConnectException) { throw new GlusterRuntimeException("Couldn't connect to Gluster Management Gateway!"); } else { - throw new GlusterRuntimeException("Exception during authentication: [" + e.getMessage() + "]"); + String errMsg = "Exception during authentication: [" + e.getMessage() + "]"; + logger.error(errMsg); + throw new GlusterRuntimeException(errMsg); } } } @@ -80,20 +85,18 @@ public class UsersClient extends AbstractClient { } public static void main(String[] args) { -// UsersClient authClient = new UsersClient(); -// -// // authenticate user -// authClient.authenticate("gluster", "gluster"); -// -// // change password to gluster1 -// authClient.changePassword("gluster", "gluster", "gluster1"); -// -// // change it back to gluster -// authClient.changePassword("gluster", "gluster1", "gluster"); -// -// System.out.println("success"); - System.out.println(new String(Base64.encode("abcdefghijklmnopqrstuvwxyz"))); - System.out.println(new String(Base64.decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="))); + UsersClient authClient = new UsersClient(); + + // authenticate user + authClient.authenticate("gluster", "gluster"); + + // change password to gluster1 + authClient.changePassword("gluster", "gluster", "gluster1"); + + // change it back to gluster + authClient.changePassword("gluster", "gluster1", "gluster"); + + System.out.println("success"); } /* 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 index 4726fc36..765735fb 100644 --- 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 @@ -27,7 +27,7 @@ public class ClientConstants { public static final String SYS_PROP_SERVER_URL = "gluster.server.url"; public static final String DEFAULT_SERVER_URL = "https://localhost:8443/glustermg/linux.gtk.x86_64"; public static final String CONTEXT_ROOT = "glustermg"; - public static final String WEB_RESOURCE_BASE_PATH = "resources"; + public static final String REST_API_VERSION = "1.0"; // SSL related public static final String TRUSTED_KEYSTORE = "gmc-trusted.keystore"; 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 index 4f7ea64e..3f87fd27 100644 --- 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 @@ -9,7 +9,7 @@ import com.gluster.storage.management.client.constants.ClientConstants; public class ClientUtil { public static URI getServerBaseURI() { - return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.WEB_RESOURCE_BASE_PATH).build(); + return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.REST_API_VERSION).build(); } private static String getBaseURL() { diff --git a/src/com.gluster.storage.management.core/.classpath b/src/com.gluster.storage.management.core/.classpath index b41cbcdb..221aeec4 100644 --- a/src/com.gluster.storage.management.core/.classpath +++ b/src/com.gluster.storage.management.core/.classpath @@ -1,5 +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 index a32970c8..fae660fb 100644 --- a/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF +++ b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF @@ -9,5 +9,8 @@ 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.response, - com.gluster.storage.management.core.utils + com.gluster.storage.management.core.utils, + org.apache.log4j Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0" +Bundle-ClassPath: lib/log4j-1.2.16.jar, + . diff --git a/src/com.gluster.storage.management.core/build.properties b/src/com.gluster.storage.management.core/build.properties index 34d2e4d2..89d32a46 100644 --- a/src/com.gluster.storage.management.core/build.properties +++ b/src/com.gluster.storage.management.core/build.properties @@ -1,4 +1,7 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + lib/ +src.includes = lib/,\ + src/ diff --git a/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar b/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar new file mode 100644 index 00000000..3f9d8476 Binary files /dev/null and b/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar differ 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 index da92ca14..ed5d12f7 100644 --- 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 @@ -19,6 +19,7 @@ package com.gluster.storage.management.core.model; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; @XmlRootElement public class User { @@ -31,6 +32,8 @@ public class User { public void setUserId(String userId) { this.userId = userId; } + + @XmlTransient public String getPassword() { return password; } diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml index 4aaa3c9b..7c20d6c7 100644 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -30,12 +30,12 @@ - gluster-resources + gluster-resources-1.0 com.sun.jersey.spi.spring.container.servlet.SpringServlet com.sun.jersey.config.property.packages - com.gluster.storage.management.server.resources + com.gluster.storage.management.server.resources.v1_0 com.sun.jersey.spi.container.ResourceFilters @@ -44,8 +44,8 @@ 1 - gluster-resources - /resources/* + gluster-resources-1.0 + /1.0/* diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java deleted file mode 100644 index feef8b3e..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import java.net.URI; -import java.util.ArrayList; - -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.StreamingOutput; -import javax.ws.rs.core.UriInfo; - -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.response.VolumeListResponse; - -/** - * - */ -public class AbstractResource { - @Context - protected UriInfo uriInfo; - - /** - * Creates a response with HTTP status code of 201 (created) and sets the "location" header to the URI created using - * the given path relative to current path. - * - * @param relativePath - * relative path of the created resource - will be set in the "location" header of response. - * @return the {@link Response} object - */ - protected Response createdResponse(String relativePath) { - return Response.created(createRelatriveURI(relativePath)).build(); - } - - /** - * Creates a response with HTTP status code of 204 (no content) - * @return the {@link Response} object - */ - protected Response noContentResponse() { - return Response.noContent().build(); - } - - /** - * Creates a response with HTTP status code of 202 (accepted), also setting the location header to given location. - * This is typically done while triggering long running tasks - * - * @param locationURI - * URI to be appended to the base URI - * @return the {@link Response} object - */ - protected Response acceptedResponse(String locationURI) { - return Response.status(Status.ACCEPTED).location(createAbsoluteURI(locationURI)).build(); - } - - /** - * Creates a response with HTTP status code of 404 (not found), also setting the given message in the response body - * - * @param message - * Message to be set in the response body - * @return the {@link Response} object - */ - protected Response notFoundResponse(String message) { - return Response.status(Status.NOT_FOUND).type(MediaType.TEXT_HTML).entity(message).build(); - } - - /** - * Creates a new URI that is relative to the base URI of the application - * @param uriString URI String to be appended to the base URI - * @return newly created URI - */ - private URI createAbsoluteURI(String uriString) { - return uriInfo.getBaseUriBuilder().path(uriString).build(); - } - - /** - * Creates a response with HTTP status code of 204 (no content), also setting the location header to given location - * @param location path of the location to be set relative to current path - * @return the {@link Response} object - */ - protected Response noContentResponse(String location) { - return Response.noContent().location(createRelatriveURI(location)).build(); - } - - /** - * Creates a URI relative to current URI - * @param location path relative to current URI - * @return newly created URI - */ - protected URI createRelatriveURI(String location) { - return uriInfo.getAbsolutePathBuilder().path(location).build(); - } - - /** - * Creates a response with HTTP status code of 500 (internal server error) and sets the error message in the - * response body - * - * @param errMessage - * Error message to be set in the response body - * @return the {@link Response} object - */ - protected Response errorResponse(String errMessage) { - return Response.serverError().type(MediaType.TEXT_HTML).entity(errMessage).build(); - } - - /** - * Creates a response with HTTP status code of 400 (bad request) and sets the error message in the - * response body - * - * @param errMessage - * Error message to be set in the response body - * @return the {@link Response} object - */ - protected Response badRequestResponse(String errMessage) { - return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_HTML).entity(errMessage).build(); - } - - /** - * Creates a response with HTTP status code of 401 (unauthorized) - * - * @return the {@link Response} object - */ - protected Response unauthorizedResponse() { - return Response.status(Status.UNAUTHORIZED).build(); - } - - /** - * Creates an OK response and sets the entity in the response body. - * - * @param entity - * Entity to be set in the response body - * @param mediaType - * Media type to be set on the response - * @return the {@link Response} object - */ - protected Response okResponse(Object entity, String mediaType) { - return Response.ok(entity).type(mediaType).build(); - } - - /** - * Creates an OK response without any entity in the response body. - * - * @param mediaType - * Media type to be set on the response - * @return the {@link Response} object - */ - protected Response okResponse(String mediaType) { - return Response.ok().type(mediaType).build(); - } - - /** - * Creates a streaming output response and sets the given streaming output in the response. Typically used for - * "download" requests - * - * @param entity - * Entity to be set in the response body - * @param mediaType - * Media type to be set on the response - * @return the {@link Response} object - */ - protected Response streamingOutputResponse(StreamingOutput output) { - return Response.ok(output).type(MediaType.APPLICATION_OCTET_STREAM).build(); - } -} 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 deleted file mode 100644 index dd6e2804..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * AbstractServersResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.server.resources; - -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.ServerUtil; -import com.sun.jersey.api.core.InjectParam; - -/** - * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". - */ -public class AbstractServersResource extends AbstractResource { - @InjectParam - protected ServerUtil serverUtil; - - @InjectParam - protected GlusterUtil glusterUtil; - - // TODO: Remove this class! -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java deleted file mode 100644 index 3c70beec..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.*; - -import java.util.ArrayList; -import java.util.List; - -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 com.gluster.storage.management.core.model.AlertListResponse; -import com.gluster.storage.management.core.model.Alert; - -@Component -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_ALERTS) -public class AlertsResource { - - @GET - @Produces(MediaType.APPLICATION_XML) - public AlertListResponse getAlerts() { - - List alerts = new ArrayList(); - - // TODO To implement the following dummy alerts - // Alert #1 - Alert alert = new Alert(); - alert.setId("0001"); - alert.setReference("Server1"); // Server - alert.setType(Alert.ALERT_TYPES.CPU_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #2 - alert = new Alert(); - alert.setId("0002"); - alert.setReference("Server2"); // server:Disk - brick - alert.setType(Alert.ALERT_TYPES.MEMORY_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #3 - alert = new Alert(); - alert.setId("0003"); - alert.setReference("server1:sda1"); // Disk name - alert.setType(Alert.ALERT_TYPES.DISK_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in disk [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #4 - alert = new Alert(); - alert.setId("0004"); - alert.setReference("Volume3:server2:sda1"); // volume:[Disk name] - alert.setType(Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in volume [" + alert.getReference().split(":")[0] - + "] disk [" + alert.getReference().split(":")[1] + ":" + alert.getReference().split(":")[2] + "]"); - alerts.add(alert); - - // Alert #5 - alert = new Alert(); - alert.setId("0005"); - alert.setReference("Server2"); // Server name - alert.setType(Alert.ALERT_TYPES.OFFLINE_SERVERS_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " [" + alert.getReference() + "]"); - alerts.add(alert); - - return new AlertListResponse(alerts); - - } - - public static void main(String[] args) { - /* - * // Unit test code AlertsResource alertResource = new AlertsResource(); AlertsListResponse alertResponse = - * alertResource.getAlerts(); List alerts = alertResponse.getAlerts(); for (Alert alert: alerts) { - * System.out.println(alert.getMessage()); } - */ - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java deleted file mode 100644 index 4c834973..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; - -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.DELETE; -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 javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.response.ClusterNameListResponse; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.services.ClusterService; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -/** - * - */ -@Component -@Singleton -@Path(RESOURCE_PATH_CLUSTERS) -public class ClustersResource extends AbstractResource { - @InjectParam - private ClusterService clusterService; - - @GET - @Produces(MediaType.APPLICATION_XML) - public ClusterNameListResponse getClusters() { - List clusters = clusterService.getAllClusters(); - List clusterList = new ArrayList(); - for (ClusterInfo cluster : clusters) { - clusterList.add(cluster.getName()); - } - return new ClusterNameListResponse(clusterList); - } - - @POST - public Response createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - return badRequestResponse("Cluster [" + clusterName + "] already exists!"); - } - - try { - clusterService.createCluster(clusterName); - return createdResponse(clusterName); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to save cluster [" + clusterName + "]: [" + e.getMessage() - + "]"); - } - } - - @PUT - public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, - @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(knownServer == null || knownServer.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - return badRequestResponse("Cluster [" + clusterName + "] already exists!"); - } - - ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); - if(mappedCluster != null) { - return badRequestResponse("Server [" + knownServer + "] is already present in cluster [" - + mappedCluster.getName() + "]!"); - } - - try { - clusterService.registerCluster(clusterName, knownServer); - return noContentResponse(clusterName); - } catch(Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to register cluster [" + clusterName + "] using server [" - + knownServer + "]: [" + e.getMessage() + "]"); - } - } - - @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") - @DELETE - public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if(cluster == null) { - return badRequestResponse("Cluster [" + clusterName + "] does not exist!"); - } - - try { - clusterService.unregisterCluster(cluster); - return noContentResponse(); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to unregister cluster [" + clusterName + "]: [" - + e.getMessage() + "]"); - } - } -} 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 deleted file mode 100644 index 283ab147..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DETAILS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_DISCOVERED_SERVERS; - -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 javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.response.ServerListResponse; -import com.gluster.storage.management.core.response.ServerNameListResponse; -import com.sun.jersey.spi.resource.Singleton; - -@Component -@Singleton -@Path(RESOURCE_PATH_DISCOVERED_SERVERS) -public class DiscoveredServersResource extends AbstractServersResource { - private List discoveredServerNames = new ArrayList(); - - public List getDiscoveredServerNames() { - return discoveredServerNames; - } - - public void setDiscoveredServerNames(List discoveredServerNames) { - synchronized (discoveredServerNames) { - this.discoveredServerNames = discoveredServerNames; - } - } - - public void removeDiscoveredServer(String serverName) { - discoveredServerNames.remove(serverName); - } - - public void addDiscoveredServer(String serverName) { - discoveredServerNames.add(serverName); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getDiscoveredServersXML(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getDiscoveredServersResponse(details, MediaType.APPLICATION_XML); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getDiscoveredServersJSON(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getDiscoveredServersResponse(details, MediaType.APPLICATION_JSON); - } - - private Response getDiscoveredServersResponse(Boolean details, String mediaType) { - if(details != null && details == true) { - try { - List discoveredServers = getDiscoveredServerDetails(); - return okResponse(new ServerListResponse(discoveredServers), mediaType); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - } else { - return okResponse(new ServerNameListResponse(getDiscoveredServerNames()), mediaType); - } - } - - private List getDiscoveredServerDetails() { - List discoveredServers = new ArrayList(); - for (String serverName : getDiscoveredServerNames()) { - try { - discoveredServers.add(getDiscoveredServer(serverName)); - } catch(Exception e) { - // TODO: Log the exception - // continue with next discovered server - } - } - return discoveredServers; - } - - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getDiscoveredServerXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_XML); - } - - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getDiscoveredServerJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_JSON); - } - - private Response getDiscoveredServerResponse(String serverName, String mediaType) { - if(serverName == null || serverName.isEmpty()) { - return badRequestResponse("Server name must not be empty!"); - } - try { - return okResponse(getDiscoveredServer(serverName), mediaType); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse(e.getMessage()); - } - } - - private Server getDiscoveredServer(String serverName) { - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - return server; - } - - public static void main(String[] args) { - Response response = (Response)new DiscoveredServersResource().getDiscoveredServersXML(false); - System.out.println(response.getEntity()); - } -} 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 deleted file mode 100644 index 1f4b15de..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java +++ /dev/null @@ -1,444 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_DISK_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DISKS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_SERVERS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; - -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.DELETE; -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 javax.ws.rs.core.Response; - -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.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; -import com.gluster.storage.management.core.response.GlusterServerListResponse; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.data.ServerInfo; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.tasks.InitializeDiskTask; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -@Component -@Singleton -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_SERVERS) -public class GlusterServersResource extends AbstractServersResource { - - public static final String HOSTNAMETAG = "hostname:"; - - @InjectParam - private DiscoveredServersResource discoveredServersResource; - - @InjectParam - private TasksResource taskResource; - - @Autowired - private ClusterService clusterService; - - @Autowired - private SshUtil sshUtil; - - protected void fetchServerDetails(GlusterServer server) { - try { - server.setStatus(SERVER_STATUS.ONLINE); - serverUtil.fetchServerDetails(server); - } catch (ConnectionException e) { - server.setStatus(SERVER_STATUS.OFFLINE); - } - } - - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getGlusterServers(clusterName, MediaType.APPLICATION_JSON); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getGlusterServers(clusterName, MediaType.APPLICATION_XML); - } - - public Response getGlusterServers(String clusterName, String mediaType) { - List glusterServers = new ArrayList(); - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (cluster.getServers().size() == 0) { - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - return errorResponse("Couldn't fetch details for server(s): " + errMsg); - } - - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } - - public String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { - String errMsg = ""; - - for (GlusterServer server : glusterServers) { - if (server.getStatus() == SERVER_STATUS.ONLINE && !server.getName().equals(onlineServer.getName())) { - try { - fetchServerDetails(server); - } catch (Exception e) { - errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; - } - } - } - return errMsg; - } - - public List getGlusterServers(String clusterName, GlusterServer onlineServer) { - List glusterServers; - try { - glusterServers = glusterUtil.getGlusterServers(onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - glusterServers = glusterUtil.getGlusterServers(onlineServer); - } - return glusterServers; - } - - @GET - @Path("{serverName}") - @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_XML); - } - - @GET - @Path("{serverName}") - @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_JSON); - } - - private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) { - try { - return okResponse(getGlusterServer(clusterName, serverName), mediaType); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - private GlusterServer getGlusterServer(String clusterName, String serverName) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterRuntimeException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterRuntimeException("Server name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - GlusterServer server = null; - try { - server = glusterUtil.getGlusterServer(onlineServer, serverName); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - server = glusterUtil.getGlusterServer(onlineServer, serverName); - } - - if (server.isOnline()) { - fetchServerDetails(server); - } - return server; - } - - private void performAddServer(String clusterName, String serverName) { - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.addServer(onlineServer.getName(), serverName); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - glusterUtil.addServer(serverName, onlineServer.getName()); - } - } - - @POST - public Response addServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @FormParam(FORM_PARAM_SERVER_NAME) String serverName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(serverName); - if (!publicKeyInstalled && !sshUtil.hasDefaultPassword(serverName)) { - // public key not installed, default password doesn't work. return with error. - return errorResponse("Gluster Management Gateway uses the default password to set up keys on the server." - + CoreConstants.NEWLINE + "However it seems that the password on server [" + serverName - + "] has been changed manually." + CoreConstants.NEWLINE - + "Please reset it back to the standard default password and try again."); - } - - List servers = cluster.getServers(); - if (servers != null && !servers.isEmpty()) { - // cluster has at least one existing server, so that peer probe can be performed - try { - performAddServer(clusterName, serverName); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } else { - // this is the first server to be added to the cluster, which means no - // gluster CLI operation required. just add it to the cluster-server mapping - } - - try { - // add the cluster-server mapping - clusterService.mapServerToCluster(clusterName, serverName); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - - // since the server is added to a cluster, it should not more be considered as a - // discovered server available to other clusters - discoveredServersResource.removeDiscoveredServer(serverName); - - if (!publicKeyInstalled) { - try { - // install public key (this will also disable password based ssh login) - sshUtil.installPublicKey(serverName); - } catch (Exception e) { - return errorResponse("Public key could not be installed on [" + serverName + "]! Error: [" - + e.getMessage() + "]"); - } - } - - return createdResponse(serverName); - } - - @DELETE - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - public Response removeServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - return badRequestResponse("Server name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - List servers = cluster.getServers(); - if (servers == null || servers.isEmpty() || !containsServer(servers, serverName)) { - return badRequestResponse("Server [" + serverName + "] is not attached to cluster [" + clusterName + "]!"); - } - - if (servers.size() == 1) { - // Only one server mapped to the cluster, no "peer detach" required. - // remove the cached online server for this cluster if present - clusterService.removeOnlineServer(clusterName); - } else { - try { - removeServerFromCluster(clusterName, serverName); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - return noContentResponse(); - } - - private void removeServerFromCluster(String clusterName, String serverName) { - // get an online server that is not same as the server being removed - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName, serverName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.removeServer(onlineServer.getName(), serverName); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName, serverName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - glusterUtil.removeServer(onlineServer.getName(), serverName); - } - - if (onlineServer.getName().equals(serverName)) { - // since the cached server has been removed from the cluster, remove it from the cache - clusterService.removeOnlineServer(clusterName); - } - - clusterService.unmapServerFromCluster(clusterName, serverName); - - // since the server is removed from the cluster, it is now available to be added to other clusters. - // Hence add it back to the discovered servers list. - discoveredServersResource.addDiscoveredServer(serverName); - } - - private boolean containsServer(List servers, String serverName) { - for (ServerInfo server : servers) { - if (server.getName().toUpperCase().equals(serverName.toUpperCase())) { - return true; - } - } - return false; - } - - @PUT - @Produces(MediaType.APPLICATION_XML) - @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_DISKS + "/{" + PATH_PARAM_DISK_NAME + "}") - public Response initializeDisk(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName, @PathParam(PATH_PARAM_DISK_NAME) String diskName) { - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - return badRequestResponse("Server name must not be empty!"); - } - - if (diskName == null || diskName.isEmpty()) { - return badRequestResponse("Disk name must not be empty!"); - } - - InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName); - try { - initializeTask.start(); - taskResource.addTask(initializeTask); - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + initializeTask.getId()); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - private void setGlusterUtil(GlusterUtil glusterUtil) { - this.glusterUtil = glusterUtil; - } - - public static void main(String[] args) { - GlusterServersResource glusterServersResource = new GlusterServersResource(); - GlusterUtil glusterUtil = new GlusterUtil(); - glusterUtil.setSshUtil(new SshUtil()); - glusterServersResource.setGlusterUtil(glusterUtil); - // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); - - // To add a server - // GlusterServerResponse response = glusterServersResource.addServer("my-server"); - // System.out.println(response.getData().getName()); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java deleted file mode 100644 index 53122f11..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * TaskResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_TASK_ID; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.DELETE; -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.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.response.TaskInfoListResponse; -import com.gluster.storage.management.server.tasks.Task; -import com.sun.jersey.spi.resource.Singleton; - -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) -@Singleton -public class TasksResource extends AbstractResource { - private Map tasksMap = new HashMap(); - - public TasksResource() { - } - - public void addTask(Task task) { - tasksMap.put(task.getId(), task); - } - - public void removeTask(Task task) { - tasksMap.remove(task.getId()); - } - - public List getAllTasksInfo() { - List allTasksInfo = new ArrayList(); - for (Map.Entry entry : tasksMap.entrySet()) { - checkTaskStatus(entry.getKey()); - allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status - } - return allTasksInfo; - } - - public Task getTask(String taskId) { - for (Map.Entry entry : tasksMap.entrySet()) { - if (entry.getValue().getId().equals(taskId)) { - return entry.getValue(); - } - } - return null; - } - - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getTasks() { - try { - return okResponse(new TaskInfoListResponse(getAllTasksInfo()), MediaType.APPLICATION_XML); - } catch (GlusterRuntimeException e) { - return errorResponse(e.getMessage()); - } - } - - @GET - @Path("/{" + PATH_PARAM_TASK_ID + "}") - @Produces(MediaType.APPLICATION_XML) - public Response getTaskStatus( @PathParam(PATH_PARAM_TASK_ID) String taskId) { - try { - Task task = checkTaskStatus(taskId); - return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML); - } catch (GlusterRuntimeException e) { - return errorResponse(e.getMessage()); - } - } - - private Task checkTaskStatus(String taskId) { - Task task = getTask(taskId); - task.getTaskInfo().setStatus(task.checkStatus()); - return task; - } - - @PUT - @Path("/{" + PATH_PARAM_TASK_ID + "}") - @Produces(MediaType.APPLICATION_XML) - public Response performTask(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_TASK_ID) String taskId, @FormParam(FORM_PARAM_OPERATION) String taskOperation) { - Task task = getTask(taskId); - - try { - if (taskOperation.equals(RESTConstants.TASK_RESUME)) { - task.resume(); - } else if (taskOperation.equals(RESTConstants.TASK_PAUSE)) { - task.pause(); - } else if (taskOperation.equals(RESTConstants.TASK_STOP)) { - task.stop(); - } else if (taskOperation.equals(RESTConstants.TASK_COMMIT)) { - task.commit(); - } - return (Response) noContentResponse(); - } catch(GlusterValidationException ve) { - return badRequestResponse(ve.getMessage()); - } catch (GlusterRuntimeException e) { - return errorResponse(e.getMessage()); - } - } - - @DELETE - @Path("/{" + PATH_PARAM_TASK_ID + "}") - @Produces(MediaType.APPLICATION_XML) - public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, - @QueryParam(FORM_PARAM_OPERATION) String taskOperation) { - Task task = getTask(taskId); - if (task == null) { - return notFoundResponse("Task [" + taskId + "] not found!"); - } - - if(taskOperation == null || taskOperation.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_OPERATION + "] is missing in request!"); - } - - if(!taskOperation.equals(RESTConstants.TASK_STOP) && !taskOperation.equals(RESTConstants.TASK_DELETE)) { - return badRequestResponse("Invalid value [" + taskOperation + "] for parameter [" + FORM_PARAM_OPERATION - + "]"); - } - - try { - if (taskOperation.equals(RESTConstants.TASK_STOP)) { - task.stop(); - // On successfully stopping the task, we can delete (forget) it as it is no more useful - taskOperation = RESTConstants.TASK_DELETE; - } - - if (taskOperation.equals(RESTConstants.TASK_DELETE)) { - removeTask(task); - } - - return noContentResponse(); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } -} 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 deleted file mode 100644 index 0ccb4263..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_USER; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_USERS; - -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 javax.ws.rs.core.Response; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.encoding.PasswordEncoder; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.provisioning.JdbcUserDetailsManager; -import org.springframework.stereotype.Component; - -import com.sun.jersey.spi.resource.Singleton; - -@Singleton -@Component -@Path(RESOURCE_PATH_USERS) -public class UsersResource extends AbstractResource { - @Autowired - private JdbcUserDetailsManager jdbcUserService; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Path("{" + PATH_PARAM_USER + "}") - @GET - @Produces(MediaType.APPLICATION_XML) - public Response authenticateXML(@PathParam("user") String user) { - // success only if the user passed in query is same as the one passed in security header - // spring security would have already authenticated the user credentials - return getAuthenticationResponse(user, MediaType.APPLICATION_XML); - } - - @Path("{" + PATH_PARAM_USER + "}") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response authenticateJSON(@PathParam("user") String user) { - // success only if the user passed in query is same as the one passed in security header - // spring security would have already authenticated the user credentials - return getAuthenticationResponse(user, MediaType.APPLICATION_JSON); - } - - public Response getAuthenticationResponse(String user, String mediaType) { - return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? okResponse(mediaType) - : unauthorizedResponse()); - } - - @Path("{" + PATH_PARAM_USER + "}") - @PUT - public Response changePassword(@FormParam("oldpassword") String oldPassword, - @FormParam("newpassword") String newPassword) { - try { - jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); - } catch (Exception ex) { - // TODO: Log the exception - ex.printStackTrace(); - return errorResponse("Could not change password. Error: [" + ex.getMessage() + "]"); - } - return noContentResponse(); - } -} 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 deleted file mode 100644 index 7ccd2f3c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ /dev/null @@ -1,1025 +0,0 @@ -/** - * VolumesResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * This file is part of Gluster Management Console. - * - * Gluster Management Console is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Gluster Management Console is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License - * for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * . - */ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_ACCESS_PROTOCOLS; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_AUTO_COMMIT; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_BRICKS; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FIX_LAYOUT; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FORCED_DATA_MIGRATE; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_MIGRATE_DATA; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_KEY; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_VALUE; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_REPLICA_COUNT; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SOURCE; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_STRIPE_COUNT; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TARGET; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TRANSPORT_TYPE; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_OPTIONS; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_TYPE; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICKS; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICK_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DOWNLOAD; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_FROM_TIMESTAMP; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LOG_SEVERITY; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TO_TIMESTAMP; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_BRICKS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DEFAULT_OPTIONS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DOWNLOAD; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_LOGS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_OPTIONS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_VOLUMES; -import static com.gluster.storage.management.core.constants.RESTConstants.TASK_START; -import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -import javax.ws.rs.DELETE; -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.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; -import com.gluster.storage.management.core.model.VolumeLogMessage; -import com.gluster.storage.management.core.response.GenericResponse; -import com.gluster.storage.management.core.response.LogMessageListResponse; -import com.gluster.storage.management.core.response.VolumeListResponse; -import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse; -import com.gluster.storage.management.core.utils.DateUtil; -import com.gluster.storage.management.core.utils.FileUtil; -import com.gluster.storage.management.core.utils.ProcessUtil; -import com.gluster.storage.management.server.constants.VolumeOptionsDefaults; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.tasks.MigrateBrickTask; -import com.gluster.storage.management.server.tasks.RebalanceVolumeTask; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.ServerUtil; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -@Singleton -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_VOLUMES) -public class VolumesResource extends AbstractResource { - private static final String VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; - private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; - - @InjectParam - private ServerUtil serverUtil; - - @InjectParam - private GlusterUtil glusterUtil; - - @InjectParam - private ClusterService clusterService; - - @InjectParam - private VolumeOptionsDefaults volumeOptionsDefaults; - - @InjectParam - private TasksResource taskResource; - - @GET - @Produces({MediaType.APPLICATION_XML}) - public Response getVolumesXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getVolumes(clusterName, MediaType.APPLICATION_XML); - } - - @GET - @Produces({MediaType.APPLICATION_JSON}) - public Response getVolumesJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - return getVolumes(clusterName, MediaType.APPLICATION_JSON); - } - - public Response getVolumes(String clusterName, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if(cluster.getServers().size() == 0) { - // no server added yet. return an empty array. - return okResponse(new VolumeListResponse(), mediaType); - } - - return okResponse(getVolumes(clusterName), mediaType); - } - - public VolumeListResponse getVolumes(String clusterName) { - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return new VolumeListResponse(new ArrayList()); - } - - try { - return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return new VolumeListResponse(new ArrayList()); - } - - return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); - } - } - - @POST - @Produces(MediaType.APPLICATION_XML) - public Response createVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @FormParam(FORM_PARAM_VOLUME_NAME) String volumeName, - @FormParam(FORM_PARAM_VOLUME_TYPE) String volumeType, @FormParam(FORM_PARAM_TRANSPORT_TYPE) String transportType, - @FormParam(FORM_PARAM_REPLICA_COUNT) Integer replicaCount, @FormParam(FORM_PARAM_STRIPE_COUNT) Integer stripeCount, - @FormParam(FORM_PARAM_BRICKS) String bricks, @FormParam(FORM_PARAM_ACCESS_PROTOCOLS) String accessProtocols, - @FormParam(FORM_PARAM_VOLUME_OPTIONS) String options) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - String missingParam = checkMissingParamsForCreateVolume(volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); - if(missingParam != null) { - return badRequestResponse("Parameter [" + missingParam + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && replicaCount <= 0) { - return badRequestResponse("Replica count must be a positive integer"); - } - - if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_STRIPE) && stripeCount <= 0) { - return badRequestResponse("Stripe count must be a positive integer"); - } - - try { - performCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, - options); - return createdResponse(volumeName); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - public void performCreateVolume(String clusterName, String volumeName, String volumeType, String transportType, Integer replicaCount, - Integer stripeCount, String bricks, String accessProtocols, String options) { - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); - } - } - - /** - * Returns name of the missing parameter if any. If all parameters are present, - * @param volumeName - * @param volumeType - * @param transportType - * @param replicaCount - * @param stripeCount - * @param bricks - * @param accessProtocols - * @param options - * @return - */ - private String checkMissingParamsForCreateVolume(String volumeName, String volumeType, - String transportType, Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, - String options) { - - return (volumeName == null || volumeName.isEmpty()) ? FORM_PARAM_VOLUME_NAME : - (volumeType == null || volumeType.isEmpty()) ? FORM_PARAM_VOLUME_TYPE : - (transportType == null || transportType.isEmpty()) ? FORM_PARAM_TRANSPORT_TYPE : - (replicaCount == null) ? FORM_PARAM_REPLICA_COUNT : - (stripeCount == null) ? FORM_PARAM_STRIPE_COUNT : - (bricks == null || bricks.isEmpty()) ? FORM_PARAM_BRICKS : - (accessProtocols == null || accessProtocols.isEmpty()) ? FORM_PARAM_ACCESS_PROTOCOLS : - (options == null || options.isEmpty()) ? FORM_PARAM_VOLUME_OPTIONS : - null; - } - - @GET - @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - @Produces(MediaType.APPLICATION_XML) - public Response getVolumeXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { - return getVolume(clusterName, volumeName, MediaType.APPLICATION_XML); - } - - @GET - @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - @Produces(MediaType.APPLICATION_JSON) - public Response getVolumeJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { - return getVolume(clusterName, volumeName, MediaType.APPLICATION_JSON); - } - - private Response getVolume(String clusterName, String volumeName, String mediaType) { - Volume volume = null; - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - try { - volume = getVolume(clusterName, volumeName); - return okResponse(volume, mediaType); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - } - - private Volume getVolume(String clusterName, String volumeName) { - Volume volume; - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); - } - return volume; - } - - @PUT - @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - public Response performOperation(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_OPERATION) String operation, - @FormParam(FORM_PARAM_FIX_LAYOUT) Boolean isFixLayout, - @FormParam(FORM_PARAM_MIGRATE_DATA) Boolean isMigrateData, - @FormParam(FORM_PARAM_FORCED_DATA_MIGRATE) Boolean isForcedDataMigrate) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - try { - if (operation.equals(RESTConstants.TASK_REBALANCE_START)) { - String taskId = rebalanceStart(clusterName, volumeName, isFixLayout, isMigrateData, isForcedDataMigrate); - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS - + "/" + taskId); - } else if (operation.equals(RESTConstants.TASK_REBALANCE_STOP)) { - rebalanceStop(clusterName, volumeName); - } else { - performVolumeOperation(clusterName, volumeName, operation); - } - return noContentResponse(); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - } - - private void performVolumeOperation(String clusterName, String volumeName, String operation) { - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - try { - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - performOperation(volumeName, operation, onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - performOperation(volumeName, operation, onlineServer); - } - } - - private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { - if (operation.equals(TASK_START)) { - return glusterUtil.startVolume(volumeName, onlineServer.getName()); - } else if (operation.equals(TASK_STOP)) { - return glusterUtil.stopVolume(volumeName, onlineServer.getName()); - } else { - return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); - } - } - - @DELETE - @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - public Response deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, - @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (deleteFlag == null) { - deleteFlag = false; - } - - Volume volume = null; - try { - volume = getVolume(clusterName, volumeName); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse(e.getMessage()); - } - - List bricks = volume.getBricks(); - Status status = glusterUtil.deleteVolume(volumeName, clusterService.getOnlineServer(clusterName) - .getName()); - if(!status.isSuccess()) { - return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + status); - } - - try { - postDelete(volumeName, bricks, deleteFlag); - } catch(Exception e) { - return errorResponse("Volume [" + volumeName - + "] deleted from cluster, however following errors happened: " + CoreConstants.NEWLINE - + e.getMessage()); - } - - return noContentResponse(); - } - - @DELETE - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Response removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICKS) String bricks, - @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { - List brickList = Arrays.asList(bricks.split(",")); // Convert from comma separated string (query - // parameter) - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (bricks == null || bricks.isEmpty()) { - return badRequestResponse("Parameter [" + QUERY_PARAM_BRICKS + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if(deleteFlag == null) { - deleteFlag = false; - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - removeBricks(clusterName, volumeName, brickList, onlineServer); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - - try { - cleanupDirectories(brickList, volumeName, brickList.size(), deleteFlag); - } catch(Exception e) { - // append cleanup error to prepare brick error - return errorResponse(e.getMessage()); - } - - return noContentResponse(); - } - - public void removeBricks(String clusterName, String volumeName, List brickList, GlusterServer onlineServer) { - try { - glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } - } - - @SuppressWarnings("rawtypes") - private void cleanupDirectories(List bricks, String volumeName, int maxIndex, boolean deleteFlag) { - Status result; - String errors = ""; - for (int i = 0; i < maxIndex; i++) { - String[] brickInfo = bricks.get(i).split(":"); - String serverName = brickInfo[0]; - String brickDirectory = brickInfo[1]; - - String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " - + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); - if (response instanceof GenericResponse) { - result = ((GenericResponse) response).getStatus(); - if (!result.isSuccess()) { - errors += "[" + mountPoint + "][" + volumeName + "] => " + result - + CoreConstants.NEWLINE; - } - } else { - Status errStatus = (Status) response; - errors += "[" + mountPoint + "][" + volumeName + "] => " + errStatus + CoreConstants.NEWLINE; - } - } - if(!errors.trim().isEmpty()) { - throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); - } - } - - private void postDelete(String volumeName, List bricks, boolean deleteFlag) { - Status result; - for (Brick brick : bricks) { - String brickDirectory = brick.getBrickDirectory(); - String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - - result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT - + " " + mountPoint + " " + volumeName + (deleteFlag ? " -d" : ""), Status.class); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Error in post-delete operation of volume [" + volumeName + "]: " - + result); - } - } - } - - @POST - @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - public Response setOption(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, - @FormParam(RESTConstants.FORM_PARAM_OPTION_KEY) String key, - @FormParam(RESTConstants.FORM_PARAM_OPTION_VALUE) String value) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if(volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if(key == null || key.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_KEY + "] is missing in request!"); - } - - if(value == null || value.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_VALUE + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - - return createdResponse(key); - } - - @PUT - @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - public Response resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if(volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.resetOptions(volumeName, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.resetOptions(volumeName, onlineServer.getName()); - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - - return noContentResponse(); - } - - @GET - @Path(RESOURCE_DEFAULT_OPTIONS) - @Produces(MediaType.APPLICATION_XML) - public VolumeOptionInfoListResponse getDefaultOptionsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - // TODO: Fetch all volume options with their default values from GlusterFS - // whenever such a CLI command is made available in GlusterFS - return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); - } - - @GET - @Path(RESOURCE_DEFAULT_OPTIONS) - @Produces(MediaType.APPLICATION_JSON) - public VolumeOptionInfoListResponse getDefaultOptionsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - // TODO: Fetch all volume options with their default values from GlusterFS - // whenever such a CLI command is made available in GlusterFS - return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); - } - - private List getBrickLogs(Volume volume, Brick brick, Integer lineCount) - throws GlusterRuntimeException { - String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); - String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); - String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; - - // Usage: get_volume_disk_log.py - Object responseObj = serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " " - + logFilePath + " " + lineCount, LogMessageListResponse.class); - - LogMessageListResponse response = null; - if (responseObj instanceof LogMessageListResponse) { - response = (LogMessageListResponse) responseObj; - // populate disk and trim other fields - List logMessages = response.getLogMessages(); - for (VolumeLogMessage logMessage : logMessages) { - logMessage.setBrickDirectory(brick.getBrickDirectory()); - } - return logMessages; - } else { - Status status = (Status) responseObj; - throw new GlusterRuntimeException(status.toString()); - } - } - - @GET - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS + "/" + RESOURCE_DOWNLOAD) - public Response downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) final String volumeName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - try { - final Volume volume = getVolume(clusterName, volumeName); - StreamingOutput output = new StreamingOutput() { - - @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - try { - File archiveFile = new File(downloadLogs(volume)); - output.write(FileUtil.readFileAsByteArray(archiveFile)); - archiveFile.delete(); - } catch (Exception e) { - // TODO: Log the exception - e.printStackTrace(); - String errMsg = "Exception while downloading/archiving volume log files : " + e.getMessage(); - output.write(errMsg.getBytes()); - } - } - }; - return streamingOutputResponse(output); - } catch(Exception e) { - return errorResponse("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]!"); - } - } - - private String downloadLogs(Volume volume) { - // create temporary directory - File tempDir = FileUtil.createTempDir(); - String tempDirPath = tempDir.getPath(); - - for (Brick brick : volume.getBricks()) { - String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), - brick.getServerName()); - String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); - String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; - - serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); - - String fetchedLogFile = tempDirPath + File.separator + logFileName; - // append log file name with server name so that log files don't overwrite each other - // in cases where the brick log file names are same on multiple servers - String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; - - FileUtil.renameFile(fetchedLogFile, localLogFile); - } - - String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; - new ProcessUtil().executeCommand("tar", "czvf", gzipPath, "-C", tempDir.getParent(), tempDir.getName()); - - // delete the temp directory - FileUtil.recursiveDelete(tempDir); - - return gzipPath; - } - - @GET - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) - @Produces(MediaType.APPLICATION_XML) - public Response getLogsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, - @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, - @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, - @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, - @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { - return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_XML); - } - - @GET - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) - @Produces(MediaType.APPLICATION_JSON) - public Response getLogsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, - @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, - @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, - @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, - @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { - return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_JSON); - } - - public Response getLogs(String clusterName, String volumeName, String brickName, String severity, - String fromTimestamp, String toTimestamp, Integer lineCount, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - List logMessages = null; - Volume volume = null; - try { - volume = (Volume) getVolume(clusterName, volumeName); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - - if (brickName == null || brickName.isEmpty() || brickName.equals(CoreConstants.ALL)) { - logMessages = getLogsForAllBricks(volume, lineCount); - } else { - // fetch logs for given brick of the volume - for (Brick brick : volume.getBricks()) { - if (brick.getQualifiedName().equals(brickName)) { - logMessages = getBrickLogs(volume, brick, lineCount); - break; - } - } - } - - filterLogsBySeverity(logMessages, severity); - filterLogsByTime(logMessages, fromTimestamp, toTimestamp); - - return okResponse(new LogMessageListResponse(logMessages), mediaType); - } - - private void filterLogsByTime(List logMessages, String fromTimestamp, String toTimestamp) { - Date fromTime = null, toTime = null; - - if (fromTimestamp != null && !fromTimestamp.isEmpty()) { - fromTime = DateUtil.stringToDate(fromTimestamp); - } - - if (toTimestamp != null && !toTimestamp.isEmpty()) { - toTime = DateUtil.stringToDate(toTimestamp); - } - - List messagesToRemove = new ArrayList(); - for (VolumeLogMessage logMessage : logMessages) { - Date logTimestamp = logMessage.getTimestamp(); - if (fromTime != null && logTimestamp.before(fromTime)) { - messagesToRemove.add(logMessage); - continue; - } - - if (toTime != null && logTimestamp.after(toTime)) { - messagesToRemove.add(logMessage); - } - } - logMessages.removeAll(messagesToRemove); - } - - private void filterLogsBySeverity(List logMessages, String severity) { - if (severity == null || severity.isEmpty()) { - return; - } - - List messagesToRemove = new ArrayList(); - for (VolumeLogMessage logMessage : logMessages) { - if (!logMessage.getSeverity().equals(severity)) { - messagesToRemove.add(logMessage); - } - } - logMessages.removeAll(messagesToRemove); - } - - private List getLogsForAllBricks(Volume volume, Integer lineCount) { - List logMessages; - logMessages = new ArrayList(); - // fetch logs for every brick of the volume - for (Brick brick : volume.getBricks()) { - logMessages.addAll(getBrickLogs(volume, brick, lineCount)); - } - - // Sort the log messages based on log timestamp - Collections.sort(logMessages, new Comparator() { - @Override - public int compare(VolumeLogMessage message1, VolumeLogMessage message2) { - return message1.getTimestamp().compareTo(message2.getTimestamp()); - } - }); - - return logMessages; - } - - @POST - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Response addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_BRICKS) String bricks) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (bricks == null || bricks.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_BRICKS + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - List brickList = Arrays.asList(bricks.split(",")); - try { - glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - - return createdResponse(""); - } - - @PUT - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Response migrateBrick(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_SOURCE) String fromBrick, - @FormParam(FORM_PARAM_TARGET) String toBrick, @FormParam(FORM_PARAM_AUTO_COMMIT) Boolean autoCommit) { - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (fromBrick == null || fromBrick.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_SOURCE + "] is missing in request!"); - } - - if (toBrick == null || toBrick.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_TARGET + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - if(autoCommit == null) { - autoCommit = false; - } - - String taskId = null; - try { - taskId = migrateBrickStart(clusterName, volumeName, fromBrick, toBrick, autoCommit); - }catch(Exception e) { - return errorResponse(e.getMessage()); - } - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + taskId); - } - - private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, - Boolean autoCommit) { - MigrateBrickTask migrateDiskTask = new MigrateBrickTask(clusterService, clusterName, volumeName, fromBrick, - toBrick); - migrateDiskTask.setAutoCommit(autoCommit); - migrateDiskTask.start(); - taskResource.addTask(migrateDiskTask); - return migrateDiskTask.getTaskInfo().getName(); // Return Task ID - } - - private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, - Boolean isForcedDataMigrate) { - String layout = ""; - if (isForcedDataMigrate) { - layout = "forced-data-migrate"; - } else if (isMigrateData) { - layout = "migrate-data"; - } else if (isFixLayout) { - layout = "fix-layout"; - } - - return rebalanceStart(clusterName, volumeName, layout); - } - - private String rebalanceStart(String clusterName, String volumeName, String layout) { - RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName); - rebalanceTask.setLayout(layout); - rebalanceTask.start(); - taskResource.addTask(rebalanceTask); - return rebalanceTask.getId(); - } - - public void rebalanceStop(String clusterName, String volumeName) { - // TODO: arrive at the task id and fetch it - String taskId = ""; - - taskResource.getTask(taskId).stop(); - } - - public static void main(String[] args) throws ClassNotFoundException { - VolumesResource vr = new VolumesResource(); - // VolumeListResponse response = vr.getAllVolumes(); - // for (Volume volume : response.getVolumes()) { - // System.out.println("\nName:" + volume.getName() + "\nType: " + volume.getVolumeTypeStr() + "\nStatus: " - // + volume.getStatusStr()); - // } - // Volume volume = new Volume(); - // volume.setName("vol3"); - // volume.setTransportType(TRANSPORT_TYPE.ETHERNET); - // List disks = new ArrayList(); - // disks.add("192.168.1.210:sdb"); - // volume.addDisks(disks); - // volume.setAccessControlList("192.168.*"); - // // Status status = vr.createVolume(volume); - // // System.out.println(status.getMessage()); - // Form form = new Form(); - // form.add("volumeName", volume.getName()); - // form.add(RESTConstants.FORM_PARAM_DELETE_OPTION, 1); - // Status status = vr.deleteVolume("Vol2", true); - // System.out.println("Code : " + status.getCode()); - // System.out.println("Message " + status.getMessage()); - - // vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true); - - String taskId = vr.migrateBrickStart("myGluster", "students", "devserver1:/export/sdc/students", - "devserver2:/export/sdb/students", true); - - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java new file mode 100644 index 00000000..c28c0da0 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import java.net.URI; +import java.util.ArrayList; + +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.core.UriInfo; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.response.VolumeListResponse; + +/** + * + */ +public class AbstractResource { + @Context + protected UriInfo uriInfo; + + /** + * Creates a response with HTTP status code of 201 (created) and sets the "location" header to the URI created using + * the given path relative to current path. + * + * @param relativePath + * relative path of the created resource - will be set in the "location" header of response. + * @return the {@link Response} object + */ + protected Response createdResponse(String relativePath) { + return Response.created(createRelatriveURI(relativePath)).build(); + } + + /** + * Creates a response with HTTP status code of 204 (no content) + * @return the {@link Response} object + */ + protected Response noContentResponse() { + return Response.noContent().build(); + } + + /** + * Creates a response with HTTP status code of 202 (accepted), also setting the location header to given location. + * This is typically done while triggering long running tasks + * + * @param locationURI + * URI to be appended to the base URI + * @return the {@link Response} object + */ + protected Response acceptedResponse(String locationURI) { + return Response.status(Status.ACCEPTED).location(createAbsoluteURI(locationURI)).build(); + } + + /** + * Creates a response with HTTP status code of 404 (not found), also setting the given message in the response body + * + * @param message + * Message to be set in the response body + * @return the {@link Response} object + */ + protected Response notFoundResponse(String message) { + return Response.status(Status.NOT_FOUND).type(MediaType.TEXT_HTML).entity(message).build(); + } + + /** + * Creates a new URI that is relative to the base URI of the application + * @param uriString URI String to be appended to the base URI + * @return newly created URI + */ + private URI createAbsoluteURI(String uriString) { + return uriInfo.getBaseUriBuilder().path(uriString).build(); + } + + /** + * Creates a response with HTTP status code of 204 (no content), also setting the location header to given location + * @param location path of the location to be set relative to current path + * @return the {@link Response} object + */ + protected Response noContentResponse(String location) { + return Response.noContent().location(createRelatriveURI(location)).build(); + } + + /** + * Creates a URI relative to current URI + * @param location path relative to current URI + * @return newly created URI + */ + protected URI createRelatriveURI(String location) { + return uriInfo.getAbsolutePathBuilder().path(location).build(); + } + + /** + * Creates a response with HTTP status code of 500 (internal server error) and sets the error message in the + * response body + * + * @param errMessage + * Error message to be set in the response body + * @return the {@link Response} object + */ + protected Response errorResponse(String errMessage) { + return Response.serverError().type(MediaType.TEXT_HTML).entity(errMessage).build(); + } + + /** + * Creates a response with HTTP status code of 400 (bad request) and sets the error message in the + * response body + * + * @param errMessage + * Error message to be set in the response body + * @return the {@link Response} object + */ + protected Response badRequestResponse(String errMessage) { + return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_HTML).entity(errMessage).build(); + } + + /** + * Creates a response with HTTP status code of 401 (unauthorized) + * + * @return the {@link Response} object + */ + protected Response unauthorizedResponse() { + return Response.status(Status.UNAUTHORIZED).build(); + } + + /** + * Creates an OK response and sets the entity in the response body. + * + * @param entity + * Entity to be set in the response body + * @param mediaType + * Media type to be set on the response + * @return the {@link Response} object + */ + protected Response okResponse(Object entity, String mediaType) { + return Response.ok(entity).type(mediaType).build(); + } + + /** + * Creates a streaming output response and sets the given streaming output in the response. Typically used for + * "download" requests + * + * @param entity + * Entity to be set in the response body + * @param mediaType + * Media type to be set on the response + * @return the {@link Response} object + */ + protected Response streamingOutputResponse(StreamingOutput output) { + return Response.ok(output).type(MediaType.APPLICATION_OCTET_STREAM).build(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java new file mode 100644 index 00000000..8b4b6d99 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java @@ -0,0 +1,38 @@ +/** + * AbstractServersResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.ServerUtil; +import com.sun.jersey.api.core.InjectParam; + +/** + * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". + */ +public class AbstractServersResource extends AbstractResource { + @InjectParam + protected ServerUtil serverUtil; + + @InjectParam + protected GlusterUtil glusterUtil; + + // TODO: Remove this class! +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java new file mode 100644 index 00000000..91eeef1a --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java @@ -0,0 +1,82 @@ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.*; + +import java.util.ArrayList; +import java.util.List; + +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 com.gluster.storage.management.core.model.AlertListResponse; +import com.gluster.storage.management.core.model.Alert; + +@Component +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_ALERTS) +public class AlertsResource { + + @GET + @Produces(MediaType.APPLICATION_XML) + public AlertListResponse getAlerts() { + + List alerts = new ArrayList(); + + // TODO To implement the following dummy alerts + // Alert #1 + Alert alert = new Alert(); + alert.setId("0001"); + alert.setReference("Server1"); // Server + alert.setType(Alert.ALERT_TYPES.CPU_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #2 + alert = new Alert(); + alert.setId("0002"); + alert.setReference("Server2"); // server:Disk - brick + alert.setType(Alert.ALERT_TYPES.MEMORY_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #3 + alert = new Alert(); + alert.setId("0003"); + alert.setReference("server1:sda1"); // Disk name + alert.setType(Alert.ALERT_TYPES.DISK_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in disk [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #4 + alert = new Alert(); + alert.setId("0004"); + alert.setReference("Volume3:server2:sda1"); // volume:[Disk name] + alert.setType(Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in volume [" + alert.getReference().split(":")[0] + + "] disk [" + alert.getReference().split(":")[1] + ":" + alert.getReference().split(":")[2] + "]"); + alerts.add(alert); + + // Alert #5 + alert = new Alert(); + alert.setId("0005"); + alert.setReference("Server2"); // Server name + alert.setType(Alert.ALERT_TYPES.OFFLINE_SERVERS_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " [" + alert.getReference() + "]"); + alerts.add(alert); + + return new AlertListResponse(alerts); + + } + + public static void main(String[] args) { + /* + * // Unit test code AlertsResource alertResource = new AlertsResource(); AlertsListResponse alertResponse = + * alertResource.getAlerts(); List alerts = alertResponse.getAlerts(); for (Alert alert: alerts) { + * System.out.println(alert.getMessage()); } + */ + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java new file mode 100644 index 00000000..431de952 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.DELETE; +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 javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.response.ClusterNameListResponse; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.services.ClusterService; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +/** + * + */ +@Component +@Singleton +@Path(RESOURCE_PATH_CLUSTERS) +public class ClustersResource extends AbstractResource { + @InjectParam + private ClusterService clusterService; + + @GET + @Produces(MediaType.APPLICATION_XML) + public ClusterNameListResponse getClusters() { + List clusters = clusterService.getAllClusters(); + List clusterList = new ArrayList(); + for (ClusterInfo cluster : clusters) { + clusterList.add(cluster.getName()); + } + return new ClusterNameListResponse(clusterList); + } + + @POST + public Response createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + return badRequestResponse("Cluster [" + clusterName + "] already exists!"); + } + + try { + clusterService.createCluster(clusterName); + return createdResponse(clusterName); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to save cluster [" + clusterName + "]: [" + e.getMessage() + + "]"); + } + } + + @PUT + public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(knownServer == null || knownServer.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + return badRequestResponse("Cluster [" + clusterName + "] already exists!"); + } + + ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); + if(mappedCluster != null) { + return badRequestResponse("Server [" + knownServer + "] is already present in cluster [" + + mappedCluster.getName() + "]!"); + } + + try { + clusterService.registerCluster(clusterName, knownServer); + return noContentResponse(clusterName); + } catch(Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to register cluster [" + clusterName + "] using server [" + + knownServer + "]: [" + e.getMessage() + "]"); + } + } + + @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") + @DELETE + public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if(cluster == null) { + return badRequestResponse("Cluster [" + clusterName + "] does not exist!"); + } + + try { + clusterService.unregisterCluster(cluster); + return noContentResponse(); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to unregister cluster [" + clusterName + "]: [" + + e.getMessage() + "]"); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java new file mode 100644 index 00000000..cb39746c --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DETAILS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_DISCOVERED_SERVERS; + +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 javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.response.ServerListResponse; +import com.gluster.storage.management.core.response.ServerNameListResponse; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_DISCOVERED_SERVERS) +public class DiscoveredServersResource extends AbstractServersResource { + private List discoveredServerNames = new ArrayList(); + + public List getDiscoveredServerNames() { + return discoveredServerNames; + } + + public void setDiscoveredServerNames(List discoveredServerNames) { + synchronized (discoveredServerNames) { + this.discoveredServerNames = discoveredServerNames; + } + } + + public void removeDiscoveredServer(String serverName) { + discoveredServerNames.remove(serverName); + } + + public void addDiscoveredServer(String serverName) { + discoveredServerNames.add(serverName); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getDiscoveredServersXML(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getDiscoveredServersResponse(details, MediaType.APPLICATION_XML); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getDiscoveredServersJSON(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getDiscoveredServersResponse(details, MediaType.APPLICATION_JSON); + } + + private Response getDiscoveredServersResponse(Boolean details, String mediaType) { + if(details != null && details == true) { + try { + List discoveredServers = getDiscoveredServerDetails(); + return okResponse(new ServerListResponse(discoveredServers), mediaType); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + } else { + return okResponse(new ServerNameListResponse(getDiscoveredServerNames()), mediaType); + } + } + + private List getDiscoveredServerDetails() { + List discoveredServers = new ArrayList(); + for (String serverName : getDiscoveredServerNames()) { + try { + discoveredServers.add(getDiscoveredServer(serverName)); + } catch(Exception e) { + // TODO: Log the exception + // continue with next discovered server + } + } + return discoveredServers; + } + + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getDiscoveredServerXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_XML); + } + + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getDiscoveredServerJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_JSON); + } + + private Response getDiscoveredServerResponse(String serverName, String mediaType) { + if(serverName == null || serverName.isEmpty()) { + return badRequestResponse("Server name must not be empty!"); + } + try { + return okResponse(getDiscoveredServer(serverName), mediaType); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse(e.getMessage()); + } + } + + private Server getDiscoveredServer(String serverName) { + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + return server; + } + + public static void main(String[] args) { + Response response = (Response)new DiscoveredServersResource().getDiscoveredServersXML(false); + System.out.println(response.getEntity()); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java new file mode 100644 index 00000000..619e4f55 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java @@ -0,0 +1,444 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_DISK_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DISKS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_SERVERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.DELETE; +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 javax.ws.rs.core.Response; + +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.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; +import com.gluster.storage.management.core.response.GlusterServerListResponse; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.data.ServerInfo; +import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.tasks.InitializeDiskTask; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_SERVERS) +public class GlusterServersResource extends AbstractServersResource { + + public static final String HOSTNAMETAG = "hostname:"; + + @InjectParam + private DiscoveredServersResource discoveredServersResource; + + @InjectParam + private TasksResource taskResource; + + @Autowired + private ClusterService clusterService; + + @Autowired + private SshUtil sshUtil; + + protected void fetchServerDetails(GlusterServer server) { + try { + server.setStatus(SERVER_STATUS.ONLINE); + serverUtil.fetchServerDetails(server); + } catch (ConnectionException e) { + server.setStatus(SERVER_STATUS.OFFLINE); + } + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getGlusterServers(clusterName, MediaType.APPLICATION_JSON); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getGlusterServers(clusterName, MediaType.APPLICATION_XML); + } + + public Response getGlusterServers(String clusterName, String mediaType) { + List glusterServers = new ArrayList(); + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (cluster.getServers().size() == 0) { + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterServers = getGlusterServers(clusterName, onlineServer); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + try { + glusterServers = getGlusterServers(clusterName, onlineServer); + } catch (Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + return errorResponse("Couldn't fetch details for server(s): " + errMsg); + } + + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } + + public String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { + String errMsg = ""; + + for (GlusterServer server : glusterServers) { + if (server.getStatus() == SERVER_STATUS.ONLINE && !server.getName().equals(onlineServer.getName())) { + try { + fetchServerDetails(server); + } catch (Exception e) { + errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; + } + } + } + return errMsg; + } + + public List getGlusterServers(String clusterName, GlusterServer onlineServer) { + List glusterServers; + try { + glusterServers = glusterUtil.getGlusterServers(onlineServer); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + glusterServers = glusterUtil.getGlusterServers(onlineServer); + } + return glusterServers; + } + + @GET + @Path("{serverName}") + @Produces(MediaType.APPLICATION_XML) + public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_XML); + } + + @GET + @Path("{serverName}") + @Produces(MediaType.APPLICATION_JSON) + public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_JSON); + } + + private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) { + try { + return okResponse(getGlusterServer(clusterName, serverName), mediaType); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + private GlusterServer getGlusterServer(String clusterName, String serverName) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterRuntimeException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterRuntimeException("Server name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + GlusterServer server = null; + try { + server = glusterUtil.getGlusterServer(onlineServer, serverName); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + server = glusterUtil.getGlusterServer(onlineServer, serverName); + } + + if (server.isOnline()) { + fetchServerDetails(server); + } + return server; + } + + private void performAddServer(String clusterName, String serverName) { + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.addServer(onlineServer.getName(), serverName); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + glusterUtil.addServer(serverName, onlineServer.getName()); + } + } + + @POST + public Response addServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String serverName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(serverName); + if (!publicKeyInstalled && !sshUtil.hasDefaultPassword(serverName)) { + // public key not installed, default password doesn't work. return with error. + return errorResponse("Gluster Management Gateway uses the default password to set up keys on the server." + + CoreConstants.NEWLINE + "However it seems that the password on server [" + serverName + + "] has been changed manually." + CoreConstants.NEWLINE + + "Please reset it back to the standard default password and try again."); + } + + List servers = cluster.getServers(); + if (servers != null && !servers.isEmpty()) { + // cluster has at least one existing server, so that peer probe can be performed + try { + performAddServer(clusterName, serverName); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } else { + // this is the first server to be added to the cluster, which means no + // gluster CLI operation required. just add it to the cluster-server mapping + } + + try { + // add the cluster-server mapping + clusterService.mapServerToCluster(clusterName, serverName); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + + // since the server is added to a cluster, it should not more be considered as a + // discovered server available to other clusters + discoveredServersResource.removeDiscoveredServer(serverName); + + if (!publicKeyInstalled) { + try { + // install public key (this will also disable password based ssh login) + sshUtil.installPublicKey(serverName); + } catch (Exception e) { + return errorResponse("Public key could not be installed on [" + serverName + "]! Error: [" + + e.getMessage() + "]"); + } + } + + return createdResponse(serverName); + } + + @DELETE + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + public Response removeServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + return badRequestResponse("Server name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + List servers = cluster.getServers(); + if (servers == null || servers.isEmpty() || !containsServer(servers, serverName)) { + return badRequestResponse("Server [" + serverName + "] is not attached to cluster [" + clusterName + "]!"); + } + + if (servers.size() == 1) { + // Only one server mapped to the cluster, no "peer detach" required. + // remove the cached online server for this cluster if present + clusterService.removeOnlineServer(clusterName); + } else { + try { + removeServerFromCluster(clusterName, serverName); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + return noContentResponse(); + } + + private void removeServerFromCluster(String clusterName, String serverName) { + // get an online server that is not same as the server being removed + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName, serverName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.removeServer(onlineServer.getName(), serverName); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName, serverName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + glusterUtil.removeServer(onlineServer.getName(), serverName); + } + + if (onlineServer.getName().equals(serverName)) { + // since the cached server has been removed from the cluster, remove it from the cache + clusterService.removeOnlineServer(clusterName); + } + + clusterService.unmapServerFromCluster(clusterName, serverName); + + // since the server is removed from the cluster, it is now available to be added to other clusters. + // Hence add it back to the discovered servers list. + discoveredServersResource.addDiscoveredServer(serverName); + } + + private boolean containsServer(List servers, String serverName) { + for (ServerInfo server : servers) { + if (server.getName().toUpperCase().equals(serverName.toUpperCase())) { + return true; + } + } + return false; + } + + @PUT + @Produces(MediaType.APPLICATION_XML) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_DISKS + "/{" + PATH_PARAM_DISK_NAME + "}") + public Response initializeDisk(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName, @PathParam(PATH_PARAM_DISK_NAME) String diskName) { + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + return badRequestResponse("Server name must not be empty!"); + } + + if (diskName == null || diskName.isEmpty()) { + return badRequestResponse("Disk name must not be empty!"); + } + + InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName); + try { + initializeTask.start(); + taskResource.addTask(initializeTask); + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + private void setGlusterUtil(GlusterUtil glusterUtil) { + this.glusterUtil = glusterUtil; + } + + public static void main(String[] args) { + GlusterServersResource glusterServersResource = new GlusterServersResource(); + GlusterUtil glusterUtil = new GlusterUtil(); + glusterUtil.setSshUtil(new SshUtil()); + glusterServersResource.setGlusterUtil(glusterUtil); + // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); + + // To add a server + // GlusterServerResponse response = glusterServersResource.addServer("my-server"); + // System.out.println(response.getData().getName()); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java new file mode 100644 index 00000000..777565eb --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java @@ -0,0 +1,175 @@ +/** + * TaskResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_TASK_ID; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.DELETE; +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.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.response.TaskInfoListResponse; +import com.gluster.storage.management.server.tasks.Task; +import com.sun.jersey.spi.resource.Singleton; + +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) +@Singleton +public class TasksResource extends AbstractResource { + private Map tasksMap = new HashMap(); + + public TasksResource() { + } + + public void addTask(Task task) { + tasksMap.put(task.getId(), task); + } + + public void removeTask(Task task) { + tasksMap.remove(task.getId()); + } + + public List getAllTasksInfo() { + List allTasksInfo = new ArrayList(); + for (Map.Entry entry : tasksMap.entrySet()) { + checkTaskStatus(entry.getKey()); + allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status + } + return allTasksInfo; + } + + public Task getTask(String taskId) { + for (Map.Entry entry : tasksMap.entrySet()) { + if (entry.getValue().getId().equals(taskId)) { + return entry.getValue(); + } + } + return null; + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getTasks() { + try { + return okResponse(new TaskInfoListResponse(getAllTasksInfo()), MediaType.APPLICATION_XML); + } catch (GlusterRuntimeException e) { + return errorResponse(e.getMessage()); + } + } + + @GET + @Path("/{" + PATH_PARAM_TASK_ID + "}") + @Produces(MediaType.APPLICATION_XML) + public Response getTaskStatus( @PathParam(PATH_PARAM_TASK_ID) String taskId) { + try { + Task task = checkTaskStatus(taskId); + return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML); + } catch (GlusterRuntimeException e) { + return errorResponse(e.getMessage()); + } + } + + private Task checkTaskStatus(String taskId) { + Task task = getTask(taskId); + task.getTaskInfo().setStatus(task.checkStatus()); + return task; + } + + @PUT + @Path("/{" + PATH_PARAM_TASK_ID + "}") + @Produces(MediaType.APPLICATION_XML) + public Response performTask(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_TASK_ID) String taskId, @FormParam(FORM_PARAM_OPERATION) String taskOperation) { + Task task = getTask(taskId); + + try { + if (taskOperation.equals(RESTConstants.TASK_RESUME)) { + task.resume(); + } else if (taskOperation.equals(RESTConstants.TASK_PAUSE)) { + task.pause(); + } else if (taskOperation.equals(RESTConstants.TASK_STOP)) { + task.stop(); + } else if (taskOperation.equals(RESTConstants.TASK_COMMIT)) { + task.commit(); + } + return (Response) noContentResponse(); + } catch(GlusterValidationException ve) { + return badRequestResponse(ve.getMessage()); + } catch (GlusterRuntimeException e) { + return errorResponse(e.getMessage()); + } + } + + @DELETE + @Path("/{" + PATH_PARAM_TASK_ID + "}") + @Produces(MediaType.APPLICATION_XML) + public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, + @QueryParam(FORM_PARAM_OPERATION) String taskOperation) { + Task task = getTask(taskId); + if (task == null) { + return notFoundResponse("Task [" + taskId + "] not found!"); + } + + if(taskOperation == null || taskOperation.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_OPERATION + "] is missing in request!"); + } + + if(!taskOperation.equals(RESTConstants.TASK_STOP) && !taskOperation.equals(RESTConstants.TASK_DELETE)) { + return badRequestResponse("Invalid value [" + taskOperation + "] for parameter [" + FORM_PARAM_OPERATION + + "]"); + } + + try { + if (taskOperation.equals(RESTConstants.TASK_STOP)) { + task.stop(); + // On successfully stopping the task, we can delete (forget) it as it is no more useful + taskOperation = RESTConstants.TASK_DELETE; + } + + if (taskOperation.equals(RESTConstants.TASK_DELETE)) { + removeTask(task); + } + + return noContentResponse(); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java new file mode 100644 index 00000000..1b5e8fad --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_USER; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_USERS; + +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 javax.ws.rs.core.Response; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.encoding.PasswordEncoder; +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(RESOURCE_PATH_USERS) +public class UsersResource extends AbstractResource { + @Autowired + private JdbcUserDetailsManager jdbcUserService; + + @Autowired + private PasswordEncoder passwordEncoder; + + private static final Logger logger = Logger.getLogger(UsersResource.class); + + @Path("{" + PATH_PARAM_USER + "}") + @GET + @Produces(MediaType.APPLICATION_XML) + public Response authenticateXML(@PathParam("user") String user) { + // success only if the user passed in query is same as the one passed in security header + // spring security would have already authenticated the user credentials + return getAuthenticationResponse(user, MediaType.APPLICATION_XML); + } + + @Path("{" + PATH_PARAM_USER + "}") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response authenticateJSON(@PathParam("user") String user) { + // success only if the user passed in query is same as the one passed in security header + // spring security would have already authenticated the user credentials + return getAuthenticationResponse(user, MediaType.APPLICATION_JSON); + } + + public Response getAuthenticationResponse(String user, String mediaType) { + return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? okResponse( + Status.STATUS_SUCCESS, mediaType) : unauthorizedResponse()); + } + + @Path("{" + PATH_PARAM_USER + "}") + @PUT + public Response changePassword(@FormParam("oldpassword") String oldPassword, + @FormParam("newpassword") String newPassword) { + try { + jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); + } catch (Exception ex) { + String errMsg = "Could not change password. Error: [" + ex.getMessage() + "]"; + logger.error(errMsg, ex); + return errorResponse(errMsg); + } + return noContentResponse(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java new file mode 100644 index 00000000..a09b7f08 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java @@ -0,0 +1,1025 @@ +/** + * VolumesResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_ACCESS_PROTOCOLS; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_AUTO_COMMIT; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_BRICKS; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FIX_LAYOUT; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FORCED_DATA_MIGRATE; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_MIGRATE_DATA; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_KEY; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_VALUE; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_REPLICA_COUNT; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SOURCE; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_STRIPE_COUNT; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TARGET; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TRANSPORT_TYPE; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_OPTIONS; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_TYPE; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICKS; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICK_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DOWNLOAD; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_FROM_TIMESTAMP; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LOG_SEVERITY; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TO_TIMESTAMP; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_BRICKS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DEFAULT_OPTIONS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DOWNLOAD; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_LOGS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_OPTIONS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_VOLUMES; +import static com.gluster.storage.management.core.constants.RESTConstants.TASK_START; +import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import javax.ws.rs.DELETE; +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.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.model.VolumeLogMessage; +import com.gluster.storage.management.core.response.GenericResponse; +import com.gluster.storage.management.core.response.LogMessageListResponse; +import com.gluster.storage.management.core.response.VolumeListResponse; +import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse; +import com.gluster.storage.management.core.utils.DateUtil; +import com.gluster.storage.management.core.utils.FileUtil; +import com.gluster.storage.management.core.utils.ProcessUtil; +import com.gluster.storage.management.server.constants.VolumeOptionsDefaults; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.tasks.MigrateBrickTask; +import com.gluster.storage.management.server.tasks.RebalanceVolumeTask; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.ServerUtil; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +@Singleton +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_VOLUMES) +public class VolumesResource extends AbstractResource { + private static final String VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; + private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; + + @InjectParam + private ServerUtil serverUtil; + + @InjectParam + private GlusterUtil glusterUtil; + + @InjectParam + private ClusterService clusterService; + + @InjectParam + private VolumeOptionsDefaults volumeOptionsDefaults; + + @InjectParam + private TasksResource taskResource; + + @GET + @Produces({MediaType.APPLICATION_XML}) + public Response getVolumesXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getVolumes(clusterName, MediaType.APPLICATION_XML); + } + + @GET + @Produces({MediaType.APPLICATION_JSON}) + public Response getVolumesJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getVolumes(clusterName, MediaType.APPLICATION_JSON); + } + + public Response getVolumes(String clusterName, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if(cluster.getServers().size() == 0) { + // no server added yet. return an empty array. + return okResponse(new VolumeListResponse(), mediaType); + } + + return okResponse(getVolumes(clusterName), mediaType); + } + + public VolumeListResponse getVolumes(String clusterName) { + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return new VolumeListResponse(new ArrayList()); + } + + try { + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return new VolumeListResponse(new ArrayList()); + } + + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); + } + } + + @POST + @Produces(MediaType.APPLICATION_XML) + public Response createVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @FormParam(FORM_PARAM_VOLUME_NAME) String volumeName, + @FormParam(FORM_PARAM_VOLUME_TYPE) String volumeType, @FormParam(FORM_PARAM_TRANSPORT_TYPE) String transportType, + @FormParam(FORM_PARAM_REPLICA_COUNT) Integer replicaCount, @FormParam(FORM_PARAM_STRIPE_COUNT) Integer stripeCount, + @FormParam(FORM_PARAM_BRICKS) String bricks, @FormParam(FORM_PARAM_ACCESS_PROTOCOLS) String accessProtocols, + @FormParam(FORM_PARAM_VOLUME_OPTIONS) String options) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + String missingParam = checkMissingParamsForCreateVolume(volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + if(missingParam != null) { + return badRequestResponse("Parameter [" + missingParam + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && replicaCount <= 0) { + return badRequestResponse("Replica count must be a positive integer"); + } + + if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_STRIPE) && stripeCount <= 0) { + return badRequestResponse("Stripe count must be a positive integer"); + } + + try { + performCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, + options); + return createdResponse(volumeName); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + public void performCreateVolume(String clusterName, String volumeName, String volumeType, String transportType, Integer replicaCount, + Integer stripeCount, String bricks, String accessProtocols, String options) { + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + } + } + + /** + * Returns name of the missing parameter if any. If all parameters are present, + * @param volumeName + * @param volumeType + * @param transportType + * @param replicaCount + * @param stripeCount + * @param bricks + * @param accessProtocols + * @param options + * @return + */ + private String checkMissingParamsForCreateVolume(String volumeName, String volumeType, + String transportType, Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, + String options) { + + return (volumeName == null || volumeName.isEmpty()) ? FORM_PARAM_VOLUME_NAME : + (volumeType == null || volumeType.isEmpty()) ? FORM_PARAM_VOLUME_TYPE : + (transportType == null || transportType.isEmpty()) ? FORM_PARAM_TRANSPORT_TYPE : + (replicaCount == null) ? FORM_PARAM_REPLICA_COUNT : + (stripeCount == null) ? FORM_PARAM_STRIPE_COUNT : + (bricks == null || bricks.isEmpty()) ? FORM_PARAM_BRICKS : + (accessProtocols == null || accessProtocols.isEmpty()) ? FORM_PARAM_ACCESS_PROTOCOLS : + (options == null || options.isEmpty()) ? FORM_PARAM_VOLUME_OPTIONS : + null; + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.APPLICATION_XML) + public Response getVolumeXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + return getVolume(clusterName, volumeName, MediaType.APPLICATION_XML); + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.APPLICATION_JSON) + public Response getVolumeJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + return getVolume(clusterName, volumeName, MediaType.APPLICATION_JSON); + } + + private Response getVolume(String clusterName, String volumeName, String mediaType) { + Volume volume = null; + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + try { + volume = getVolume(clusterName, volumeName); + return okResponse(volume, mediaType); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + } + + private Volume getVolume(String clusterName, String volumeName) { + Volume volume; + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); + } + return volume; + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + public Response performOperation(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_OPERATION) String operation, + @FormParam(FORM_PARAM_FIX_LAYOUT) Boolean isFixLayout, + @FormParam(FORM_PARAM_MIGRATE_DATA) Boolean isMigrateData, + @FormParam(FORM_PARAM_FORCED_DATA_MIGRATE) Boolean isForcedDataMigrate) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + try { + if (operation.equals(RESTConstants.TASK_REBALANCE_START)) { + String taskId = rebalanceStart(clusterName, volumeName, isFixLayout, isMigrateData, isForcedDataMigrate); + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + + "/" + taskId); + } else if (operation.equals(RESTConstants.TASK_REBALANCE_STOP)) { + rebalanceStop(clusterName, volumeName); + } else { + performVolumeOperation(clusterName, volumeName, operation); + } + return noContentResponse(); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + } + + private void performVolumeOperation(String clusterName, String volumeName, String operation) { + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + try { + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + performOperation(volumeName, operation, onlineServer); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + performOperation(volumeName, operation, onlineServer); + } + } + + private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { + if (operation.equals(TASK_START)) { + return glusterUtil.startVolume(volumeName, onlineServer.getName()); + } else if (operation.equals(TASK_STOP)) { + return glusterUtil.stopVolume(volumeName, onlineServer.getName()); + } else { + return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + } + } + + @DELETE + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + public Response deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, + @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (deleteFlag == null) { + deleteFlag = false; + } + + Volume volume = null; + try { + volume = getVolume(clusterName, volumeName); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse(e.getMessage()); + } + + List bricks = volume.getBricks(); + Status status = glusterUtil.deleteVolume(volumeName, clusterService.getOnlineServer(clusterName) + .getName()); + if(!status.isSuccess()) { + return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + status); + } + + try { + postDelete(volumeName, bricks, deleteFlag); + } catch(Exception e) { + return errorResponse("Volume [" + volumeName + + "] deleted from cluster, however following errors happened: " + CoreConstants.NEWLINE + + e.getMessage()); + } + + return noContentResponse(); + } + + @DELETE + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + public Response removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICKS) String bricks, + @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { + List brickList = Arrays.asList(bricks.split(",")); // Convert from comma separated string (query + // parameter) + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (bricks == null || bricks.isEmpty()) { + return badRequestResponse("Parameter [" + QUERY_PARAM_BRICKS + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if(deleteFlag == null) { + deleteFlag = false; + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + removeBricks(clusterName, volumeName, brickList, onlineServer); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + try { + cleanupDirectories(brickList, volumeName, brickList.size(), deleteFlag); + } catch(Exception e) { + // append cleanup error to prepare brick error + return errorResponse(e.getMessage()); + } + + return noContentResponse(); + } + + public void removeBricks(String clusterName, String volumeName, List brickList, GlusterServer onlineServer) { + try { + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } + } + + @SuppressWarnings("rawtypes") + private void cleanupDirectories(List bricks, String volumeName, int maxIndex, boolean deleteFlag) { + Status result; + String errors = ""; + for (int i = 0; i < maxIndex; i++) { + String[] brickInfo = bricks.get(i).split(":"); + String serverName = brickInfo[0]; + String brickDirectory = brickInfo[1]; + + String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); + Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); + if (response instanceof GenericResponse) { + result = ((GenericResponse) response).getStatus(); + if (!result.isSuccess()) { + errors += "[" + mountPoint + "][" + volumeName + "] => " + result + + CoreConstants.NEWLINE; + } + } else { + Status errStatus = (Status) response; + errors += "[" + mountPoint + "][" + volumeName + "] => " + errStatus + CoreConstants.NEWLINE; + } + } + if(!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); + } + } + + private void postDelete(String volumeName, List bricks, boolean deleteFlag) { + Status result; + for (Brick brick : bricks) { + String brickDirectory = brick.getBrickDirectory(); + String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); + + result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT + + " " + mountPoint + " " + volumeName + (deleteFlag ? " -d" : ""), Status.class); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Error in post-delete operation of volume [" + volumeName + "]: " + + result); + } + } + } + + @POST + @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) + public Response setOption(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, + @FormParam(RESTConstants.FORM_PARAM_OPTION_KEY) String key, + @FormParam(RESTConstants.FORM_PARAM_OPTION_VALUE) String value) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if(key == null || key.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_KEY + "] is missing in request!"); + } + + if(value == null || value.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_VALUE + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + return createdResponse(key); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) + public Response resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.resetOptions(volumeName, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.resetOptions(volumeName, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + return noContentResponse(); + } + + @GET + @Path(RESOURCE_DEFAULT_OPTIONS) + @Produces(MediaType.APPLICATION_XML) + public VolumeOptionInfoListResponse getDefaultOptionsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + // TODO: Fetch all volume options with their default values from GlusterFS + // whenever such a CLI command is made available in GlusterFS + return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); + } + + @GET + @Path(RESOURCE_DEFAULT_OPTIONS) + @Produces(MediaType.APPLICATION_JSON) + public VolumeOptionInfoListResponse getDefaultOptionsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + // TODO: Fetch all volume options with their default values from GlusterFS + // whenever such a CLI command is made available in GlusterFS + return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); + } + + private List getBrickLogs(Volume volume, Brick brick, Integer lineCount) + throws GlusterRuntimeException { + String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); + String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); + String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; + + // Usage: get_volume_disk_log.py + Object responseObj = serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " " + + logFilePath + " " + lineCount, LogMessageListResponse.class); + + LogMessageListResponse response = null; + if (responseObj instanceof LogMessageListResponse) { + response = (LogMessageListResponse) responseObj; + // populate disk and trim other fields + List logMessages = response.getLogMessages(); + for (VolumeLogMessage logMessage : logMessages) { + logMessage.setBrickDirectory(brick.getBrickDirectory()); + } + return logMessages; + } else { + Status status = (Status) responseObj; + throw new GlusterRuntimeException(status.toString()); + } + } + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS + "/" + RESOURCE_DOWNLOAD) + public Response downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) final String volumeName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + try { + final Volume volume = getVolume(clusterName, volumeName); + StreamingOutput output = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + try { + File archiveFile = new File(downloadLogs(volume)); + output.write(FileUtil.readFileAsByteArray(archiveFile)); + archiveFile.delete(); + } catch (Exception e) { + // TODO: Log the exception + e.printStackTrace(); + String errMsg = "Exception while downloading/archiving volume log files : " + e.getMessage(); + output.write(errMsg.getBytes()); + } + } + }; + return streamingOutputResponse(output); + } catch(Exception e) { + return errorResponse("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]!"); + } + } + + private String downloadLogs(Volume volume) { + // create temporary directory + File tempDir = FileUtil.createTempDir(); + String tempDirPath = tempDir.getPath(); + + for (Brick brick : volume.getBricks()) { + String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), + brick.getServerName()); + String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); + String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; + + serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); + + String fetchedLogFile = tempDirPath + File.separator + logFileName; + // append log file name with server name so that log files don't overwrite each other + // in cases where the brick log file names are same on multiple servers + String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; + + FileUtil.renameFile(fetchedLogFile, localLogFile); + } + + String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; + new ProcessUtil().executeCommand("tar", "czvf", gzipPath, "-C", tempDir.getParent(), tempDir.getName()); + + // delete the temp directory + FileUtil.recursiveDelete(tempDir); + + return gzipPath; + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) + @Produces(MediaType.APPLICATION_XML) + public Response getLogsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, + @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, + @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, + @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, + @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { + return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_XML); + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) + @Produces(MediaType.APPLICATION_JSON) + public Response getLogsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, + @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, + @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, + @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, + @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { + return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_JSON); + } + + public Response getLogs(String clusterName, String volumeName, String brickName, String severity, + String fromTimestamp, String toTimestamp, Integer lineCount, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + List logMessages = null; + Volume volume = null; + try { + volume = (Volume) getVolume(clusterName, volumeName); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + if (brickName == null || brickName.isEmpty() || brickName.equals(CoreConstants.ALL)) { + logMessages = getLogsForAllBricks(volume, lineCount); + } else { + // fetch logs for given brick of the volume + for (Brick brick : volume.getBricks()) { + if (brick.getQualifiedName().equals(brickName)) { + logMessages = getBrickLogs(volume, brick, lineCount); + break; + } + } + } + + filterLogsBySeverity(logMessages, severity); + filterLogsByTime(logMessages, fromTimestamp, toTimestamp); + + return okResponse(new LogMessageListResponse(logMessages), mediaType); + } + + private void filterLogsByTime(List logMessages, String fromTimestamp, String toTimestamp) { + Date fromTime = null, toTime = null; + + if (fromTimestamp != null && !fromTimestamp.isEmpty()) { + fromTime = DateUtil.stringToDate(fromTimestamp); + } + + if (toTimestamp != null && !toTimestamp.isEmpty()) { + toTime = DateUtil.stringToDate(toTimestamp); + } + + List messagesToRemove = new ArrayList(); + for (VolumeLogMessage logMessage : logMessages) { + Date logTimestamp = logMessage.getTimestamp(); + if (fromTime != null && logTimestamp.before(fromTime)) { + messagesToRemove.add(logMessage); + continue; + } + + if (toTime != null && logTimestamp.after(toTime)) { + messagesToRemove.add(logMessage); + } + } + logMessages.removeAll(messagesToRemove); + } + + private void filterLogsBySeverity(List logMessages, String severity) { + if (severity == null || severity.isEmpty()) { + return; + } + + List messagesToRemove = new ArrayList(); + for (VolumeLogMessage logMessage : logMessages) { + if (!logMessage.getSeverity().equals(severity)) { + messagesToRemove.add(logMessage); + } + } + logMessages.removeAll(messagesToRemove); + } + + private List getLogsForAllBricks(Volume volume, Integer lineCount) { + List logMessages; + logMessages = new ArrayList(); + // fetch logs for every brick of the volume + for (Brick brick : volume.getBricks()) { + logMessages.addAll(getBrickLogs(volume, brick, lineCount)); + } + + // Sort the log messages based on log timestamp + Collections.sort(logMessages, new Comparator() { + @Override + public int compare(VolumeLogMessage message1, VolumeLogMessage message2) { + return message1.getTimestamp().compareTo(message2.getTimestamp()); + } + }); + + return logMessages; + } + + @POST + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + public Response addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_BRICKS) String bricks) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (bricks == null || bricks.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_BRICKS + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + List brickList = Arrays.asList(bricks.split(",")); + try { + glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + + return createdResponse(""); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + public Response migrateBrick(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_SOURCE) String fromBrick, + @FormParam(FORM_PARAM_TARGET) String toBrick, @FormParam(FORM_PARAM_AUTO_COMMIT) Boolean autoCommit) { + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (fromBrick == null || fromBrick.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SOURCE + "] is missing in request!"); + } + + if (toBrick == null || toBrick.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_TARGET + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + if(autoCommit == null) { + autoCommit = false; + } + + String taskId = null; + try { + taskId = migrateBrickStart(clusterName, volumeName, fromBrick, toBrick, autoCommit); + }catch(Exception e) { + return errorResponse(e.getMessage()); + } + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + taskId); + } + + private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, + Boolean autoCommit) { + MigrateBrickTask migrateDiskTask = new MigrateBrickTask(clusterService, clusterName, volumeName, fromBrick, + toBrick); + migrateDiskTask.setAutoCommit(autoCommit); + migrateDiskTask.start(); + taskResource.addTask(migrateDiskTask); + return migrateDiskTask.getTaskInfo().getName(); // Return Task ID + } + + private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, + Boolean isForcedDataMigrate) { + String layout = ""; + if (isForcedDataMigrate) { + layout = "forced-data-migrate"; + } else if (isMigrateData) { + layout = "migrate-data"; + } else if (isFixLayout) { + layout = "fix-layout"; + } + + return rebalanceStart(clusterName, volumeName, layout); + } + + private String rebalanceStart(String clusterName, String volumeName, String layout) { + RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName); + rebalanceTask.setLayout(layout); + rebalanceTask.start(); + taskResource.addTask(rebalanceTask); + return rebalanceTask.getId(); + } + + public void rebalanceStop(String clusterName, String volumeName) { + // TODO: arrive at the task id and fetch it + String taskId = ""; + + taskResource.getTask(taskId).stop(); + } + + public static void main(String[] args) throws ClassNotFoundException { + VolumesResource vr = new VolumesResource(); + // VolumeListResponse response = vr.getAllVolumes(); + // for (Volume volume : response.getVolumes()) { + // System.out.println("\nName:" + volume.getName() + "\nType: " + volume.getVolumeTypeStr() + "\nStatus: " + // + volume.getStatusStr()); + // } + // Volume volume = new Volume(); + // volume.setName("vol3"); + // volume.setTransportType(TRANSPORT_TYPE.ETHERNET); + // List disks = new ArrayList(); + // disks.add("192.168.1.210:sdb"); + // volume.addDisks(disks); + // volume.setAccessControlList("192.168.*"); + // // Status status = vr.createVolume(volume); + // // System.out.println(status.getMessage()); + // Form form = new Form(); + // form.add("volumeName", volume.getName()); + // form.add(RESTConstants.FORM_PARAM_DELETE_OPTION, 1); + // Status status = vr.deleteVolume("Vol2", true); + // System.out.println("Code : " + status.getCode()); + // System.out.println("Message " + status.getMessage()); + + // vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true); + + String taskId = vr.migrateBrickStart("myGluster", "students", "devserver1:/export/sdc/students", + "devserver2:/export/sdb/students", true); + + } +} 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 index b0959445..e5b8d726 100644 --- 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 @@ -30,7 +30,7 @@ import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.data.PersistenceDao; -import com.gluster.storage.management.server.resources.DiscoveredServersResource; +import com.gluster.storage.management.server.resources.v1_0.DiscoveredServersResource; import com.gluster.storage.management.server.utils.ServerUtil; /** diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java index 2a86a690..a24e147c 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java @@ -44,7 +44,7 @@ import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.utils.GlusterCoreUtil; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.core.utils.StringUtil; -import com.gluster.storage.management.server.resources.TasksResource; +import com.gluster.storage.management.server.resources.v1_0.TasksResource; import com.sun.jersey.api.core.InjectParam; @Component 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 index 59714c87..c8301c7b 100644 --- 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 @@ -16,7 +16,7 @@ - -- cgit