diff options
Diffstat (limited to 'src')
37 files changed, 1035 insertions, 287 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index 695fae19..c02d73b5 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()); } @@ -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..8e608983 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.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 ((TaskListResponse) fetchResource(TaskListResponse.class)).getTaskList(); } // see startMigration @ VolumesClient, etc 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/TaskListResponse.java index 2637b197..110f4e63 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/TaskListResponse.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 = "response") +public class TaskListResponse { + private List<TaskInfo> taskInfoList; - public void setStatus(Status status) { - this.status = status; - } + public TaskListResponse() { + } - public void setData(List<TaskInfo> taskList) { - this.taskList.clear(); - this.taskList.addAll(taskList); + public TaskListResponse(List<TaskInfo> taskInfoList) { + this.taskInfoList = taskInfoList; + } + + @XmlElement(name="TaskInfo", 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/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/utils/GUIHelper.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/GUIHelper.java index ac29ecf0..31d762ec 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(); @@ -450,6 +451,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..d86cede2 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,24 @@ 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.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 +68,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 +82,95 @@ public class TasksResource { } return null; } - + @GET @Produces(MediaType.APPLICATION_XML) - public TaskListResponse getTasks() { - TaskListResponse taskListResponse = new TaskListResponse(); + public Response getTasks() { + try { + return okResponse(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..1f044d77 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,12 @@ */ package com.gluster.storage.management.server.tasks; -import org.springframework.beans.factory.annotation.Autowired; - 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 +60,111 @@ 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().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().matches("*abort")) { + 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().matches("*Migration complete")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + return taskStatus; } } 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..0a0892f0 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,21 @@ 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); |
