diff options
| author | Selvam <selvam@gluster.com> | 2011-04-20 10:55:26 +0530 |
|---|---|---|
| committer | Selvam <selvam@gluster.com> | 2011-04-28 17:57:17 +0530 |
| commit | 98da4383c37046e81f83bf9bf98ec077e94134b8 (patch) | |
| tree | c4669777417867a1eb3de7ba4fd7d1eefc19e510 /src | |
| parent | c11192c4cf06f14ad90d72819ebeee2ad527f16d (diff) | |
Story #18 Add disk, UI, REST client and REST Resource
Diffstat (limited to 'src')
10 files changed, 452 insertions, 46 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java index 05b89306..7ce2028f 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java @@ -20,7 +20,11 @@ */ 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.Status; import com.gluster.storage.management.core.model.Volume; import com.gluster.storage.management.core.response.VolumeListResponse; @@ -84,6 +88,12 @@ public class VolumesClient extends AbstractClient { return ((VolumeOptionInfoListResponse) fetchSubResource(RESTConstants.SUBRESOURCE_DEFAULT_OPTIONS, VolumeOptionInfoListResponse.class)); } + + public Status addDisks(String volumeName, String disks) { + Form form = new Form(); + form.add(RESTConstants.QUERY_PARAM_DISKS, disks); + return (Status) postRequest(volumeName + "/" + RESTConstants.SUBRESOURCE_DISKS, Status.class, form); + } public static void main(String[] args) { UsersClient usersClient = new UsersClient(); @@ -105,8 +115,11 @@ public class VolumesClient extends AbstractClient { // for (VolumeOptionInfo option : client.getVolumeOptionsDefaults()) { // System.out.println(option.getName() + "-" + option.getDescription() + "-" + option.getDefaultValue()); // } - System.out.println(client.getVolume("Volume3").getOptions()); - System.out.println(client.setVolumeOption("Volume3", "network.frame-timeout", "600").getMessage()); +// System.out.println(client.getVolume("Volume3").getOptions()); +// System.out.println(client.setVolumeOption("Volume3", "network.frame-timeout", "600").getMessage()); + + Status status = client.addDisks("Volume3", "server1:sda, server1:sdb, server1:sdc"); + System.out.println(status.getMessage()); } } } 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 0aa286a3..4bd0d292 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 @@ -29,6 +29,7 @@ public class RESTConstants { public static final String SUBRESOURCE_DEFAULT_OPTIONS = "defaultoptions"; public static final String SUBRESOURCE_OPTIONS = "options"; public static final String SUBRESOURCE_LOGS = "logs"; + public static final String SUBRESOURCE_DISKS = "disks"; public static final String FORM_PARAM_OPERATION = "operation"; @@ -41,6 +42,7 @@ public class RESTConstants { public static final String FORM_PARAM_DELETE_OPTION = "value"; public static final String QUERY_PARAM_DISK_NAME = "diskName"; + public static final String QUERY_PARAM_DISKS = "disks"; public static final String QUERY_PARAM_LINE_COUNT = "lineCount"; public static final String QUERY_PARAM_VOLUME_NAME = "volumeName"; public static final String QUERY_PARAM_DELETE_OPTION = "deleteOption"; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java index 94b23179..e01a35b3 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java @@ -49,6 +49,10 @@ public class Volume extends Entity { GLUSTERFS, NFS }; + + public static final int DEFAULT_REPLICA_COUNT = 2; + public static final int DEFAULT_STRIPE_COUNT = 2; + public static final String OPTION_AUTH_ALLOW = "auth.allow"; private static final String[] VOLUME_TYPE_STR = new String[] { "Plain Distribute", "Distributed Mirror", @@ -104,9 +108,9 @@ public class Volume extends Entity { // TODO find a way to get the replica / strip count if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { setReplicaCount(0); - setStripeCount(3); + setStripeCount(DEFAULT_STRIPE_COUNT); } else if (volumeType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - setReplicaCount(2); + setReplicaCount(DEFAULT_REPLICA_COUNT); setStripeCount(0); } else { setReplicaCount(0); diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java index 45f4c436..aed9c80c 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java @@ -18,15 +18,26 @@ *******************************************************************************/ package com.gluster.storage.management.core.utils; +import java.util.List; + public class StringUtil { - public static boolean filterString(String sourceString, - String filterString, boolean caseSensitive) { - return caseSensitive ? sourceString.contains(filterString) - : sourceString.toLowerCase().contains( - filterString.toLowerCase()); + public static boolean filterString(String sourceString, String filterString, boolean caseSensitive) { + return caseSensitive ? sourceString.contains(filterString) : sourceString.toLowerCase().contains( + filterString.toLowerCase()); } - + public static String removeSpaces(String str) { return str.replaceAll("\\s+", ""); } + + public static String ListToString(List<String> list, String delimiter) { + StringBuilder output = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + output.append(list.get(i)); + if (i < (list.size()-1) ) { + output.append(delimiter); + } + } + return output.toString(); + } } diff --git a/src/com.gluster.storage.management.gui/plugin.xml b/src/com.gluster.storage.management.gui/plugin.xml index 97a60ad1..8004b47e 100644 --- a/src/com.gluster.storage.management.gui/plugin.xml +++ b/src/com.gluster.storage.management.gui/plugin.xml @@ -251,6 +251,12 @@ id="com.gluster.storage.management.gui.commands.MigrateDisk" name="Migrate Disk"> </command> + <command + categoryId="com.gluster.storage.management.gui.category" + description="Add Disk" + id="com.gluster.storage.management.gui.commands.AddDisk" + name="Add Disk"> + </command> </extension> <extension point="org.eclipse.ui.bindings"> @@ -491,11 +497,6 @@ style="push" toolbarPath="Normal" tooltip="Migrate Disk"> - <enablement> - <objectClass - name="com.gluster.storage.management.core.model.Disk"> - </objectClass> - </enablement> </action> <action allowLabelUpdate="false" @@ -577,6 +578,22 @@ toolbarPath="Normal" tooltip="Start Volume"> </action> + <action + allowLabelUpdate="false" + class="com.gluster.storage.management.gui.actions.AddDiskAction" + definitionId="com.gluster.storage.management.gui.commands.AddDisk" + icon="icons/disk.png" + id="com.gluster.storage.management.gui.actions.AddDiskAction" + label="&Add Disk" + menubarPath="com.gluster.storage.management.gui.menu.volume/volume" + mode="FORCE_TEXT" + pulldown="false" + retarget="false" + state="false" + style="push" + toolbarPath="Normal" + tooltip="Add disk to the volume"> + </action> <menu id="com.gluster.storage.management.gui.menu.volume" label="&Gluster" diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java new file mode 100644 index 00000000..befa3e37 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/actions/AddDiskAction.java @@ -0,0 +1,65 @@ +package com.gluster.storage.management.gui.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Display; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.gui.dialogs.AddDiskWizard; + +public class AddDiskAction extends AbstractActionDelegate { + private Volume volume; + private GlusterDataModelManager modelManager = GlusterDataModelManager.getInstance(); + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() + */ + @Override + public void dispose() { + window = null; + } + + /* (non-Javadoc) + * @see com.gluster.storage.management.gui.actions.AbstractActionDelegate#performAction(org.eclipse.jface.action.IAction) + */ + @Override + protected void performAction(IAction action) { + //TODO: open a dialog box + // MessageDialog.openInformation(getShell(), "Action captured", action.getDescription() + "\n" + volume.getName()); + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + AddDiskWizard wizard = new AddDiskWizard(); + wizard.addPages(volume); + + WizardDialog dialog = new WizardDialog(getShell(), wizard); + dialog.create(); + dialog.getShell().setSize(1024, 600); + dialog.open(); + } + }); + + } + + + /* + * (non-Javadoc) + * + * @see + * com.gluster.storage.management.gui.actions.AbstractActionDelegate#selectionChanged(org.eclipse.jface.action.IAction + * , org.eclipse.jface.viewers.ISelection) + */ + @Override + public void selectionChanged(IAction action, ISelection selection) { + super.selectionChanged(action, selection); + + if (selectedEntity instanceof Volume) { + this.volume = (Volume) selectedEntity; + // action.setEnabled(volume.getStatus() == VOLUME_STATUS.ONLINE); + } + } + +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java new file mode 100644 index 00000000..f8046a13 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskPage.java @@ -0,0 +1,101 @@ +/** + * AddDiskPage.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.dialogs; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import com.gluster.storage.management.client.GlusterDataModelManager; +import com.gluster.storage.management.core.model.Disk; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; + +/** + * @author root + * + */ +public class AddDiskPage extends WizardPage { + private List<Disk> availableDisks = new ArrayList<Disk>(); + private List<Disk> selectedDisks = new ArrayList<Disk>(); + private Volume volume = null; + private CreateVolumeDisksPage page = null; + + public static final String PAGE_NAME = "add.disk.volume.page"; + + /** + * @param pageName + */ + protected AddDiskPage(Volume volume) { + super(PAGE_NAME); + this.volume = volume; + setTitle("Add Disk"); + + String description = "Add disks to the Volume by choosing disks from the cluster servers.\n"; + if ( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + description += "(Disk selection should be multiples of " + volume.getReplicaCount() + ")"; + } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + description += "(Disk selection should be multiples of " + volume.getStripeCount() + ")"; + } + setDescription(description); + + availableDisks = getAvailableDisks(volume); + } + + protected List<Disk> getAvailableDisks(Volume volume) { + List<Disk> availableDisks = new ArrayList<Disk>(); + boolean isDiskAlreadyUsedInTheVolume = false; + for (Disk disk : GlusterDataModelManager.getInstance().getReadyDisksOfAllServers()) { + isDiskAlreadyUsedInTheVolume = false; + for (String volumeDisk : volume.getDisks()) { // volumeDisk of the form "server:diskName" + if (disk.getServerName().equals(volumeDisk.split(":")[0]) + && disk.getName().equals(volumeDisk.split(":")[1])) { + isDiskAlreadyUsedInTheVolume = true; + break; + } + } + if (!isDiskAlreadyUsedInTheVolume) { + availableDisks.add(disk); + } + } + return availableDisks; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createControl(Composite parent) { + getShell().setText("Add Disk"); + List<Disk> configuredDisks = new ArrayList<Disk>(); // or volume.getDisks(); + page = new CreateVolumeDisksPage(parent, SWT.NONE, availableDisks, configuredDisks); + setControl(page); + } + + public CreateVolumeDisksPage getDialogPage() { + return this.page; + } +} diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java new file mode 100644 index 00000000..5d096764 --- /dev/null +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/dialogs/AddDiskWizard.java @@ -0,0 +1,127 @@ +/** + * AddDiskWizard.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.dialogs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; +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.Disk; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.StringUtil; + +/** + * + */ +public class AddDiskWizard extends Wizard { + private AddDiskPage page; + private Volume volume; + + public AddDiskWizard() { + setWindowTitle("Gluster Management Console - Add disk"); + setHelpAvailable(false); // TODO: Introduce wizard help + } + + public void addPages(Volume volume) { + this.volume = volume; + page = new AddDiskPage(volume); + addPage(page); + } + + private String getDiskNames(List<Disk> disks) { + List<String> diskNames = new ArrayList<String>(); + for (Disk disk : disks) { + diskNames.add(disk.getServerName() + ":" + disk.getName()); + } + return StringUtil.ListToString(diskNames, ","); + } + + private boolean isValidDiskSelection(int diskCount) { + switch (volume.getVolumeType()) { + case PLAIN_DISTRIBUTE: + return (diskCount > 0); + case DISTRIBUTED_MIRROR: + return (diskCount % volume.getReplicaCount() == 0 && diskCount > 0); + case DISTRIBUTED_STRIPE: + return (diskCount % volume.getStripeCount() == 0 && diskCount > 0); + } + return false; + } + + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + List<Disk> disks = page.getDialogPage().getChosenDisks(); + String selectedDisks = getDiskNames(disks); + List<String> diskList = Arrays.asList(selectedDisks.split(":")); + if (isValidDiskSelection(disks.size())) { + VolumesClient volumeClient = new VolumesClient(GlusterDataModelManager.getInstance().getSecurityToken()); + try { + Status status = volumeClient.addDisks(volume.getName(), getDiskNames(disks)); + if (!status.isSuccess()) { + MessageDialog.openError(getShell(), "Add disk failure", status.getMessage()); + return status.isSuccess(); + } else { + volume.addDisks(diskList); + MessageDialog.openInformation(getShell(), "Add Disk", status.getMessage()); + return status.isSuccess(); + } + } catch (Exception e) { + MessageDialog.openError(getShell(), "Add disk failure", e.getMessage()); + return false; + } + } else { + String errorMessage = ""; + if ( volume.getVolumeType() == VOLUME_TYPE.PLAIN_DISTRIBUTE) { + errorMessage = "Atleast one disk required to add"; + } else if( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + errorMessage = "Multiples of " + volume.getReplicaCount() + " disks are required to add"; + } else { + errorMessage = "Multiples of " + volume.getStripeCount() + " disks are required to add"; + } + MessageDialog.openError(getShell(), "Add disk failure", errorMessage); + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.wizard.Wizard#canFinish() + */ + @Override + public boolean canFinish() { + // TODO: Add logic to return true only when all validations are successful + return super.canFinish(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java index e30462f2..73d2eee4 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java @@ -24,12 +24,14 @@ import static com.gluster.storage.management.core.constants.RESTConstants.FORM_P 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.QUERY_PARAM_DELETE_OPTION; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DISKS; import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DISK_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT; import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_VOLUME_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_VOLUMES; import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_DEFAULT_OPTIONS; +import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_DISKS; import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_LOGS; import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_OPTIONS; @@ -218,8 +220,11 @@ public class VolumesResource { String[] diskParts = disk.split(":"); String serverName = diskParts[0]; String diskName = diskParts[1]; - - status = prepareBrick(serverName, diskName, volumeName); + try { + status = prepareBrick(serverName, diskName, volumeName); + } catch (Exception e) { + status = new Status(e); + } if (status.isSuccess()) { String brickDir = status.getMessage().trim().replace(CoreConstants.NEWLINE, ""); bricks.add(serverName + ":" + brickDir); @@ -228,7 +233,7 @@ public class VolumesResource { Status cleanupStatus = cleanupDirectories(disks, volumeName, i + 1); if (!cleanupStatus.isSuccess()) { // append cleanup error to prepare brick error - status.setMessage(status.getMessage() + CoreConstants.NEWLINE + status.getMessage()); + status.setMessage(status.getMessage() + CoreConstants.NEWLINE + cleanupStatus.getMessage()); } return status; } @@ -237,6 +242,7 @@ public class VolumesResource { return status; } + //TODO Can be removed and use StringUtil.ListToString(List<String> list, String delimiter) private String bricksAsString(List<String> bricks) { String bricksStr = ""; for (String brickInfo : bricks) { @@ -245,6 +251,7 @@ public class VolumesResource { return bricksStr.trim(); } + @SuppressWarnings("rawtypes") private Status cleanupDirectories(List<String> disks, String volumeName, int maxIndex) { String serverName, diskName, diskInfo[]; Status result; @@ -252,8 +259,8 @@ public class VolumesResource { diskInfo = disks.get(i).split(":"); serverName = diskInfo[0]; diskName = diskInfo[1]; - result = (Status) serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " - + diskName + " " + volumeName, Status.class); + result = ((GenericResponse) serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + + diskName + " " + volumeName, GenericResponse.class)).getStatus(); if (!result.isSuccess()) { return result; } @@ -310,6 +317,26 @@ public class VolumesResource { return new LogMessageListResponse(Status.STATUS_SUCCESS, logMessages); } + + @POST + @Path("{" + QUERY_PARAM_VOLUME_NAME + "}/" + SUBRESOURCE_DISKS) + public Status addDisks(@PathParam(QUERY_PARAM_VOLUME_NAME) String volumeName, @FormParam(QUERY_PARAM_DISKS) String disks) { + + List<String> diskList = Arrays.asList( disks.split(",") ); // Convert from comma separated sting (query parameter) to list + Status status = createDirectories(diskList, volumeName); + if (status.isSuccess()) { + List<String> bricks = Arrays.asList(status.getMessage().split(" ")); + status = glusterUtil.addDisks(volumeName, bricks); + if (!status.isSuccess()) { + Status cleanupStatus = cleanupDirectories(diskList, volumeName, diskList.size()); + if (!cleanupStatus.isSuccess()) { + // append cleanup error to prepare brick error + status.setMessage(status.getMessage() + CoreConstants.NEWLINE + cleanupStatus.getMessage()); + } + } + } + return status; + } public static void main(String[] args) throws ClassNotFoundException { VolumesResource vr = new VolumesResource(); 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 6a60962f..8b2e13f1 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 @@ -48,6 +48,7 @@ public class GlusterUtil { private static final String VOLUME_NAME_PFX = "Volume Name:"; private static final String VOLUME_TYPE_PFX = "Type:"; private static final String VOLUME_STATUS_PFX = "Status:"; + private static final String VOLUME_NUMBER_OF_BRICKS = "Number of Bricks:"; private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; @@ -168,23 +169,22 @@ public class GlusterUtil { VOLUME_TYPE volType = volume.getVolumeType(); if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { volumeType = "replica"; - count = 2; + count = volume.getReplicaCount(); } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { volumeType = "stripe"; - count = 4; + count = volume.getStripeCount(); } String transportTypeStr = null; TRANSPORT_TYPE transportType = volume.getTransportType(); transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; - List<String> command = prepareVolumeCreateCommand(volume, bricks, count, volumeType, transportTypeStr); ProcessResult result = processUtil.executeCommand(command); - if(!result.isSuccess()) { + if (!result.isSuccess()) { // TODO: Perform cleanup on all nodes before returning return new Status(result); } - + return createOptions(volume); } @@ -235,7 +235,7 @@ public class GlusterUtil { public Status deleteVolume(String volumeName) { return new Status(processUtil.executeCommand("gluster", "--mode=script", "volume", "delete", volumeName)); } - + private String getVolumeInfo(String volumeName) { ProcessResult result = new ProcessUtil().executeCommand("gluster", "volume", "info", volumeName); if (!result.isSuccess()) { @@ -253,17 +253,41 @@ public class GlusterUtil { } return result.getOutput(); } - + private boolean readVolumeType(Volume volume, String line) { String volumeType = extractToken(line, VOLUME_TYPE_PFX); if (volumeType != null) { - volume.setVolumeType((volumeType.equals("Distribute")) ? VOLUME_TYPE.PLAIN_DISTRIBUTE - : VOLUME_TYPE.DISTRIBUTED_MIRROR); // TODO: for Stripe + if (volumeType.equals("Distribute")) { + volume.setVolumeType(VOLUME_TYPE.PLAIN_DISTRIBUTE); + } else if (volumeType.equals("Replicate")) { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_MIRROR); + volume.setReplicaCount(Volume.DEFAULT_REPLICA_COUNT ); + } else { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_STRIPE); + volume.setStripeCount(Volume.DEFAULT_STRIPE_COUNT ); + } return true; } return false; } - + + private void readBrickPair(Volume volume, String line) { + if (extractToken(line, "x") != null) { + int count = Integer.parseInt(line.split("x")[1].split("=")[0].trim()); + if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volume.setStripeCount(count); + } + else if ( volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volume.setReplicaCount( count ); + volume.setStripeCount(0); + } else { + volume.setStripeCount(0); + volume.setReplicaCount(0); + } + } + return; + } + private boolean readVolumeStatus(Volume volume, String line) { String volumeStatus = extractToken(line, VOLUME_STATUS_PFX); if (volumeStatus != null) { @@ -272,17 +296,16 @@ public class GlusterUtil { } return false; } - + private boolean readTransportType(Volume volume, String line) { String transportType = extractToken(line, VOLUME_TRANSPORT_TYPE_PFX); if (transportType != null) { - volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET - : TRANSPORT_TYPE.INFINIBAND); + volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET : TRANSPORT_TYPE.INFINIBAND); return true; } return false; } - + private boolean readBrick(Volume volume, String line) { if (line.matches("Brick[0-9]+:.*")) { // line: "Brick1: server1:/export/md0/volume-name" @@ -292,11 +315,11 @@ public class GlusterUtil { // brick directory should be of the form /export/<diskname>/volume-name try { volume.addDisk(serverName + ":" + brickDir.split("/")[2].trim()); - } catch(ArrayIndexOutOfBoundsException e) { + } catch (ArrayIndexOutOfBoundsException e) { // brick directory of a different form, most probably created manually // connect to the server and get disk for the brick directory Status status = new ServerUtil().getDiskForDir(serverName, brickDir); - if(status.isSuccess()) { + if (status.isSuccess()) { volume.addDisk(serverName + ":" + status.getMessage()); } else { // Couldn't fetch disk for the brick directory. Log error and add "unknown" as disk name. @@ -308,15 +331,15 @@ public class GlusterUtil { } return false; } - + private boolean readBrickGroup(String line) { - return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; + return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; } - + private boolean readOptionReconfigGroup(String line) { return extractToken(line, VOLUME_OPTIONS_RECONFIG_PFX) != null; } - + private boolean readOption(Volume volume, String line) { if (line.matches("^[^:]*:.*$")) { int index = line.indexOf(':'); @@ -328,7 +351,7 @@ public class GlusterUtil { public Volume getVolume(String volumeName) { List<Volume> volumes = parseVolumeInfo(getVolumeInfo(volumeName)); - if(volumes.size() > 0) { + if (volumes.size() > 0) { return volumes.get(0); } return null; @@ -348,7 +371,6 @@ public class GlusterUtil { String volumeName = extractToken(line, VOLUME_NAME_PFX); if (volumeName != null) { if (volume != null) { - volumes.add(volume); } @@ -361,11 +383,13 @@ public class GlusterUtil { if (readVolumeType(volume, line)) continue; + if (extractToken(line, VOLUME_NUMBER_OF_BRICKS) != null) { + readBrickPair(volume, line); + } if (readVolumeStatus(volume, line)) continue; - if(readTransportType(volume, line)) + if (readTransportType(volume, line)) continue; - if (readBrickGroup(line)) { isBricksGroupFound = true; continue; @@ -385,7 +409,7 @@ public class GlusterUtil { } if (isOptionReconfigFound) { - if(readOption(volume, line)) { + if (readOption(volume, line)) { continue; } else { isOptionReconfigFound = false; @@ -399,8 +423,23 @@ public class GlusterUtil { return volumes; } + public Status addDisks(String volumeName, List<String> bricks) { + List<String> command = new ArrayList<String>(); + command.add("gluster"); + command.add("volume"); + command.add("add-brick"); + command.add(volumeName); + command.addAll(bricks); + return new Status(processUtil.executeCommand(command)); + } + public static void main(String args[]) { // List<String> names = new GlusterUtil().getGlusterServerNames(); // System.out.println(names); + List<String> disks = new ArrayList<String>(); + disks.add("server1:sda"); + disks.add("server1:sdb"); + Status status = new GlusterUtil().addDisks("Volume3", disks); + System.out.println(status); } } |
