diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-03-22 17:53:14 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-03-22 17:53:14 +0530 |
| commit | c0767db8bf79afd62cdb750558ab7db1a227838f (patch) | |
| tree | 86e64122f70f8a03a3a9dbe677ac1be89948490a | |
| parent | 97964bbc552cf0c3a86d0dff8ba00d930f60fd5d (diff) | |
story#21 Start Volume
13 files changed, 202 insertions, 38 deletions
diff --git a/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java index 45e61e8e..58067a82 100644 --- a/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java +++ b/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java @@ -26,11 +26,13 @@ import java.util.List; import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.Disk; import com.gluster.storage.management.core.model.Disk.DISK_STATUS; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.GlusterDataModel; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS; -import com.gluster.storage.management.core.model.IClusterListener; +import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.LogMessage; import com.gluster.storage.management.core.model.NetworkInterface; import com.gluster.storage.management.core.model.Server; @@ -49,7 +51,7 @@ public class GlusterDataModelManager { private GlusterDataModel model; private String securityToken; private String serverName; - private List<IClusterListener> listeners = new ArrayList<IClusterListener>(); + private List<ClusterListener> listeners = new ArrayList<ClusterListener>(); private GlusterDataModelManager() { } @@ -298,7 +300,7 @@ public class GlusterDataModelManager { return disks; } - public void addClusterListener(IClusterListener listener) { + public void addClusterListener(ClusterListener listener) { listeners.add(listener); } @@ -306,7 +308,7 @@ public class GlusterDataModelManager { Cluster cluster = (Cluster)model.getChildren().get(0); cluster.addServer(server); - for(IClusterListener listener : listeners) { + for(ClusterListener listener : listeners) { listener.serverAdded(server); } } @@ -315,8 +317,15 @@ public class GlusterDataModelManager { Cluster cluster = (Cluster)model.getChildren().get(0); cluster.removeDiscoveredServer(server); - for(IClusterListener listener : listeners) { + for(ClusterListener listener : listeners) { listener.discoveredServerRemoved(server); } } + + public void updateVolumeStatus(Volume volume, VOLUME_STATUS newStatus) { + volume.setStatus(newStatus); + for(ClusterListener listener : listeners) { + listener.volumeChanged(volume, new Event(EVENT_TYPE.VOLUME_STATUS_CHANGED, newStatus)); + } + } } diff --git a/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java b/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java index 10c64e28..d2e870e7 100644 --- a/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java +++ b/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java @@ -23,14 +23,16 @@ package com.gluster.storage.management.client; import java.util.ArrayList; import java.util.List; +import com.gluster.storage.management.core.constants.RESTConstants; import com.gluster.storage.management.core.model.Disk; import com.gluster.storage.management.core.model.Disk.DISK_STATUS; import com.gluster.storage.management.core.model.GenericResponse; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; +import com.sun.jersey.api.representation.Form; public class VolumesClient extends AbstractClient { - private static final String RESOURCE_NAME = "/cluster/volumes"; + private static final String RESOURCE_NAME = "/cluster/volumes"; // TODO: move to common place public VolumesClient(String serverName, String securityToken) { super(serverName, securityToken); @@ -46,10 +48,22 @@ public class VolumesClient extends AbstractClient { GenericResponse<String> response = (GenericResponse<String>) postObject(GenericResponse.class, volume); return response.getStatus(); } + + private Status performOperation(String volumeName, String operation) { + Form form = new Form(); + form.add(RESTConstants.FORM_PARAM_OPERATION, operation); + + return (Status)putRequest(volumeName, Status.class, form); + } + + public Status startVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_START); + } + + public Status stopVolume(String volumeName) { + return performOperation(volumeName, RESTConstants.FORM_PARAM_VALUE_STOP); + } - /** - * @param args - */ public static void main(String[] args) { UsersClient usersClient = new UsersClient("localhost"); if (usersClient.authenticate("gluster", "gluster")) { diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java index abd8ba4b..177334bd 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java @@ -18,8 +18,6 @@ *******************************************************************************/ package com.gluster.storage.management.core.constants; -import java.util.ArrayList; -import java.util.List; /** * diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java new file mode 100644 index 00000000..63cc560a --- /dev/null +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -0,0 +1,33 @@ +/** + * RESTConstants.java + * + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + */ +package com.gluster.storage.management.core.constants; + +/** + * All constants related to the Gluster REST server and client + */ +public class RESTConstants { + // Constants related to Volumes Resource + public static final String PATH_RESOURCE_VOLUMES = "/cluster/volumes"; + public static final String FORM_PARAM_OPERATION = "operation"; + public static final String FORM_PARAM_VALUE_START = "start"; + public static final String FORM_PARAM_VALUE_STOP = "stop"; + public static final String PATH_PARAM_VOLUME_NAME = "volumeName"; +} diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/IClusterListener.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java index 46d56ab4..85cdd872 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/IClusterListener.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java @@ -22,7 +22,7 @@ package com.gluster.storage.management.core.model; * Interface for a cluster listener. Every registered listener will be notified * on various events happening on the cluster. */ -public interface IClusterListener { +public interface ClusterListener { public void discoveredServerAdded(Server server); public void discoveredServerRemoved(Server server); diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java index 46d9ca55..bf76de43 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java @@ -22,7 +22,7 @@ package com.gluster.storage.management.core.model; * Default listener - doesn't do anything. Sub-class and override the method for * the event you want to handle. */ -public class DefaultClusterListener implements IClusterListener { +public class DefaultClusterListener implements ClusterListener { @Override public void serverAdded(GlusterServer server) { diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java index 8435f998..65501a2b 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Event.java @@ -23,7 +23,8 @@ public class Event { DISK_ADDED, DISK_REMOVED, NETWORK_INTERFACE_ADDED, - NETWORK_INTERFACE_REMOVED + NETWORK_INTERFACE_REMOVED, + VOLUME_STATUS_CHANGED } private EVENT_TYPE eventType; @@ -33,4 +34,20 @@ public class Event { this.eventType = eventType; this.eventData = eventData; } + + public EVENT_TYPE getEventType() { + return eventType; + } + + public void setEventType(EVENT_TYPE eventType) { + this.eventType = eventType; + } + + public Object getEventData() { + return eventData; + } + + public void setEventData(Object eventData) { + this.eventData = eventData; + } } diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java index 77a3e001..340b297f 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java @@ -48,6 +48,7 @@ public class Status { public Status(ProcessResult result) { this.code = result.getExitValue(); + this.message = result.getOutput(); } @XmlElement(name = "code", type = Integer.class) diff --git a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java index 683e6c00..81208eff 100644 --- a/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java +++ b/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterUtil.java @@ -117,9 +117,6 @@ public class GlusterUtil { return glusterServerNames; } - /** - * @return - */ private String getPeerStatus() { String output; ProcessResult result = processUtil.executeCommand("gluster", "peer", "status"); @@ -133,6 +130,14 @@ public class GlusterUtil { public ProcessResult addServer(String serverName) { return processUtil.executeCommand("gluster", "peer", "probe", serverName); } + + public ProcessResult startVolume(String volumeName) { + return processUtil.executeCommand("gluster", "volume", "start", volumeName); + } + + public ProcessResult stopVolume(String volumeName) { + return processUtil.executeCommand("gluster", "--mode=script", "volume", "stop", volumeName); + } public static void main(String args[]) { List<String> names = new GlusterUtil().getGlusterServerNames(); diff --git a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java index 6dbe6315..dec94f12 100644 --- a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java +++ b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/StartVolumeAction.java @@ -19,21 +19,39 @@ package com.gluster.storage.management.gui.actions; import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.client.VolumesClient; +import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; public class StartVolumeAction extends AbstractActionDelegate { + private Volume volume; + GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); @Override public void run(IAction action) { - System.out.println("Running [" + this.getClass().getSimpleName() + "]"); + VolumesClient client = new VolumesClient(modelManager.getServerName(), modelManager.getSecurityToken()); + Status status = client.startVolume(volume.getName()); + if (status.isSuccess()) { + new MessageDialog(Display.getDefault().getActiveShell(), "Create Volume", null, "Volume [" + + volume.getName() + "] started successfully!", MessageDialog.INFORMATION, new String[] { "OK" }, 0) + .open(); + modelManager.updateVolumeStatus(volume, VOLUME_STATUS.ONLINE); + } else { + new MessageDialog(Display.getDefault().getActiveShell(), "Create Volume", null, "Volume [" + + volume.getName() + "] could not be started! Error: [" + status + "]", MessageDialog.ERROR, + new String[] { "OK" }, 0).open(); + } } @Override public void dispose() { - System.out.println("Disposing [" + this.getClass().getSimpleName() + "]"); + } /* @@ -48,7 +66,7 @@ public class StartVolumeAction extends AbstractActionDelegate { super.selectionChanged(action, selection); if (selectedEntity instanceof Volume) { - Volume volume = (Volume) selectedEntity; + volume = (Volume) selectedEntity; action.setEnabled(volume.getStatus() == VOLUME_STATUS.OFFLINE); } } diff --git a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java index 8618c1da..35b5cd7a 100644 --- a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java +++ b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/NavigationView.java @@ -37,8 +37,10 @@ import org.eclipse.ui.part.ViewPart; import com.gluster.storage.management.client.GlusterDataModelManager; import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.Entity; +import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.GlusterDataModel; import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; import com.gluster.storage.management.gui.views.navigator.ClusterAdapterFactory; @@ -86,6 +88,19 @@ public class NavigationView extends ViewPart implements ISelectionListener { public void serverAdded(GlusterServer server) { treeViewer.refresh(); } + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.core.model.DefaultClusterListener#volumeChanged(com.gluster.storage.management + * .core.model.Volume, com.gluster.storage.management.core.model.Event) + */ + @Override + public void volumeChanged(Volume volume, Event event) { + treeViewer.refresh(); + selectEntity(volume); // this makes sure that the toolbar buttons get updated accoring to new status + } }); } diff --git a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java index 99ac0e0b..396c5419 100644 --- a/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java +++ b/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java @@ -16,11 +16,17 @@ import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.ViewPart; +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.DefaultClusterListener; +import com.gluster.storage.management.core.model.Event; +import com.gluster.storage.management.core.model.Event.EVENT_TYPE; +import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.utils.NumberUtil; import com.gluster.storage.management.gui.IImageKeys; +import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; import com.gluster.storage.management.gui.utils.GUIHelper; public class VolumeSummaryView extends ViewPart { @@ -29,6 +35,7 @@ public class VolumeSummaryView extends ViewPart { private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); private ScrolledForm form; private Volume volume; + private CLabel lblStatusValue; @Override public void createPartControl(Composite parent) { @@ -37,6 +44,20 @@ public class VolumeSummaryView extends ViewPart { } createSections(parent); + + // Refresh the navigation tree whenever there is a change to the data model + GlusterDataModelManager.getInstance().addClusterListener(new DefaultClusterListener() { + /* (non-Javadoc) + * @see com.gluster.storage.management.core.model.DefaultClusterListener#volumeChanged(com.gluster.storage.management.core.model.Volume, com.gluster.storage.management.core.model.Event) + */ + @Override + public void volumeChanged(Volume volume, Event event) { + if(event.getEventType() == EVENT_TYPE.VOLUME_STATUS_CHANGED) { + updateVolumeStatusLabel(); + new GlusterToolbarManager(getSite().getWorkbenchWindow()).updateToolbar(volume); + } + } + }); } private void createSections(Composite parent) { @@ -192,12 +213,16 @@ public class VolumeSummaryView extends ViewPart { private void createStatusField(Composite section) { toolkit.createLabel(section, "Status: ", SWT.NONE); - CLabel lblStatusValue = new CLabel(section, SWT.NONE); + lblStatusValue = new CLabel(section, SWT.NONE); + updateVolumeStatusLabel(); + + toolkit.createLabel(section, "", SWT.NONE); // dummy + } + + private void updateVolumeStatusLabel() { lblStatusValue.setText(volume.getStatusStr()); lblStatusValue.setImage(volume.getStatus() == Volume.VOLUME_STATUS.ONLINE ? guiHelper .getImage(IImageKeys.STATUS_ONLINE) : guiHelper.getImage(IImageKeys.STATUS_OFFLINE)); - - toolkit.createLabel(section, "", SWT.NONE); // dummy } private void createTransportTypeField(Composite section) { diff --git a/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java index abd4411d..c370fd53 100644 --- a/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ b/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -20,12 +20,21 @@ */ package com.gluster.storage.management.server.resources; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_START; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VALUE_STOP; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.PATH_RESOURCE_VOLUMES; + import java.util.ArrayList; import java.util.List; import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @@ -35,52 +44,57 @@ import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.GlusterUtil; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.core.utils.ProcessUtil; +import com.sun.jersey.spi.resource.Singleton; -@Path("/cluster/volumes") +@Singleton +@Path(PATH_RESOURCE_VOLUMES) public class VolumesResource { + private final GlusterUtil glusterUtil = new GlusterUtil(); @POST @Consumes(MediaType.TEXT_XML) @Produces(MediaType.TEXT_XML) public GenericResponse<String> createVolume(Volume volume) { - - int count=1; // replica or stripe count + + int count = 1; // replica or stripe count String volumeType = null; - VOLUME_TYPE volType = volume.getVolumeType(); - if(volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + VOLUME_TYPE volType = volume.getVolumeType(); + if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { volumeType = "replica"; count = 2; - } else if(volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { volumeType = "stripe"; count = 4; } - + String transportTypeStr = null; TRANSPORT_TYPE transportType = volume.getTransportType(); - transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; - + transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + List<String> command = new ArrayList<String>(); command.add("gluster"); command.add("volume"); command.add("create"); command.add(volume.getName()); - if(volumeType != null) { + if (volumeType != null) { command.add(volumeType); command.add("" + count); } command.add("transport"); command.add(transportTypeStr); - - for(Disk disk : volume.getDisks()) { + + for (Disk disk : volume.getDisks()) { command.add(getBrickNotation(volume, disk)); } - + ProcessResult result = new ProcessUtil().executeCommand(command); - + if (!result.isSuccess()) { - return new GenericResponse<String>(Status.STATUS_FAILURE, "Volume creation failed: [" + result.getOutput() + "]"); + return new GenericResponse<String>(Status.STATUS_FAILURE, "Volume creation failed: [" + result.getOutput() + + "]"); } return new GenericResponse<String>(Status.STATUS_SUCCESS, "Volume created successfully!"); } @@ -94,4 +108,19 @@ public class VolumesResource { String dirName = "/export/" + vol.getName() + "/" + disk.getName(); return disk.getServerName() + ":" + dirName; } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.TEXT_XML) + public Status performOperation(@FormParam(FORM_PARAM_OPERATION) String operation, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + + if (operation.equals(FORM_PARAM_VALUE_START)) { + return new Status(glusterUtil.startVolume(volumeName)); + } + if (operation.equals(FORM_PARAM_VALUE_STOP)) { + return new Status(glusterUtil.stopVolume(volumeName)); + } + return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + } } |
