diff options
| author | Shireesh Anjal <anjalshireesh@gmail.com> | 2011-06-27 08:38:11 -0700 |
|---|---|---|
| committer | Selvasundaram <selvam@gluster.com> | 2011-06-28 21:09:31 +0530 |
| commit | 5c9b6a12aab8e4ea95d404c4312a89ca2b07ddc6 (patch) | |
| tree | bcc91e2fd0eabc9228bfe72e05e3daf6cac5f1bd | |
| parent | 8c59a588c903cc1a70ea769e78e0414c69006b35 (diff) | |
| parent | 4ef7f5b73e733528d818d2bb6987a56cc3b097ce (diff) | |
Task progress view UI
42 files changed, 1122 insertions, 321 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java index 3d13a8de..9e0e0339 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java @@ -9,6 +9,7 @@ import static com.gluster.storage.management.client.constants.ClientConstants.TR import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
import java.security.KeyStore;
import javax.net.ssl.HostnameVerifier;
@@ -31,6 +32,7 @@ import com.sun.jersey.api.representation.Form; import com.sun.jersey.client.urlconnection.HTTPSProperties;
import com.sun.jersey.core.util.MultivaluedMapImpl;
+
public abstract class AbstractClient {
private static final String HTTP_HEADER_AUTH = "Authorization";
protected static final MultivaluedMap<String, String> NO_PARAMS = new MultivaluedMapImpl();
@@ -262,9 +264,9 @@ public abstract class AbstractClient { postRequest(resource.path(subResourceName), form);
}
- private void putRequest(WebResource resource, Form form) {
+ private ClientResponse putRequest(WebResource resource, Form form) {
try {
- prepareFormRequestBuilder(resource).put(form);
+ return prepareFormRequestBuilder(resource).put(ClientResponse.class, form);
} catch (UniformInterfaceException e) {
throw new GlusterRuntimeException(e.getResponse().getEntity(String.class));
}
@@ -286,6 +288,11 @@ public abstract class AbstractClient { protected void putRequest(String subResourceName, Form form) {
putRequest(resource.path(subResourceName), form);
}
+
+
+ protected URI putRequestURI(String subResourceName, Form form) {
+ return putRequest(resource.path(subResourceName), form).getLocation();
+ }
/**
* Submits given Form using PUT method to the given sub-resource and returns the object received as response
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 695fae19..88d5fdd0 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 @@ -35,15 +35,13 @@ import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Server; 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.model.Volume; import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.model.VolumeOptionInfo; -import com.gluster.storage.management.core.response.GlusterServerListResponse; -import com.gluster.storage.management.core.response.ServerListResponse; -import com.gluster.storage.management.core.response.VolumeListResponse; -import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse; public class GlusterDataModelManager { private static GlusterDataModelManager instance = new GlusterDataModelManager(); @@ -92,7 +90,6 @@ public class GlusterDataModelManager { initializeAutoDiscoveredServers(cluster); // initializeDisks(); - initializeTasks(cluster); initializeAlerts(cluster); initializeVolumeOptionsDefaults(); @@ -118,10 +115,40 @@ public class GlusterDataModelManager { } public void initializeTasks(Cluster cluster) { - List<TaskInfo> taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); + // List<TaskInfo> taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); + List<TaskInfo> taskInfoList = getDummyTasks(); cluster.setTaskInfoList(taskInfoList); } + private List<TaskInfo> getDummyTasks() { + List<TaskInfo> taskInfoList = new ArrayList<TaskInfo>(); + + // Task #1 + TaskInfo taskInfo = new TaskInfo(); + taskInfo.setType(TASK_TYPE.BRICK_MIGRATE); + taskInfo.setName("Migrate Brick-music"); + taskInfo.setCanPause(true); + taskInfo.setCanStop(true); + taskInfo.setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, ""))); + + taskInfo.getStatus().setMessage("Migrating file xxxxx to yyyy"); + taskInfo.setDescription("Migrate Brick on volume [music] from /export/adb/music to /export/sdc/music."); + taskInfoList.add(taskInfo); + // Task #2 + taskInfo = new TaskInfo(); + taskInfo.setType(TASK_TYPE.DISK_FORMAT); + taskInfo.setName("Format Disk-server1:sdc"); + taskInfo.setCanPause(false); + taskInfo.setCanStop(false); + taskInfo.setStatus( new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, ""))); + taskInfo.getStatus().setMessage("Format completes 80% ..."); + taskInfo.setDescription("Formatting disk server1:sdc."); + taskInfoList.add(taskInfo); + + + return taskInfoList; + } + public void initializeAlerts(Cluster cluster) { cluster.setAlerts(new AlertsClient(cluster.getName()).getAllAlerts()); } @@ -175,7 +202,7 @@ public class GlusterDataModelManager { Disk disk = null; List<Disk> volumeDisks = new ArrayList<Disk>(); for (Brick brick : volume.getBricks()) { - disk = getDisk(brick.getDiskName()); + disk = getDisk(brick.getServerName() + ":" + brick.getDiskName()); // disk = new Disk(); // disk.setServerName(brick.getServerName()); // disk.setName(brick.getDiskName()); @@ -334,6 +361,15 @@ public class GlusterDataModelManager { } } + public void updateTaskStatus(TaskInfo taskInfo, Status newStatus) { + taskInfo.getStatus().setCode(newStatus.getCode()); + taskInfo.getStatus().setMessage(newStatus.getMessage()); + for (ClusterListener listener : listeners) { + listener.taskUpdated(taskInfo); + } + } + + public List<VolumeOptionInfo> getVolumeOptionsDefaults() { return volumeOptionsDefaults; } @@ -414,4 +450,5 @@ public class GlusterDataModelManager { } return volumeNames; } + } diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/TasksClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/TasksClient.java index b5ee1d1c..aff4f5d2 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/TasksClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/TasksClient.java @@ -26,15 +26,17 @@ import javax.ws.rs.core.MultivaluedMap; import com.gluster.storage.management.core.constants.RESTConstants; 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.response.TaskListResponse; -import com.gluster.storage.management.core.response.TaskResponse; +import com.gluster.storage.management.core.response.TaskInfoListResponse; import com.sun.jersey.api.representation.Form; import com.sun.jersey.core.util.MultivaluedMapImpl; public class TasksClient extends AbstractClient { + public TasksClient() { + super(); + } + public TasksClient(String clusterName) { super(clusterName); } @@ -48,14 +50,8 @@ public class TasksClient extends AbstractClient { return RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESTConstants.RESOURCE_TASKS + "/"; } - @SuppressWarnings("unchecked") public List<TaskInfo> getAllTasks() { // TaskListResponse get only the list of taskInfo not list of Tasks - TaskListResponse response = (TaskListResponse) fetchResource(TaskListResponse.class); - if (response.getStatus().isSuccess()) { - return (List<TaskInfo>) response.getData(); - } else { - throw new GlusterRuntimeException("Exception on fetching tasks [" + response.getStatus().getMessage() + "]"); - } + return ((TaskInfoListResponse) fetchResource(TaskInfoListResponse.class)).getTaskList(); } // see startMigration @ VolumesClient, etc 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 c04389d1..07aea5a1 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 @@ -29,6 +29,7 @@ import static com.gluster.storage.management.core.constants.RESTConstants.FORM_P 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 java.net.URI; import java.util.Date; import java.util.List; @@ -227,7 +228,9 @@ public class VolumesClient extends AbstractClient { form.add(RESTConstants.FORM_PARAM_OPERATION, RESTConstants.TASK_START); form.add(RESTConstants.FORM_PARAM_AUTO_COMMIT, autoCommit); - putRequest(volumeName + "/" + RESTConstants.RESOURCE_BRICKS, form); + // putRequest(volumeName + "/" + RESTConstants.RESOURCE_BRICKS, form); + URI uri = putRequestURI(volumeName + "/" + RESTConstants.RESOURCE_BRICKS, form); + System.out.println(uri.getRawPath()); } public static void main(String[] args) { diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java index deabbde7..c37869dc 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -45,6 +45,7 @@ public class RESTConstants { public static final String TASK_PAUSE = "pause"; public static final String TASK_RESUME = "resume"; public static final String TASK_STOP = "stop"; + public static final String TASK_COMMIT = "commit"; public static final String TASK_STATUS = "status"; public static final String TASK_DELETE = "delete"; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterValidationException.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterValidationException.java new file mode 100644 index 00000000..ca5e01f8 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/exceptions/GlusterValidationException.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.core.exceptions; + +public class GlusterValidationException extends GlusterRuntimeException { + private static final long serialVersionUID = 1L; + + public GlusterValidationException(String message) { + super(message); + } +} 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 f96116ed..71de5e23 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 @@ -42,4 +42,10 @@ public interface ClusterListener { public void volumeCreated(Volume volume); public void volumeDeleted(Volume volume); + + public void taskAdded(TaskInfo taskInfo); + + public void taskRemoved(TaskInfo taskInfo); + + public void taskUpdated(TaskInfo taskInfo); } 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 e226d51b..d3b0e42e 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 @@ -74,6 +74,24 @@ public class DefaultClusterListener implements ClusterListener { clusterChanged(); } + + @Override + public void taskAdded(TaskInfo taskInfo) { + clusterChanged(); + } + + + @Override + public void taskRemoved(TaskInfo taskInfo) { + clusterChanged(); + } + + + @Override + public void taskUpdated(TaskInfo taskInfo) { + clusterChanged(); + } + /** * This method is called by every other event method. Thus, if a view/listener is interested in performing the same * task on any change happening in the cluster data model, it can simply override this method and implement the @@ -82,4 +100,5 @@ public class DefaultClusterListener implements ClusterListener { public void clusterChanged() { } + } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Task.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Task.java index 45eb07ba..b7823c4b 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Task.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Task.java @@ -20,22 +20,23 @@ */ package com.gluster.storage.management.core.model; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; + public abstract class Task { - public enum TASK_TYPE { - DISK_FORMAT, BRICK_MIGRATE, VOLUME_REBALANCE - } - public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; - private TaskInfo taskInfo; + protected TaskInfo taskInfo; protected String serverName; - public Task(TASK_TYPE type, String reference) { + public Task(TASK_TYPE type, String reference, String desc, boolean canPause, boolean canStop, boolean canCommit) { taskInfo = new TaskInfo(); taskInfo.setType(type); - taskInfo.setId(getTypeStr() + "-" + reference); // construct id taskInfo.setReference(reference); + taskInfo.setDescription(desc); + + // IMPORTANT. This call must be in the end since getId may need to use the values set in above statements + taskInfo.setName(getId()); } public Task(TaskInfo taskInfo) { @@ -68,16 +69,18 @@ public abstract class Task { public abstract String getId(); - public abstract TaskInfo start(); + public abstract void start(); - public abstract TaskInfo resume(); + public abstract void resume(); - public abstract TaskInfo stop(); + public abstract void stop(); - public abstract TaskInfo pause(); - - public abstract TaskInfo status(); - - public abstract void setTaskDescription(); + public abstract void pause(); + public abstract void commit(); + + /** + * This method should check current status of the task and update it's taskInfo accordingly + */ + public abstract TaskStatus checkStatus(); } 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 d4549146..1ce2fa04 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 @@ -20,24 +20,31 @@ */ package com.gluster.storage.management.core.model; -import com.gluster.storage.management.core.model.Task.TASK_TYPE; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.gluster.storage.management.core.utils.StringUtil; + +@XmlRootElement +public class TaskInfo extends Entity { + public enum TASK_TYPE { + DISK_FORMAT, BRICK_MIGRATE, VOLUME_REBALANCE + } -public class TaskInfo extends Status { - private String id; private TASK_TYPE type; private String reference; private String description; - private Boolean canPause; - private Boolean canStop; + private Boolean pauseSupported; + private Boolean stopSupported; + private Boolean commitSupported; private TaskStatus status; - - public String getId() { - return id; + public TaskInfo() { } - public void setId(String id) { - this.id = id; + @XmlElement(name="id") + public String getName() { + return super.getName(); } public TASK_TYPE getType() { @@ -72,20 +79,35 @@ public class TaskInfo extends Status { this.status = status; } - public Boolean getCanPause() { - return canPause; + public Boolean canPause() { + return pauseSupported; } public void setCanPause(Boolean canPause) { - this.canPause = canPause; + this.pauseSupported = canPause; } - public Boolean getCanStop() { - return canStop; + public Boolean canStop() { + return stopSupported; } public void setCanStop(Boolean canStop) { - this.canStop = canStop; + this.stopSupported = canStop; + } + + public Boolean canCommit() { + return this.commitSupported; + } + + public void setCanCommit(Boolean canCommit) { + this.commitSupported = canCommit; } + /* (non-Javadoc) + * @see com.gluster.storage.management.core.model.Entity#filter(java.lang.String, boolean) + */ + @Override + public boolean filter(String filterString, boolean caseSensitive) { + return StringUtil.filterString(getDescription() + getStatus().getMessage(), filterString, caseSensitive); + } } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java index 2637b197..0ab27c35 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskListResponse.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/TaskInfoListResponse.java @@ -20,35 +20,31 @@ */ package com.gluster.storage.management.core.response; -import java.util.ArrayList; import java.util.List; +import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskInfo; -@XmlRootElement -public class TaskListResponse extends AbstractResponse { - private List<TaskInfo> taskList = new ArrayList<TaskInfo>(); - private Status status; - - public Status getStatus() { - return status; - } +@XmlRootElement(name = "tasks") +public class TaskInfoListResponse { + private List<TaskInfo> taskInfoList; - public void setStatus(Status status) { - this.status = status; - } + public TaskInfoListResponse() { + } - public void setData(List<TaskInfo> taskList) { - this.taskList.clear(); - this.taskList.addAll(taskList); + public TaskInfoListResponse(List<TaskInfo> taskInfoList) { + this.taskInfoList = taskInfoList; + } + + @XmlElement(name="task", type=TaskInfo.class) + public List<TaskInfo> getTaskList() { + return taskInfoList; } - @Override - public Object getData() { - return this.taskList; + public void setTaskList(List<TaskInfo> taskInfoList) { + this.taskInfoList = taskInfoList; } } diff --git a/src/com.gluster.storage.management.gui/icons/close_task.png b/src/com.gluster.storage.management.gui/icons/close_task.png Binary files differnew file mode 100644 index 00000000..933272b4 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/close_task.png diff --git a/src/com.gluster.storage.management.gui/icons/pause_task.png b/src/com.gluster.storage.management.gui/icons/pause_task.png Binary files differnew file mode 100644 index 00000000..af57b25d --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/pause_task.png diff --git a/src/com.gluster.storage.management.gui/icons/start_task.gif b/src/com.gluster.storage.management.gui/icons/start_task.gif Binary files differnew file mode 100644 index 00000000..2dfaef50 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/start_task.gif diff --git a/src/com.gluster.storage.management.gui/icons/stop_task.png b/src/com.gluster.storage.management.gui/icons/stop_task.png Binary files differnew file mode 100644 index 00000000..7c6af7f0 --- /dev/null +++ b/src/com.gluster.storage.management.gui/icons/stop_task.png diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index af065b7d..c5c25c33 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -30,14 +30,6 @@ restorable="true"> </view> <view - category="org.eclipse.ui" - class="org.eclipse.ui.ExtensionFactory:progressView" - icon="icons/progress-bar.png" - id="org.eclipse.ui.views.ProgressView" - name="Tasks in Progress" - restorable="true"> - </view> - <view allowMultiple="false" category="com.gluster.storage.management.gui.category" class="com.gluster.storage.management.gui.views.DiscoveredServersView" @@ -175,6 +167,15 @@ name="Server Logs" restorable="true"> </view> + <view + allowMultiple="false" + category="com.gluster.storage.management.gui.category" + class="com.gluster.storage.management.gui.views.TasksView" + icon="icons/progress-bar.png" + id="com.gluster.storage.management.gui.views.TasksView" + name="Tasks" + restorable="true"> + </view> </extension> <extension point="org.eclipse.ui.commands"> @@ -249,10 +250,35 @@ name="Remove Brick"> </command> <command + categoryId="com.gluster.storage.management.gui.category" description="Add Brick" id="com.gluster.storage.management.gui.commands.AddDisk" name="Add Brick"> </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Pause Task" + id="com.gluster.storage.management.gui.commands.Pause" + name="Pause"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Resume Task" + id="com.gluster.storage.management.gui.commands.Resume" + name="Resume"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Stop Task" + id="com.gluster.storage.management.gui.commands.Stop" + name="Stop"> + </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Delete Task" + id="com.gluster.storage.management.gui.commands.Delete" + name="Delete"> + </command> </extension> <extension point="org.eclipse.ui.bindings"> @@ -643,6 +669,70 @@ visible="false"> <action allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.ClearTaskAction" + definitionId="com.gluster.storage.management.gui.commands.Clear" + icon="icons/close_task.png" + id="com.gluster.storage.management.gui.actions.Clear" + label="&Clear Task" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="To clear selected task from task list"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.StopTaskAction" + definitionId="com.gluster.storage.management.gui.commands.Stop" + icon="icons/stop_task.png" + id="com.gluster.storage.management.gui.actions.Stop" + label="&Stop Task" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="To Stop the selected task"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.ResumeTaskAction" + definitionId="com.gluster.storage.management.gui.commands.Pause" + icon="icons/start_task.gif" + id="com.gluster.storage.management.gui.actions.Resume" + label="&Resume Task" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="To Resume the selected task"> + </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.PauseTaskAction" + definitionId="com.gluster.storage.management.gui.commands.Pause" + icon="icons/pause_task.png" + id="com.gluster.storage.management.gui.actions.Pause" + label="&Pause Task" + menubarPath="com.gluster.storage.management.gui.menu.cluster/cluster" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="To Pause the selected task"> + </action> + <action + allowLabelUpdate="false" class="com.gluster.storage.management.gui.actions.CreateVolumeAction" definitionId="com.gluster.storage.management.gui.commands.CreateVolume" icon="icons/volume-create.png" @@ -1006,6 +1096,18 @@ standalone="false" visible="false"> </view> + <view + closeable="false" + id="com.gluster.storage.management.gui.views.TasksView" + minimized="false" + moveable="false" + ratio="0.30f" + relationship="stack" + relative="com.gluster.storage.management.gui.views.ClusterSummaryView" + showTitle="true" + standalone="false" + visible="false"> + </view> </perspectiveExtension> </extension> <extension diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java index 65124bf9..c2223729 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/IImageKeys.java @@ -55,6 +55,11 @@ public interface IImageKeys { public static final String LOW_DISK_SPACE = "icons/disk.png"; public static final String DISK_OFFLINE = "icons/status-offline.png"; + public static final String PAUSE_TASK = "icons/pause_task.gif"; + public static final String RESUME_TASK = "icons/resume_task.gif"; + public static final String STOP_TASK = "icons/stop_task.gif"; + public static final String CLEAR_TASK = "icons/close_task.gif"; + public static final String OVERLAY_OFFLINE = "icons/status-offline-small.png"; public static final String OVERLAY_ONLINE = "icons/status-online-small.png"; public static final String OVERLAY_STAR = "icons/star-small.png"; diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TasksTableLabelProvider.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TasksTableLabelProvider.java new file mode 100644 index 00000000..177b069e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/TasksTableLabelProvider.java @@ -0,0 +1,47 @@ +/** + * TasksTableLabelProvider.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package com.gluster.storage.management.gui; + +import org.eclipse.swt.graphics.Image; + +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.gui.utils.GUIHelper; +import com.gluster.storage.management.gui.views.pages.TasksPage.TASK_TABLE_COLUMN_INDICES; + + +public class TasksTableLabelProvider extends TableLabelProviderAdapter { + private GUIHelper guiHelper = GUIHelper.getInstance(); + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + if (!(element instanceof TaskInfo)) { + return null; + } + + TaskInfo taskInfo = (TaskInfo) element; + return (columnIndex == TASK_TABLE_COLUMN_INDICES.TASK.ordinal()) ? taskInfo.getDescription() : taskInfo.getStatus().getMessage(); + } +} 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 new file mode 100644 index 00000000..75db898d --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ClearTaskAction.java @@ -0,0 +1,53 @@ +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.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public class ClearTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @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.updateTaskStatus(taskInfo, new Status(Status.STATUS_CODE_PART_SUCCESS, taskInfo.getName() + " is cleared from task list")); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be cleared! 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.getStatus().getCode() == Status.STATUS_CODE_SUCCESS + || taskInfo.getStatus().getCode() == Status.STATUS_CODE_FAILURE); + } + } + + @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 index bbb29253..56ea8179 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 @@ -18,14 +18,16 @@ *******************************************************************************/ 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.viewers.StructuredSelection; 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; @@ -33,9 +35,6 @@ public class MigrateDiskAction extends AbstractActionDelegate { @Override protected void performAction(IAction action) { -// MigrateDiskDialog dialog = new MigrateDiskDialog(window.getShell(), volume, disk); -// dialog.create(); -// dialog.open(); MigrateDiskWizard wizard = new MigrateDiskWizard(volume, brick); WizardDialog dialog = new WizardDialog(window.getShell(), wizard); @@ -47,15 +46,16 @@ public class MigrateDiskAction extends AbstractActionDelegate { @Override public void selectionChanged(IAction action, ISelection selection) { super.selectionChanged(action, selection); - + Set<Brick> bricks; if (selectedEntity instanceof Volume) { volume = (Volume) selectedEntity; } action.setEnabled(false); if (selectedEntity instanceof Brick) { - brick = (Brick) selectedEntity; - action.setEnabled(((StructuredSelection) selection).size() == 1); + bricks = GUIHelper.getInstance().getSelectedEntities(getWindow(), Brick.class); + brick = (Brick) bricks.iterator().next(); + action.setEnabled(brick != null); } } 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 new file mode 100644 index 00000000..2bb7261e --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/PauseTaskAction.java @@ -0,0 +1,75 @@ +/** + * PauseTaskAction.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package com.gluster.storage.management.gui.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.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + + +public class PauseTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @Override + protected void performAction(final IAction action) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + final String actionDesc = action.getDescription(); + + try { + new TasksClient().pauseTask(taskInfo.getName()); + //TODO Update taskInfo in the model + // modelManager.updateVolumeStatus(volume, VOLUME_STATUS.OFFLINE); + modelManager.updateTaskStatus(taskInfo, new Status( Status.STATUS_CODE_PAUSE, "Paused")); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] 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); + } + } + + @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/ResumeTaskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java new file mode 100644 index 00000000..07894c80 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/ResumeTaskAction.java @@ -0,0 +1,54 @@ +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.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public class ResumeTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @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.updateTaskStatus(taskInfo, new Status(Status.STATUS_CODE_PAUSE, taskInfo.getName() + " is Resumed")); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be Resumed! 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.getStatus().getCode() == Status.STATUS_CODE_PAUSE); + } + } + + @Override + public void dispose() { + + + } + + +} 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 new file mode 100644 index 00000000..144e94be --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StopTaskAction.java @@ -0,0 +1,54 @@ +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.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; + +public class StopTaskAction extends AbstractActionDelegate { + private TaskInfo taskInfo; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + @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.updateTaskStatus(taskInfo, new Status(Status.STATUS_CODE_PART_SUCCESS, taskInfo.getName() + " is Stopped")); + } catch (Exception e) { + showErrorDialog(actionDesc, + "Task [" + taskInfo.getName() + "] could not be Stopped! 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.canStop() + && (taskInfo.getStatus().getCode() == Status.STATUS_CODE_PAUSE + || taskInfo.getStatus().getCode() == Status.STATUS_CODE_RUNNING)); + } + } + + @Override + public void dispose() { + + } + +} 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 index ba5ef867..4533ca23 100644 --- 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 @@ -23,13 +23,16 @@ 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; @@ -62,6 +65,8 @@ public class MigrateDiskPage1 extends WizardPage { private TableViewer tableViewerFrom; + private Button autoCompleteCheckbox; + private ITableLabelProvider getDiskLabelProvider(final String volumeName) { return new TableLabelProviderAdapter() { @@ -74,9 +79,9 @@ public class MigrateDiskPage1 extends WizardPage { 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()) + .formatNumber(disk.getFreeSpace() / 1024 ) /* Coverted to GB */ : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil - .formatNumber(disk.getSpace()) : "Invalid"); + .formatNumber(disk.getSpace() / 1024) : "Invalid"); } }; } @@ -118,10 +123,6 @@ public class MigrateDiskPage1 extends WizardPage { this.volume = volume; this.fromBrick = brick; setTitle("Migrate Brick [" + volume.getName() + "]"); - // setDescription("Migrate data from one disk to another for the chosen Volume. " + - // "This will copy all data present in the \"from disk\" of the volume " + - // "to \"to disk\", remove \"from disk\" from the volume, and " + - // "add \"to disk\" to the volume"); setPageDescription(null, null); setPageComplete(false); } @@ -162,12 +163,18 @@ public class MigrateDiskPage1 extends WizardPage { return tableViewerComposite; } - public Disk getSourceDisk() { - return getSelectedDisk(tableViewerFrom); + public String getSourceBrickDir() { + Disk sourceDisk = getSelectedDisk(tableViewerFrom); + return sourceDisk.getQualifiedBrickName(volume.getName()); } - public Disk getTargetDisk() { - return getSelectedDisk(tableViewerTo); + public String getTargetBrickDir() { + Disk targetDisk = getSelectedDisk(tableViewerTo); + return targetDisk.getQualifiedBrickName(volume.getName()); + } + + public Boolean getAutoCommitSelection() { + return autoCompleteCheckbox.getSelection(); } /** @@ -200,7 +207,7 @@ public class MigrateDiskPage1 extends WizardPage { GlusterDataModelManager glusterDataModelManager = GlusterDataModelManager.getInstance(); List<Disk> fromBricks = glusterDataModelManager.getReadyDisksOfVolume(volume); - List<Disk> toDisks = glusterDataModelManager.getReadyDisksOfAllServersExcluding( glusterDataModelManager.getReadyDisksOfVolume(volume)); + List<Disk> toDisks = glusterDataModelManager.getReadyDisksOfAllServersExcluding( fromBricks ); tableViewerFrom = createTableViewer(container, diskLabelProvider, fromBricks, txtFilterFrom); @@ -208,6 +215,17 @@ public class MigrateDiskPage1 extends WizardPage { 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) { @@ -220,9 +238,17 @@ public class MigrateDiskPage1 extends WizardPage { } } } + + private void refreshButtonStatus() { + if(tableViewerFrom.getSelection().isEmpty() || tableViewerTo.getSelection().isEmpty()) { + setPageComplete(false); + } else { + setPageComplete(true); + } + } private TableViewer createTableViewer(Composite container, ITableLabelProvider diskLabelProvider, - List<Disk> fromDisks, Text txtFilterText) { + List<Disk> bricks, Text txtFilterText) { Composite tableViewerComposite = createTableViewerComposite(container); TableViewer tableViewer = new TableViewer(tableViewerComposite, SWT.SINGLE); @@ -232,7 +258,15 @@ public class MigrateDiskPage1 extends WizardPage { setupDiskTable(tableViewerComposite, tableViewer.getTable()); guiHelper.createFilter(tableViewer, txtFilterText, false); - tableViewer.setInput(fromDisks.toArray()); + 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 index 60cbd387..514f805e 100644 --- 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 @@ -18,9 +18,9 @@ *******************************************************************************/ package com.gluster.storage.management.gui.dialogs; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.Wizard; -import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.Disk; @@ -47,14 +47,19 @@ public class MigrateDiskWizard extends Wizard { @Override public boolean performFinish() { - Disk sourceDisk = page.getSourceDisk(); - Disk targetDisk = page.getTargetDisk(); - Boolean autoCommit = true; //TODO get auto commit from user selection - // TODO add custom confirm dialog - + String sourceDir = page.getSourceBrickDir(); + String targetDir = page.getTargetBrickDir(); + Boolean autoCommit = page.getAutoCommitSelection(); VolumesClient volumesClient = new VolumesClient(); - volumesClient.startMigration(volume.getName(), sourceDisk.getQualifiedName(), targetDisk.getQualifiedName(), autoCommit); - + + try { + volumesClient.startMigration(volume.getName(), sourceDir, targetDir, autoCommit); + MessageDialog.openInformation(getShell(), "Brick migration", + "Brick migration is initiated, Please check the status..."); + //TODO Add the task to model + } 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/utils/GUIHelper.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java index ac29ecf0..d6fd5d03 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java @@ -84,6 +84,7 @@ import com.gluster.storage.management.core.utils.JavaUtil; import com.gluster.storage.management.gui.Application; import com.gluster.storage.management.gui.IImageKeys; import com.gluster.storage.management.gui.views.NavigationView; +import com.gluster.storage.management.gui.views.TasksView; public class GUIHelper { private static final GUIHelper instance = new GUIHelper(); @@ -416,6 +417,7 @@ public class GUIHelper { return selectedEntities; } + public void configureCheckboxTableViewer(final CheckboxTableViewer tableViewer) { tableViewer.addCheckStateListener(new ICheckStateListener() { @@ -450,6 +452,16 @@ public class GUIHelper { } } + public void showTaskView() { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .showView( TasksView.ID ); + } catch (PartInitException e) { + e.printStackTrace(); + throw new GlusterRuntimeException("Could not open the task progress view!", e); + } + } + public void setStatusMessage(String message) { Application.getApplication().getStatusLineManager().setMessage(message); } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java index b4b31a0a..ab1e55ab 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterViewsManager.java @@ -29,6 +29,7 @@ import com.gluster.storage.management.core.model.Entity; import com.gluster.storage.management.core.model.EntityGroup; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.TaskInfo; import com.gluster.storage.management.core.model.Volume; /** @@ -80,6 +81,7 @@ public class GlusterViewsManager implements ViewsManager { private void showViewsForCluster(Cluster cluster) throws PartInitException { page.showView(ClusterSummaryView.ID); + page.showView(TasksView.ID, null, IWorkbenchPage.VIEW_CREATE); } private void showViewsForVolume(Volume volume) throws PartInitException { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/TasksView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/TasksView.java new file mode 100644 index 00000000..fb772d46 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/TasksView.java @@ -0,0 +1,39 @@ +package com.gluster.storage.management.gui.views; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.gui.views.pages.TasksPage; + +public class TasksView extends ViewPart { + + public static final String ID = TasksView.class.getName(); + private TasksPage page; + + + public TasksView() { + // TODO Auto-generated constructor stub + } + + @Override + public void createPartControl(Composite parent) { + page = new TasksPage(getSite(), parent, SWT.NONE, getAllTasks()); + page.layout(); // IMP: lays out the form properly + } + + + private List<TaskInfo> getAllTasks() { + return GlusterDataModelManager.getInstance().getModel().getCluster().getTaskInfoList(); + } + + @Override + public void setFocus() { + page.setFocus(); + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java index 311014a0..a43330c4 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumesSummaryView.java @@ -35,8 +35,8 @@ import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.Alert; import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.EntityGroup; -import com.gluster.storage.management.core.model.Task.TASK_TYPE; 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.Volume; import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import com.gluster.storage.management.gui.IImageKeys; diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractDisksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractDisksPage.java index 32a2c2f6..221e82b1 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractDisksPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractDisksPage.java @@ -57,7 +57,7 @@ public abstract class AbstractDisksPage extends AbstractTableViewerPage<Disk> im protected abstract int getStatusColumnIndex(); public AbstractDisksPage(final Composite parent, int style, IWorkbenchSite site, List<Disk> disks) { - super(site, parent, style, disks); + super(site, parent, style, true, true, disks); this.disks = disks; // creates hyperlinks for "unitialized" disks diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractTableViewerPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractTableViewerPage.java index dfa06f85..a37773e1 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractTableViewerPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/AbstractTableViewerPage.java @@ -26,6 +26,7 @@ import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -50,15 +51,20 @@ import com.gluster.storage.management.gui.utils.GUIHelper; public abstract class AbstractTableViewerPage<T> extends Composite { protected final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); - protected CheckboxTableViewer tableViewer; + protected TableViewer tableViewer; + private boolean useCheckboxes; + private boolean multiSelection; protected GUIHelper guiHelper = GUIHelper.getInstance(); protected Composite parent; private Hyperlink linkAll, linkNone; - public AbstractTableViewerPage(IWorkbenchSite site, final Composite parent, int style, Object model) { + public AbstractTableViewerPage(IWorkbenchSite site, final Composite parent, int style, boolean useChechboxes, boolean multiSelection, Object model) { super(parent, style); this.parent = parent; + + this.useCheckboxes = useChechboxes; + this.multiSelection = multiSelection; toolkit.adapt(this); toolkit.paintBordersFor(this); @@ -69,7 +75,7 @@ public abstract class AbstractTableViewerPage<T> extends Composite { Text filterText = guiHelper.createFilterText(toolkit, this); - setupServerTableViewer(site, filterText); + setupTableViewer(site, filterText); tableViewer.setInput(model); parent.layout(); // Important - this actually paints the table @@ -78,27 +84,35 @@ public abstract class AbstractTableViewerPage<T> extends Composite { } public void createCheckboxSelectionLinks() { - // create the "select all/none" links - toolkit.createLabel(this, "Select"); - linkAll = toolkit.createHyperlink(this, "all", SWT.NONE); - linkAll.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { - tableViewer.setAllChecked(true); - tableViewer.setSelection(new StructuredSelection(getAllEntities())); - } - }); - - toolkit.createLabel(this, " / "); - - linkNone = toolkit.createHyperlink(this, "none", SWT.NONE); - linkNone.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { - tableViewer.setAllChecked(false); - tableViewer.setSelection(null); - } - }); + if (useCheckboxes) { + // create the "select all/none" links + toolkit.createLabel(this, "Select"); + linkAll = toolkit.createHyperlink(this, "all", SWT.NONE); + linkAll.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + ((CheckboxTableViewer) tableViewer).setAllChecked(true); + tableViewer.setSelection(new StructuredSelection(getAllEntities())); + } + }); + + toolkit.createLabel(this, " / "); + + linkNone = toolkit.createHyperlink(this, "none", SWT.NONE); + linkNone.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) { + ((CheckboxTableViewer) tableViewer).setAllChecked(false); + tableViewer.setSelection(null); + } + }); + } else { + // create dummy labels to maintain layout + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + toolkit.createLabel(this, ""); + } } private void createListeners(final Composite parent) { @@ -145,7 +159,7 @@ public abstract class AbstractTableViewerPage<T> extends Composite { setLayout(layout); } - private void setupServerTable(Composite parent, Table table) { + protected void setupTable(Composite parent, Table table) { table.setHeaderVisible(true); table.setLinesVisible(false); @@ -155,15 +169,19 @@ public abstract class AbstractTableViewerPage<T> extends Composite { setColumnProperties(table); } - private CheckboxTableViewer createServerTableViewer(Composite parent) { - CheckboxTableViewer tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI); + private void createTableViewer(Composite parent) { + int style = SWT.FLAT | SWT.FULL_SELECTION; + style |= (multiSelection ? SWT.MULTI : SWT.SINGLE); + + if(useCheckboxes) { + tableViewer = CheckboxTableViewer.newCheckList(parent, style); + } else { + tableViewer = new TableViewer(parent, style); + } tableViewer.setLabelProvider(getLabelProvider()); tableViewer.setContentProvider(getContentProvider()); - - setupServerTable(parent, tableViewer.getTable()); - - return tableViewer; + setupTable(parent, tableViewer.getTable()); } private Composite createTableViewerComposite() { @@ -182,13 +200,15 @@ public abstract class AbstractTableViewerPage<T> extends Composite { return tableViewerComposite; } - private void setupServerTableViewer(IWorkbenchSite site, final Text filterText) { + private void setupTableViewer(IWorkbenchSite site, final Text filterText) { Composite tableViewerComposite = createTableViewerComposite(); - tableViewer = createServerTableViewer(tableViewerComposite); + createTableViewer(tableViewerComposite); site.setSelectionProvider(tableViewer); - // make sure that table selection is driven by checkbox selection - guiHelper.configureCheckboxTableViewer(tableViewer); + if(useCheckboxes) { + // make sure that table selection is driven by checkbox selection + guiHelper.configureCheckboxTableViewer((CheckboxTableViewer)tableViewer); + } // Create a case insensitive filter for the table viewer using the filter text field guiHelper.createFilter(tableViewer, filterText, false); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java index b83914eb..9805daec 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/BricksPage.java @@ -47,7 +47,7 @@ public class BricksPage extends AbstractTableViewerPage<Brick> { "Total Space (GB)", "Status" }; public BricksPage(Composite parent, int style, IWorkbenchSite site, final List<Brick> bricks) { - super(site, parent, style, bricks); + super(site, parent, style, true, true, bricks); this.bricks = bricks; } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java index 87644622..be4df7ad 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/GlusterServersPage.java @@ -49,7 +49,7 @@ public class GlusterServersPage extends AbstractTableViewerPage<GlusterServer> { "IP Address(es)", "Number\nof CPUs", "Total\nMemory (GB)", "Free Space (GB)", "Total \n Space (GB)", "Status" }; // Removed "Preferred\nNetwork", public GlusterServersPage(IWorkbenchSite site, final Composite parent, int style, final EntityGroup<GlusterServer> servers) { - super(site, parent, style, servers); + super(site, parent, style, true, true, servers); this.glusterServers = servers.getEntities(); } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java index 48b8892c..f285dd9f 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/ServersPage.java @@ -55,7 +55,7 @@ public class ServersPage extends AbstractTableViewerPage<Server> { // "Total Disk\n Space (GB)", "Disk Space\nin Use (GB)"}; public ServersPage(final Composite parent, IWorkbenchSite site, EntityGroup<Server> serversGroup) { - super(site, parent, SWT.NONE, serversGroup); + super(site, parent, SWT.NONE, true, true, serversGroup); this.servers = serversGroup.getEntities(); } 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 new file mode 100644 index 00000000..03c4f7ac --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/TasksPage.java @@ -0,0 +1,116 @@ +/** + * TasksPage.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package com.gluster.storage.management.gui.views.pages; + +import java.util.List; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.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.TaskInfo; +import com.gluster.storage.management.gui.TasksTableLabelProvider; + +public class TasksPage extends AbstractTableViewerPage<TaskInfo> { + private List<TaskInfo> taskInfoList; + + public enum TASK_TABLE_COLUMN_INDICES { + TASK, STATUS + }; + + private static final String[] TASK_TABLE_COLUMN_NAMES = new String[] { "Task", "Status"}; + + + public TasksPage(IWorkbenchSite site, Composite parent, int style, Object taskInfo) { + super(site, parent, style, false, false, taskInfo); + this.taskInfoList = (List<TaskInfo>) taskInfo; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#createClusterListener() + */ + @Override + protected ClusterListener createClusterListener() { + return new DefaultClusterListener() { + @Override + public void taskAdded(TaskInfo taskInfo) { + refreshViewer(); + } + + @Override + public void taskRemoved(TaskInfo taskInfo) { + refreshViewer(); + } + + private void refreshViewer() { + tableViewer.refresh(); + parent.update(); + } + }; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#getColumnNames() + */ + @Override + protected String[] getColumnNames() { + return TASK_TABLE_COLUMN_NAMES; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#setColumnProperties(org.eclipse.swt.widgets.Table) + */ + @Override + protected void setColumnProperties(Table table) { + guiHelper.setColumnProperties(table, TASK_TABLE_COLUMN_INDICES.TASK.ordinal(), SWT.LEFT, 50); + guiHelper.setColumnProperties(table, TASK_TABLE_COLUMN_INDICES.STATUS.ordinal(), SWT.LEFT, 50); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#getLabelProvider() + */ + @Override + protected IBaseLabelProvider getLabelProvider() { + return new TasksTableLabelProvider(); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#getContentProvider() + */ + @Override + protected IContentProvider getContentProvider() { + return new ArrayContentProvider(); + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.views.pages.AbstractTableViewerPage#getAllEntities() + */ + @Override + protected List<TaskInfo> getAllEntities() { + return taskInfoList; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumeOptionsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumeOptionsPage.java index bd003f3b..956fc215 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumeOptionsPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumeOptionsPage.java @@ -40,6 +40,7 @@ import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -91,9 +92,9 @@ public class VolumeOptionsPage extends Composite { toolkit.paintBordersFor(this); setupPageLayout(); + addTopButton = createAddButton(); filterText = guiHelper.createFilterText(toolkit, this); - addTopButton = createAddButton(); setupOptionsTableViewer(filterText); addBottomButton = createAddButton(); @@ -114,48 +115,7 @@ public class VolumeOptionsPage extends Composite { } private Button createAddButton() { - Button button = toolkit.createButton(this, "&Add", SWT.FLAT); - button.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // add an empty option to be filled up by user - volume.setOption("", ""); - - tableViewer.refresh(); - tableViewer.setSelection(new StructuredSelection(getEntry(""))); - keyColumn.getViewer().editElement(getEntry(""), 0); // edit newly created entry - - // disable the add button AND search filter textbox till user fills up the new option - setAddButtonsEnabled(false); - filterText.setEnabled(false); - } - - private Entry<String, String> getEntry(String key) { - for (Entry<String, String> entry : volume.getOptions().entrySet()) { - if (entry.getKey().equals(key)) { - return entry; - } - } - return null; - } - }); - - // Make sure that add button is enabled only when search filter textbox is empty - filterText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - if (filterText.getText().length() > 0) { - setAddButtonsEnabled(false); - } else { - if (defaultVolumeOptions.size() == volume.getOptions().size()) { - setAddButtonsEnabled(false); - } else { - setAddButtonsEnabled(true); - } - } - } - }); - return button; + return toolkit.createButton(this, "&Add", SWT.FLAT); } private void registerListeners(final Composite parent) { @@ -243,11 +203,55 @@ public class VolumeOptionsPage extends Composite { return optionKey.equals(volume.getOptions().keySet().toArray()[volume.getOptions().size() - 1]); } }; + + SelectionListener addButtonSelectionListener = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + // add an empty option to be filled up by user + volume.setOption("", ""); + + tableViewer.refresh(); + tableViewer.setSelection(new StructuredSelection(getEntry(""))); + keyColumn.getViewer().editElement(getEntry(""), 0); // edit newly created entry + + // disable the add button AND search filter textbox till user fills up the new option + setAddButtonsEnabled(false); + filterText.setEnabled(false); + } + + private Entry<String, String> getEntry(String key) { + for (Entry<String, String> entry : volume.getOptions().entrySet()) { + if (entry.getKey().equals(key)) { + return entry; + } + } + return null; + } + }; + addTopButton.addSelectionListener(addButtonSelectionListener); + addBottomButton.addSelectionListener(addButtonSelectionListener); + + // Make sure that add button is enabled only when search filter textbox is empty + filterText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + if (filterText.getText().length() > 0) { + setAddButtonsEnabled(false); + } else { + if (defaultVolumeOptions.size() == volume.getOptions().size()) { + setAddButtonsEnabled(false); + } else { + setAddButtonsEnabled(true); + } + } + } + }); + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); } private void setupPageLayout() { - final GridLayout layout = new GridLayout(1, false); + final GridLayout layout = new GridLayout(2, false); layout.verticalSpacing = 10; layout.marginTop = 10; setLayout(layout); @@ -256,7 +260,7 @@ public class VolumeOptionsPage extends Composite { private void setupOptionsTable(Composite parent) { Table table = tableViewer.getTable(); table.setHeaderVisible(true); - table.setLinesVisible(false); + table.setLinesVisible(true); TableColumnLayout tableColumnLayout = createTableColumnLayout(); parent.setLayout(tableColumnLayout); @@ -337,7 +341,11 @@ public class VolumeOptionsPage extends Composite { private Composite createTableViewerComposite() { Composite tableViewerComposite = new Composite(this, SWT.NO); tableViewerComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); - tableViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.horizontalSpan = 2; + tableViewerComposite.setLayoutData(layoutData); + return tableViewerComposite; } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java index 3a8891d4..33eb6da7 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/pages/VolumesPage.java @@ -48,7 +48,7 @@ public class VolumesPage extends AbstractTableViewerPage<Volume> { "Number of\nBricks", "Transport Type", "Status" }; public VolumesPage(final Composite parent, IWorkbenchSite site, EntityGroup<Volume> volumes) { - super(site, parent, SWT.NONE, volumes); + super(site, parent, SWT.NONE, true, true, volumes); } @Override 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 1999762a..e824fee7 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 @@ -457,21 +457,15 @@ public class GlusterServersResource extends AbstractServersResource { return badRequestResponse("Disk name must not be empty!"); } - TaskResponse taskResponse = new TaskResponse(); InitializeDiskTask initializeTask = new InitializeDiskTask(diskName, serverName); - String taskId = null; try { - TaskInfo taskInfo = initializeTask.start(); - taskId = taskInfo.getId(); - if (taskInfo.isSuccess()) { - taskResource.addTask(initializeTask); - } - taskResponse.setData(taskInfo); - taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "")); + initializeTask.start(); + taskResource.addTask(initializeTask); + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS, clusterName, RESOURCE_TASKS, + initializeTask.getId()); } catch (ConnectionException e) { return errorResponse(e.getMessage()); } - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS, clusterName, RESOURCE_TASKS, taskId); } private void setGlusterUtil(GlusterUtil glusterUtil) { 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 index 4bf1c0cf..44d86b1b 100644 --- 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 @@ -20,9 +20,9 @@ */ 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.FORM_PARAM_OPERATION; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; @@ -40,26 +40,25 @@ 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.model.Status; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; import com.gluster.storage.management.core.model.Task; import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.response.TaskListResponse; -import com.gluster.storage.management.core.response.TaskResponse; +import com.gluster.storage.management.core.response.TaskInfoListResponse; import com.sun.jersey.spi.resource.Singleton; @Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) @Singleton -public class TasksResource { +public class TasksResource extends AbstractResource { private Map<String, Task> tasksMap = new HashMap<String, Task>(); public TasksResource() { } - - public void addTask(Task task) { // task should be one of MuigrateDiskTask, FormatDiskTask, etc + public void addTask(Task task) { tasksMap.put(task.getId(), task); } @@ -70,18 +69,11 @@ public class TasksResource { public List<TaskInfo> getAllTasksInfo() { List<TaskInfo> allTasksInfo = new ArrayList<TaskInfo>(); for (Map.Entry<String, Task> entry : tasksMap.entrySet()) { - allTasksInfo.add(entry.getValue().getTaskInfo()); + checkTaskStatus(entry.getKey()); + allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status } return allTasksInfo; } - - public List<Task> getAllTasks() { - List<Task> allTasks = new ArrayList<Task>(); - for (Map.Entry<String, Task> entry : tasksMap.entrySet()) { - allTasks.add(entry.getValue()); - } - return allTasks; - } public Task getTask(String taskId) { for (Map.Entry<String, Task> entry : tasksMap.entrySet()) { @@ -91,63 +83,95 @@ public class TasksResource { } return null; } - + @GET @Produces(MediaType.APPLICATION_XML) - public TaskListResponse getTasks() { - TaskListResponse taskListResponse = new TaskListResponse(); + 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 { - taskListResponse.setData(getAllTasksInfo()); - taskListResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "")); + Task task = checkTaskStatus(taskId); + return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML); } catch (GlusterRuntimeException e) { - taskListResponse.setStatus(new Status(e)); + return errorResponse(e.getMessage()); } - return taskListResponse; + } + + 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 TaskResponse performTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, - @FormParam(FORM_PARAM_OPERATION) String taskOperation) { + 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); - TaskInfo taskInfo = null; - TaskResponse taskResponse = new TaskResponse(); - + try { if (taskOperation.equals(RESTConstants.TASK_RESUME)) { - taskInfo = task.resume(); - } - if (taskOperation.equals(RESTConstants.TASK_PAUSE)) { - taskInfo = task.pause(); + 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(); } - if (taskOperation.equals(RESTConstants.TASK_STOP)) { - taskInfo = task.stop(); - } - taskResponse.setData(taskInfo); - taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "")); + // updateTask(taskId, taskOperation); + return (Response) acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS, clusterName, RESOURCE_TASKS, + taskId); + } catch(GlusterValidationException ve) { + return badRequestResponse(ve.getMessage()); } catch (GlusterRuntimeException e) { - taskResponse.setStatus(new Status(e)); + return errorResponse(e.getMessage()); } - return taskResponse; } @DELETE @Path("/{" + PATH_PARAM_TASK_ID + "}") @Produces(MediaType.APPLICATION_XML) - public TaskResponse deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, + public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, @QueryParam(FORM_PARAM_OPERATION) String taskOperation) { - TaskResponse taskResponse = new TaskResponse(); Task task = getTask(taskId); if (task == null) { - taskResponse.setStatus( new Status(Status.STATUS_CODE_FAILURE, "No such task " + taskId + "is found ")); + return notFoundResponse("Task [" + taskId + "] not found!"); } - if (taskOperation.equals("delete")) { - removeTask(task); - taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "Task [" + taskId - + "] removed successfully")); - } - return null; - } + + 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/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java index d29d859b..018cd301 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 @@ -23,6 +23,7 @@ package com.gluster.storage.management.server.tasks; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Task; 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.server.utils.SshUtil; @@ -36,13 +37,10 @@ public class InitializeDiskTask extends Task { private SshUtil sshUtil = new SshUtil(); public InitializeDiskTask( String serverName, String diskName) { - super(TASK_TYPE.DISK_FORMAT, diskName); + super(TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" + diskName, false, false, false); - getTaskInfo().setCanPause(false); - getTaskInfo().setCanStop(false); setServerName(serverName); setDiskName(diskName); - setTaskDescription(); } public InitializeDiskTask(TaskInfo info) { @@ -51,25 +49,27 @@ public class InitializeDiskTask extends Task { @Override public String getId() { - return getTaskInfo().getId(); + return taskInfo.getType() + "-" + serverName + ":" + diskName; } @Override - public TaskInfo resume() { + public void resume() { getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not resume disk initialization"))); - return getTaskInfo(); } @Override - public TaskInfo stop() { + public void stop() { getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not stop disk initialization"))); - return getTaskInfo(); } @Override - public TaskInfo pause() { + public void pause() { getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not suspend disk initialization"))); - return getTaskInfo(); + } + + @Override + public void commit() { + // TODO Auto-generated method stub } @Override @@ -83,25 +83,16 @@ public class InitializeDiskTask extends Task { } @Override - public TaskInfo start() { + public void start() { getTaskInfo().setStatus( new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_SCRIPT + " " + getDiskName())))); - return getTaskInfo(); - } - - @Override - public TaskInfo status() { - getTaskInfo().setStatus( - - new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_STATUS_SCRIPT + " " - + getDiskName())))); - return getTaskInfo(); } @Override - public void setTaskDescription() { - getTaskInfo().setDescription("Formating disk of " + getServerName() + ":" + getDiskName()); + public TaskStatus checkStatus() { + return new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_STATUS_SCRIPT + " " + + getDiskName()))); } public void setDiskName(String diskName) { 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 df637ab1..0b1b67e4 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 @@ -20,12 +20,13 @@ */ package com.gluster.storage.management.server.tasks; -import org.springframework.beans.factory.annotation.Autowired; - +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Task; 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.utils.SshUtil; public class MigrateDiskTask extends Task { @@ -60,67 +61,113 @@ public class MigrateDiskTask extends Task { this.autoCommit = autoCommit; } - public MigrateDiskTask(TASK_TYPE type, String volumeName, String fromBrick, String toBrick) { - super(type, volumeName); + public MigrateDiskTask(String volumeName, String fromBrick, String toBrick) { + super(TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" + volumeName + "] from [" + fromBrick + + "] to [" + toBrick + "]", true, true, true); setFromBrick(fromBrick); setToBrick(toBrick); - setTaskDescription(); - getTaskInfo().setCanPause(true); - getTaskInfo().setCanStop(true); } public MigrateDiskTask(TaskInfo info) { super(info); - setTaskDescription(); } @Override public String getId() { - return getTaskInfo().getId(); + return taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + toBrick; } @Override - public TaskInfo start() { - getTaskInfo().setStatus( - new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick " - + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " start" ) ))); - return getTaskInfo(); + public void start() { + String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + + getToBrick() + " start"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches(".*started successfully$")) { + 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 + getTaskInfo().setStatus(taskStatus); } + + @Override - public TaskInfo resume() { - return start(); + public void pause() { + String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + + " pause"; + + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().matches("*pause")) { + taskStatus.setCode(Status.STATUS_CODE_PAUSE); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + getTaskInfo().setStatus(taskStatus); } - + + @Override - public TaskInfo stop() { - getTaskInfo().setStatus( - new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick " - + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " abort" ) ))); - return getTaskInfo(); + public void resume() { + start(); } - + @Override - public TaskInfo pause() { - getTaskInfo().setStatus( - new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick " - + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " pause" ) ))); - return getTaskInfo(); - + public void commit() { + // TODO Auto-generated method stub } - @Override - public void setTaskDescription() { - TaskInfo taskInfo = getTaskInfo(); - getTaskInfo().setDescription( - getTypeStr() + " on volume [" + taskInfo.getReference() + "] from [" + getFromBrick() - + "] to [" + getToBrick() + "]"); + public void stop() { + 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); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + getTaskInfo().setStatus(taskStatus); } @Override - public TaskInfo status() { - return getTaskInfo(); + public TaskStatus checkStatus() { + 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_SUCCESS); + } 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 + return taskStatus; } } 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 670ffb5c..dc95f50a 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,8 +36,7 @@ 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.Task.TASK_TYPE; -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.Volume; import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; @@ -539,17 +538,20 @@ public class GlusterUtil { public String migrateBrickStart(String volumeName, String fromBrick, String toBrick, Boolean autoCommit, String knownServer) { - MigrateDiskTask migrateDiskTask = new MigrateDiskTask(TASK_TYPE.BRICK_MIGRATE, volumeName, fromBrick, toBrick); + MigrateDiskTask migrateDiskTask = new MigrateDiskTask(volumeName, fromBrick, toBrick); migrateDiskTask.setOnlineServer(knownServer); migrateDiskTask.setAutoCommit(autoCommit); - - TaskInfo taskInfo = migrateDiskTask.start(); - if (taskInfo.isSuccess()) { + migrateDiskTask.start(); + int status = migrateDiskTask.getTaskInfo().getStatus().getCode(); + if (status != Status.STATUS_CODE_FAILURE ) { + TasksResource tasksResource = new TasksResource(); taskResource.addTask(migrateDiskTask); + } else { + throw new GlusterRuntimeException( migrateDiskTask.getTaskInfo().getStatus().getMessage()); } - - return taskInfo.getId(); + return migrateDiskTask.getId(); } + public Status removeBricks(String volumeName, List<String> bricks, String knownServer) { StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName); |
