summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java3
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java11
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java10
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java5
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java3
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/LogMessageListResponse.java42
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/VolumeListResponse.java4
-rw-r--r--src/com.gluster.storage.management.gui.feature/feature.xml7
-rw-r--r--src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF3
-rw-r--r--src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java45
-rw-r--r--src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java6
-rw-r--r--src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java189
-rw-r--r--src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java95
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java4
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java58
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java3
16 files changed, 375 insertions, 113 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java
index 6a22bf5f..eb6ef3a0 100644
--- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java
+++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/DiscoveredServersClient.java
@@ -41,6 +41,7 @@ public class DiscoveredServersClient extends AbstractClient {
return RESOURCE_NAME;
}
+ @SuppressWarnings("rawtypes")
private Object getDiscoveredServers(Boolean getDetails, Class responseClass) {
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
queryParams.putSingle("details", getDetails.toString());
@@ -48,10 +49,12 @@ public class DiscoveredServersClient extends AbstractClient {
return ((Response) fetchResource(queryParams, responseClass)).getData();
}
+ @SuppressWarnings("unchecked")
public List<String> getDiscoveredServerNames() {
return (List<String>) getDiscoveredServers(Boolean.FALSE, StringListResponse.class);
}
+ @SuppressWarnings("unchecked")
public List<Server> getDiscoveredServerDetails() {
return (List<Server>) getDiscoveredServers(Boolean.TRUE, ServerListResponse.class);
}
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 39141bc0..f44b24e5 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
@@ -26,17 +26,24 @@ package com.gluster.storage.management.core.constants;
public class RESTConstants {
// Volumes Resource
public static final String RESOURCE_PATH_VOLUMES = "/cluster/volumes";
+ 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 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 FORM_PARAM_OPTION_KEY = "key";
public static final String FORM_PARAM_VOLUME_NAME = "volumeName";
public static final String FORM_PARAM_OPTION_VALUE = "value";
+
public static final String PATH_PARAM_VOLUME_NAME = "volumeName";
public static final String FORM_PARAM_DELETE_OPTION = "value";
- public static final String SUBRESOURCE_DEFAULT_OPTIONS = "defaultoptions";
- public static final String SUBRESOURCE_OPTIONS = "options";
+ public static final String QUERY_PARAM_DISK_NAME = "diskName";
+ public static final String QUERY_PARAM_LINE_COUNT = "lineCount";
+
// Running tasks resource
public static final String RESOURCE_PATH_RUNNING_TASKS = "/cluster/runningtasks";
public static final String RESOURCE_PATH_ALERTS = "/cluster/alerts";
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java
index cc3aa043..d81b8d0f 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/LogMessage.java
@@ -20,14 +20,24 @@ package com.gluster.storage.management.core.model;
import java.util.Date;
+import javax.xml.bind.annotation.XmlRootElement;
+
import com.gluster.storage.management.core.utils.StringUtil;
+@XmlRootElement
public class LogMessage implements Filterable {
private Date timestamp;
private Disk disk;
private String severity;
private String message;
+ public LogMessage() {
+ }
+
+ public LogMessage(String logMessage) {
+ // TODO: Parse the log message and extract fields
+ }
+
public Date getTimestamp() {
return timestamp;
}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java
index 45a9842b..95075f78 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Status.java
@@ -59,6 +59,11 @@ public class Status {
this.code = result.getExitValue();
this.message = result.getOutput();
}
+
+ public Status(Exception e) {
+ this.code = STATUS_CODE_FAILURE;
+ this.message = e.getMessage();
+ }
@XmlElement(name = "code", type = Integer.class)
public Integer getCode() {
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 50966920..94b23179 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
@@ -72,12 +72,9 @@ public class Volume extends Entity {
}
// GlusterFS and NFS export is always enabled
- // Note: logic needs to make NFS optional
private Set<NAS_PROTOCOL> nasProtocols = new LinkedHashSet<NAS_PROTOCOL>(Arrays.asList(new NAS_PROTOCOL[] {
NAS_PROTOCOL.GLUSTERFS, NAS_PROTOCOL.NFS }));
- private String accessControlList = "*";
-
public String getVolumeTypeStr() {
return getVolumeTypeStr(getVolumeType());
}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/LogMessageListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/LogMessageListResponse.java
new file mode 100644
index 00000000..191334d3
--- /dev/null
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/LogMessageListResponse.java
@@ -0,0 +1,42 @@
+/**
+ *
+ */
+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.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.gluster.storage.management.core.model.LogMessage;
+import com.gluster.storage.management.core.model.Status;
+
+@XmlRootElement(name = "response")
+public class LogMessageListResponse extends AbstractResponse {
+ private List<LogMessage> logMessages = new ArrayList<LogMessage>();
+
+ public LogMessageListResponse() {
+ }
+
+ public LogMessageListResponse(Status status, List<LogMessage> logMessages) {
+ setStatus(status);
+ setLogMessages(logMessages);
+ }
+
+ @XmlElementWrapper(name = "logMessages")
+ @XmlElement(name = "logMessage", type = LogMessage.class)
+ public List<LogMessage> getLogMessages() {
+ return logMessages;
+ }
+
+ public void setLogMessages(List<LogMessage> logMessages) {
+ this.logMessages = logMessages;
+ }
+
+ @Override
+ public Object getData() {
+ return getLogMessages();
+ }
+}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/VolumeListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/VolumeListResponse.java
index fc1c9a6c..97085603 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/VolumeListResponse.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/VolumeListResponse.java
@@ -30,10 +30,6 @@ public class VolumeListResponse extends AbstractResponse {
return this.volumes;
}
- /**
- * @param volumes
- * volumes to set
- */
public void setVolumes(List<Volume> volumes) {
this.volumes = volumes;
}
diff --git a/src/com.gluster.storage.management.gui.feature/feature.xml b/src/com.gluster.storage.management.gui.feature/feature.xml
index 2448b3cc..7f99803e 100644
--- a/src/com.gluster.storage.management.gui.feature/feature.xml
+++ b/src/com.gluster.storage.management.gui.feature/feature.xml
@@ -772,4 +772,11 @@
fragment="true"
unpack="false"/>
+ <plugin
+ id="org.apache.commons.lang"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF
index 2e59c854..076a2805 100644
--- a/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF
+++ b/src/com.gluster.storage.management.gui/META-INF/MANIFEST.MF
@@ -21,7 +21,8 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.6.1",
org.eclipse.birt.chart.device.swt;bundle-version="2.6.1",
com.ibm.icu;bundle-version="4.2.1",
com.richclientgui.rcptoolbox;bundle-version="1.0.5",
- org.eclipse.core.resources
+ org.eclipse.core.resources,
+ org.apache.commons.lang;bundle-version="2.3.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java
index a94ae25a..27dc8d4b 100644
--- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java
+++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionKeyEditingSupport.java
@@ -4,6 +4,7 @@
package com.gluster.storage.management.gui.views.details;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -12,6 +13,7 @@ import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import com.gluster.storage.management.client.GlusterDataModelManager;
@@ -42,7 +44,9 @@ public class OptionKeyEditingSupport extends EditingSupport {
Map<String, String> volumeOptions = volume.getOptions();
for(VolumeOptionInfo optionInfo : defaults) {
String optionName = optionInfo.getName();
- if(!volumeOptions.containsKey(optionName)) {
+ if(!volumeOptions.containsKey(optionName) || volumeOptions.get(optionName).isEmpty()) {
+ // key not set => available for setting
+ // value not set => this is the row being edited
keys.add(optionName);
}
}
@@ -61,7 +65,7 @@ public class OptionKeyEditingSupport extends EditingSupport {
return;
}
- // value has changed. set volume option at back-end and update model accordingly
+ // value has changed. set new value and refresh the viewer.
volume.getOptions().remove(oldEntry.getKey());
volume.setOption(newKey, "");
getViewer().refresh();
@@ -69,16 +73,49 @@ public class OptionKeyEditingSupport extends EditingSupport {
@Override
protected Object getValue(Object element) {
- return cellEditor.getValue();
+ Entry<String, String> entryBeingAdded = getEntryBeingAdded();
+ if(entryBeingAdded == null) {
+ return cellEditor.getValue();
+ }
+
+ if(entryBeingAdded.getKey().isEmpty()) {
+ // editing just about to start. set first element as default.
+ return 0;
+ }
+
+ return getIndexOfEntry(entryBeingAdded);
}
@Override
protected CellEditor getCellEditor(Object element) {
allowedKeys = getAllowedKeys();
- cellEditor = new ComboBoxCellEditor((Composite) viewer.getControl(), allowedKeys);
+ cellEditor = new ComboBoxCellEditor((Composite) viewer.getControl(), allowedKeys, SWT.READ_ONLY);
return cellEditor;
}
+ private int getIndexOfEntry(Entry<String, String> entryBeingAdded) {
+ for(int index = 0; index < allowedKeys.length; index++) {
+ if(allowedKeys[index].equals(entryBeingAdded.getKey())) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ protected Entry<String, String> getEntryBeingAdded() {
+ Entry<String, String> entryBeingAdded = null;
+ Iterator<Entry<String, String>> iter = volume.getOptions().entrySet().iterator();
+ while(iter.hasNext()) {
+ Entry<String, String> nextEntry = iter.next();
+ if(!iter.hasNext() && nextEntry.getValue().isEmpty()) {
+ // it's the LAST entry, and it's value is empty.
+ // means this is a new row being added in the table viewer.
+ entryBeingAdded = nextEntry;
+ }
+ }
+ return entryBeingAdded;
+ }
+
@SuppressWarnings("unchecked")
@Override
protected boolean canEdit(Object element) {
diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java
index 5749c703..af1ef949 100644
--- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java
+++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/OptionValueEditingSupport.java
@@ -45,9 +45,6 @@ public class OptionValueEditingSupport extends EditingSupport {
final String optionValue = (String)value;
final String oldValue = entry.getValue();
- guiHelper.setStatusMessage("Setting option [" + optionKey + " = " + optionValue + "]...");
- getViewer().getControl().update();
-
// It is not allowed to change value to empty string
if(optionValue.isEmpty()) {
MessageDialog.openError(Display.getDefault().getActiveShell(), "Set Volume Option",
@@ -62,6 +59,9 @@ public class OptionValueEditingSupport extends EditingSupport {
}
// value has changed. set volume option at back-end and update model accordingly
+ guiHelper.setStatusMessage("Setting option [" + optionKey + " = " + optionValue + "]...");
+ getViewer().getControl().update();
+
BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
@Override
diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
index d435201e..ee7acea5 100644
--- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
+++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
@@ -56,9 +56,10 @@ public class VolumeLogsPage extends Composite {
private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Disk", "Severity", "Message" };
/**
- * Create the composite.
+ * Create the volume logs page
* @param parent
* @param style
+ * @param volume Volume for which the logs page is to be created
*/
public VolumeLogsPage(Composite parent, int style, Volume volume) {
super(parent, style);
@@ -70,80 +71,39 @@ public class VolumeLogsPage extends Composite {
toolkit.adapt(this);
toolkit.paintBordersFor(this);
- setLayout(new GridLayout(1, false));
- GridData layoutData = new GridData();
- layoutData.grabExcessHorizontalSpace = true;
- layoutData.grabExcessVerticalSpace = true;
- //layoutData.verticalIndent = 10;
- setLayoutData(layoutData);
+ configureLayout();
Composite composite = toolkit.createComposite(this, SWT.NONE);
toolkit.paintBordersFor(composite);
- Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE);
- lblScanLast.setBounds(0, 15, 80, 20);
-
- text = toolkit.createText(composite, "100", SWT.NONE);
- text.setBounds(85, 15, 60, 20);
-
- Label lblMessagesAndFilter = toolkit.createLabel(composite, "messages, and filter on disk", SWT.NONE);
- lblMessagesAndFilter.setBounds(160, 15, 200, 20);
-
- Combo combo = new Combo(composite, SWT.NONE);
- combo.setBounds(365, 15, 100, 20);
- combo.setItems(new String[] {"ALL", "sda", "sdb", "sdc", "sdd"});
- toolkit.adapt(combo);
- toolkit.paintBordersFor(combo);
- combo.select(0);
-
- Label lblSeverity = toolkit.createLabel(composite, "Severity", SWT.NONE);
- lblSeverity.setBounds(480, 15, 70, 20);
+ createLineCountLabel(composite);
+ createLineCountText(composite);
- Combo combo_1 = new Combo(composite, SWT.NONE);
- combo_1.setBounds(555, 15, 110, 20);
- combo_1.setItems(new String[] {"ALL", "SEVERE", "WARNING", "DEBUG", "INFO"});
- toolkit.adapt(combo_1);
- toolkit.paintBordersFor(combo_1);
- combo_1.select(1);
+ createDiskLabel(composite);
+ createDisksCombo(composite);
- Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE);
- lblFrom.setBounds(0, 60, 40, 20);
+ createSeverityLabel(composite);
+ createSeverityCombo(composite);
- DateTime dateTime = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
- dateTime.setBounds(45, 60, 120, 20);
- toolkit.adapt(dateTime);
- toolkit.paintBordersFor(dateTime);
-
- DateTime dateTime_1 = new DateTime(composite, SWT.BORDER | SWT.TIME);
- dateTime_1.setBounds(171, 60, 120, 20);
- toolkit.adapt(dateTime_1);
- toolkit.paintBordersFor(dateTime_1);
+ createFromDateLabel(composite);
+ createFromDateField(composite);
+ createFromTimeField(composite);
- Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE);
- lblTo.setBounds(329, 60, 26, 20);
+ createToDateLabel(composite);
+ createToDateField(composite);
+ createToTimeField(composite);
- DateTime dateTime_2 = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
- dateTime_2.setBounds(355, 60, 120, 20);
- toolkit.adapt(dateTime_2);
- toolkit.paintBordersFor(dateTime_2);
+ createSearchButton(composite);
- DateTime dateTime_3 = new DateTime(composite, SWT.BORDER | SWT.TIME);
- dateTime_3.setBounds(480, 60, 120, 20);
- toolkit.adapt(dateTime_3);
- toolkit.paintBordersFor(dateTime_3);
+ createSeparator(composite);
- Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE);
- btngo.setBounds(605, 55, 60, 30);
-
- Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL);
- separator.setBounds(0, 95, 680, 2);
-
- Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT);
- lblFilterString.setBounds(0, 105, 85, 20);
+ createFilterLabel(composite);
+ createFilterText(composite);
- text = guiHelper.createFilterText(toolkit, composite);
- text.setBounds(90, 105, 250, 20);
+ createLogTableViewer();
+ }
+ private void createLogTableViewer() {
Composite tableViewerComposite = createTableViewerComposite();
TableViewer tableViewer = new TableViewer(tableViewerComposite, SWT.FLAT | SWT.FULL_SELECTION | SWT.MULTI);
@@ -154,6 +114,111 @@ public class VolumeLogsPage extends Composite {
guiHelper.createFilter(tableViewer, text, false);
tableViewer.setInput(GlusterDummyModel.getDummyLogMessages().toArray());
}
+
+ private void createFilterText(Composite composite) {
+ text = guiHelper.createFilterText(toolkit, composite);
+ text.setBounds(90, 105, 250, 20);
+ }
+
+ private void createFilterLabel(Composite composite) {
+ Label lblFilterString = toolkit.createLabel(composite, "Filter String", SWT.LEFT);
+ lblFilterString.setBounds(0, 105, 85, 20);
+ }
+
+ private void createSeparator(Composite composite) {
+ Label separator = toolkit.createLabel(composite, "", SWT.SEPARATOR | SWT.HORIZONTAL | SWT.FILL);
+ separator.setBounds(0, 95, 680, 2);
+ }
+
+ private void createSearchButton(Composite composite) {
+ Button btngo = toolkit.createButton(composite, "&Go", SWT.NONE);
+ btngo.setBounds(605, 55, 60, 30);
+ }
+
+ private void createToTimeField(Composite composite) {
+ DateTime toTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
+ toTime.setBounds(480, 60, 120, 20);
+ toolkit.adapt(toTime);
+ toolkit.paintBordersFor(toTime);
+ }
+
+ private void createToDateField(Composite composite) {
+ DateTime toDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
+ toDate.setBounds(355, 60, 120, 20);
+ toolkit.adapt(toDate);
+ toolkit.paintBordersFor(toDate);
+ }
+
+ private void createToDateLabel(Composite composite) {
+ Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE);
+ lblTo.setBounds(329, 60, 26, 20);
+ }
+
+ private void createFromTimeField(Composite composite) {
+ DateTime fromTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
+ fromTime.setBounds(171, 60, 120, 20);
+ toolkit.adapt(fromTime);
+ toolkit.paintBordersFor(fromTime);
+ }
+
+ private void createFromDateField(Composite composite) {
+ DateTime fromDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
+ fromDate.setBounds(45, 60, 120, 20);
+ toolkit.adapt(fromDate);
+ toolkit.paintBordersFor(fromDate);
+ }
+
+ private void createFromDateLabel(Composite composite) {
+ Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE);
+ lblFrom.setBounds(0, 60, 40, 20);
+ }
+
+ private void createSeverityCombo(Composite composite) {
+ Combo severityCombo = new Combo(composite, SWT.NONE);
+ severityCombo.setBounds(555, 15, 110, 20);
+ severityCombo.setItems(new String[] {"ALL", "SEVERE", "WARNING", "DEBUG", "INFO"});
+ toolkit.adapt(severityCombo);
+ toolkit.paintBordersFor(severityCombo);
+ severityCombo.select(1);
+ }
+
+ private void createSeverityLabel(Composite composite) {
+ Label lblSeverity = toolkit.createLabel(composite, "Severity", SWT.NONE);
+ lblSeverity.setBounds(480, 15, 70, 20);
+ }
+
+ private void createDisksCombo(Composite composite) {
+ Combo disksCombo = new Combo(composite, SWT.NONE);
+ disksCombo.setBounds(365, 15, 100, 20);
+ disksCombo.setItems(new String[] {"ALL", "sda", "sdb", "sdc", "sdd"});
+ toolkit.adapt(disksCombo);
+ toolkit.paintBordersFor(disksCombo);
+ disksCombo.select(0);
+ }
+
+ private void createDiskLabel(Composite composite) {
+ Label lblMessagesAndFilter = toolkit.createLabel(composite, "messages, and filter on disk", SWT.NONE);
+ lblMessagesAndFilter.setBounds(160, 15, 200, 20);
+ }
+
+ private void createLineCountText(Composite composite) {
+ text = toolkit.createText(composite, "100", SWT.NONE);
+ text.setBounds(85, 15, 60, 20);
+ }
+
+ private void createLineCountLabel(Composite composite) {
+ Label lblScanLast = toolkit.createLabel(composite, "Scan last", SWT.NONE);
+ lblScanLast.setBounds(0, 15, 80, 20);
+ }
+
+ private void configureLayout() {
+ setLayout(new GridLayout(1, false));
+ GridData layoutData = new GridData();
+ layoutData.grabExcessHorizontalSpace = true;
+ layoutData.grabExcessVerticalSpace = true;
+ //layoutData.verticalIndent = 10;
+ setLayoutData(layoutData);
+ }
private Composite createTableViewerComposite() {
Composite tableViewerComposite = new Composite(this, SWT.NO);
diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java
index b30ce379..3dadb947 100644
--- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java
+++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeOptionsPage.java
@@ -20,6 +20,7 @@ package com.gluster.storage.management.gui.views.details;
import java.util.Map.Entry;
+import org.apache.commons.lang.WordUtils;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
@@ -32,6 +33,8 @@ import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
@@ -64,6 +67,7 @@ public class VolumeOptionsPage extends Composite {
private GUIHelper guiHelper = GUIHelper.getInstance();
private Volume volume;
private DefaultClusterListener clusterListener;
+ private Text filterText;
public enum OPTIONS_TABLE_COLUMN_INDICES {
OPTION_KEY, OPTION_VALUE
@@ -71,6 +75,8 @@ public class VolumeOptionsPage extends Composite {
private static final String[] OPTIONS_TABLE_COLUMN_NAMES = new String[] { "Option Key", "Option Value" };
private Button addButton;
+ private TableViewerColumn keyColumn;
+ private OptionKeyEditingSupport keyEditingSupport;
public VolumeOptionsPage(final Composite parent, int style, Volume volume) {
super(parent, style);
@@ -81,7 +87,8 @@ public class VolumeOptionsPage extends Composite {
toolkit.paintBordersFor(this);
setupPageLayout();
- setupDiskTableViewer(guiHelper.createFilterText(toolkit, this));
+ filterText = guiHelper.createFilterText(toolkit, this);
+ setupOptionsTableViewer(filterText);
createAddButton();
@@ -91,14 +98,6 @@ public class VolumeOptionsPage extends Composite {
registerListeners(parent);
}
- /**
- * @return
- */
- private DefaultClusterListener createClusterListener() {
- // TODO Auto-generated method stub
- return null;
- }
-
private void createAddButton() {
addButton = toolkit.createButton(this, "&Add", SWT.FLAT);
addButton.addSelectionListener(new SelectionAdapter() {
@@ -109,9 +108,11 @@ public class VolumeOptionsPage extends Composite {
tableViewer.refresh();
tableViewer.setSelection(new StructuredSelection(getEntry("")));
+ keyColumn.getViewer().editElement(getEntry(""), 0); // edit newly created entry
- // disable the add button till user fills up the new option
+ // disable the add button AND search filter textbox till user fills up the new option
addButton.setEnabled(false);
+ filterText.setEnabled(false);
}
private Entry<String, String> getEntry(String key) {
@@ -123,11 +124,29 @@ public class VolumeOptionsPage extends Composite {
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) {
+ addButton.setEnabled(false);
+ } else {
+ addButton.setEnabled(true);
+ }
+ }
+ });
}
private void registerListeners(final Composite parent) {
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
+ if(!addButton.isEnabled()) {
+ // user has selected key, but not added value. Since this is not a valid entry,
+ // remove the last option (without value) from the volume
+ volume.getOptions().remove(keyEditingSupport.getEntryBeingAdded().getKey());
+ }
+
GlusterDataModelManager.getInstance().removeClusterListener(clusterListener);
toolkit.dispose();
}
@@ -145,6 +164,20 @@ public class VolumeOptionsPage extends Composite {
}
});
+ parent.addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ if(!addButton.isEnabled()) {
+ // user has selected key, but not added value. Since this is not a valid entry,
+ // remove the last option (without value) from the volume
+ Entry<String, String> entryBeingAdded = keyEditingSupport.getEntryBeingAdded();
+ volume.getOptions().remove(entryBeingAdded.getKey());
+ }
+ }
+ });
+
+
clusterListener = new DefaultClusterListener() {
@SuppressWarnings("unchecked")
@Override
@@ -159,8 +192,9 @@ public class VolumeOptionsPage extends Composite {
if(event.getEventType() == EVENT_TYPE.VOLUME_OPTION_SET) {
Entry<String, String> eventEntry = (Entry<String, String>)event.getEventData();
if (eventEntry.getKey().equals(volume.getOptions().keySet().toArray()[volume.getOptions().size()-1])) {
- // option has been set successfully by the user. re-enable the add button
+ // option has been set successfully by the user. re-enable the add button and search filter textbox
addButton.setEnabled(true);
+ filterText.setEnabled(true);
}
if(tableViewer.getTable().getItemCount() < volume.getOptions().size()) {
@@ -183,7 +217,7 @@ public class VolumeOptionsPage extends Composite {
setLayout(layout);
}
- private void setupDiskTable(Composite parent) {
+ private void setupOptionsTable(Composite parent) {
Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(false);
@@ -210,6 +244,7 @@ public class VolumeOptionsPage extends Composite {
valueColumn.getColumn()
.setText(OPTIONS_TABLE_COLUMN_NAMES[OPTIONS_TABLE_COLUMN_INDICES.OPTION_VALUE.ordinal()]);
valueColumn.setLabelProvider(new ColumnLabelProvider() {
+ @SuppressWarnings("unchecked")
@Override
public String getText(Object element) {
return ((Entry<String, String>) element).getValue();
@@ -223,9 +258,10 @@ public class VolumeOptionsPage extends Composite {
}
private TableColumn createKeyColumn() {
- TableViewerColumn keyColumn = new TableViewerColumn(tableViewer, SWT.NONE);
+ keyColumn = new TableViewerColumn(tableViewer, SWT.NONE);
keyColumn.getColumn().setText(OPTIONS_TABLE_COLUMN_NAMES[OPTIONS_TABLE_COLUMN_INDICES.OPTION_KEY.ordinal()]);
keyColumn.setLabelProvider(new ColumnLabelProvider() {
+ @SuppressWarnings("unchecked")
@Override
public String getText(Object element) {
return ((Entry<String, String>) element).getKey();
@@ -234,25 +270,32 @@ public class VolumeOptionsPage extends Composite {
@SuppressWarnings("unchecked")
@Override
public String getToolTipText(Object element) {
- VolumeOptionInfo optionInfo = GlusterDataModelManager.getInstance().getVolumeOptionInfo(
- ((Entry<String, String>) element).getKey());
- return optionInfo.getDescription() + CoreConstants.NEWLINE + "Default value: "
+ String key = ((Entry<String, String>) element).getKey();
+ if(key.isEmpty()) {
+ return "Click to select a volume option key";
+ }
+
+ VolumeOptionInfo optionInfo = GlusterDataModelManager.getInstance().getVolumeOptionInfo(key);
+ // Wrap the description before adding to tooltip so that long descriptions are displayed properly
+ return WordUtils.wrap(optionInfo.getDescription(), 60) + CoreConstants.NEWLINE + "Default value: "
+ optionInfo.getDefaultValue();
}
});
// Editing support required when adding new key
- keyColumn.setEditingSupport(new OptionKeyEditingSupport(keyColumn.getViewer(), volume));
+ keyEditingSupport = new OptionKeyEditingSupport(keyColumn.getViewer(), volume);
+ keyColumn.setEditingSupport(keyEditingSupport);
return keyColumn.getColumn();
}
- private void createDiskTableViewer(Composite parent) {
+ private void createOptionsTableViewer(Composite parent) {
tableViewer = new TableViewer(parent, SWT.FLAT | SWT.FULL_SELECTION | SWT.SINGLE);
tableViewer.setLabelProvider(new VolumeOptionsTableLabelProvider());
tableViewer.setContentProvider(new ArrayContentProvider());
+ tableViewer.getTable().setLinesVisible(true);
- setupDiskTable(parent);
+ setupOptionsTable(parent);
}
private Composite createTableViewerComposite() {
@@ -262,23 +305,15 @@ public class VolumeOptionsPage extends Composite {
return tableViewerComposite;
}
- private void setupDiskTableViewer(final Text filterText) {
+ private void setupOptionsTableViewer(final Text filterText) {
Composite tableViewerComposite = createTableViewerComposite();
- createDiskTableViewer(tableViewerComposite);
+ createOptionsTableViewer(tableViewerComposite);
ColumnViewerToolTipSupport.enableFor(tableViewer);
// Create a case insensitive filter for the table viewer using the filter text field
guiHelper.createFilter(tableViewer, filterText, false);
}
- /**
- * Sets properties for alignment and weight of given column of given table
- *
- * @param table
- * @param columnIndex
- * @param alignment
- * @param weight
- */
- public void setColumnProperties(Table table, OPTIONS_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) {
+ private void setColumnProperties(Table table, OPTIONS_TABLE_COLUMN_INDICES columnIndex, int alignment, int weight) {
TableColumn column = table.getColumn(columnIndex.ordinal());
column.setAlignment(alignment);
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java
index 4093a4ee..5c9a6505 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java
@@ -100,9 +100,9 @@ public class VolumeOptionsDefaults {
volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats",
"Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off"));
volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level",
- "Changes the log-level of the bricks (servers).", "NORMAL"));
+ "Changes the log-level of the bricks (servers).", "INFO"));
volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level",
- "Changes the log-level of the clients.", "NORMAL"));
+ "Changes the log-level of the clients.", "INFO"));
volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32",
"Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.",
"off"));
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 073b8c13..92fba9f3 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,8 +24,11 @@ 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_DISK_NAME;
+import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT;
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_LOGS;
import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_OPTIONS;
import java.util.ArrayList;
@@ -46,10 +49,13 @@ import javax.ws.rs.core.MediaType;
import com.gluster.storage.management.core.constants.CoreConstants;
import com.gluster.storage.management.core.constants.RESTConstants;
+import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
+import com.gluster.storage.management.core.model.LogMessage;
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.response.GenericResponse;
+import com.gluster.storage.management.core.response.LogMessageListResponse;
import com.gluster.storage.management.core.response.VolumeListResponse;
import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse;
import com.gluster.storage.management.server.constants.VolumeOptionsDefaults;
@@ -64,7 +70,7 @@ import com.sun.jersey.spi.resource.Singleton;
public class VolumesResource {
private static final String PREPARE_BRICK_SCRIPT = "create_volume_directory.py";
private static final String VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py";
- private static final String POST_VOLUME_DELETE_SCRIPT = "post_volume_delete.py";
+ private static final String VOLUME_DISK_LOG_SCRIPT = "get_volume_disk_log.py";
@InjectParam
private static ServerUtil serverUtil;
@@ -251,6 +257,56 @@ public class VolumesResource {
}
return new Status(Status.STATUS_CODE_SUCCESS, "Directories cleaned up successfully!");
}
+
+ private List<LogMessage> getDiskLogs(String volumeName, String diskName, Integer lineCount)
+ throws GlusterRuntimeException {
+ String[] diskParts = diskName.split(":");
+ String server = diskParts[0];
+ String disk = diskParts[1];
+
+ // Usage: get_volume_disk_log.py <volumeName> <diskName> <lineCount>
+ Status logStatus = (Status) serverUtil.executeOnServer(true, server, VOLUME_DISK_LOG_SCRIPT + " " + volumeName
+ + " " + disk + " " + lineCount, Status.class);
+ if(!logStatus.isSuccess()) {
+ throw new GlusterRuntimeException(logStatus.toString());
+ }
+
+ return extractLogMessages(logStatus.getMessage());
+ }
+
+ private List<LogMessage> extractLogMessages(String logContent) {
+ List<LogMessage> logMessages = new ArrayList<LogMessage>();
+ for(String logMessage : logContent.split(CoreConstants.NEWLINE)) {
+ logMessages.add(new LogMessage(logMessage));
+ }
+
+ return logMessages;
+ }
+
+ @GET
+ @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + SUBRESOURCE_LOGS)
+ public LogMessageListResponse getLogs(@PathParam(PATH_PARAM_VOLUME_NAME) String volumeName,
+ @QueryParam(QUERY_PARAM_DISK_NAME) String diskName, @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount) {
+ List<LogMessage> logMessages = null;
+
+ try {
+ if (diskName == null || diskName.isEmpty()) {
+ logMessages = new ArrayList<LogMessage>();
+ // fetch logs for every brick of the volume
+ Volume volume = getVolume(volumeName);
+ for (String volumeDisk : volume.getDisks()) {
+ logMessages.addAll(getDiskLogs(volumeName, volumeDisk, lineCount));
+ }
+ } else {
+ // fetch logs for given brick of the volume
+ logMessages = getDiskLogs(volumeName, diskName, lineCount);
+ }
+ } catch (Exception e) {
+ return new LogMessageListResponse(new Status(e), null);
+ }
+
+ return new LogMessageListResponse(Status.STATUS_SUCCESS, logMessages);
+ }
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/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
index 4f99172d..47657c2a 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
@@ -39,7 +39,6 @@ import org.springframework.stereotype.Component;
import com.gluster.storage.management.core.constants.CoreConstants;
import com.gluster.storage.management.core.model.Status;
-import com.gluster.storage.management.core.response.GenericResponse;
import com.gluster.storage.management.core.utils.ProcessResult;
import com.gluster.storage.management.core.utils.ProcessUtil;
@@ -75,6 +74,7 @@ public class ServerUtil {
* @param expectedClass Class of the object expected from script execution
* @return Response from remote execution of the command
*/
+ @SuppressWarnings("rawtypes")
public Object executeOnServer(boolean runInForeground, String serverName, String commandWithArgs, Class expectedClass) {
StringBuffer output = new StringBuffer();
try {
@@ -114,6 +114,7 @@ public class ServerUtil {
* class Status. If that also fails, a status object with exception message is created and returned.
* @return Object of given expected class, or a status object in case first unmarshalling fails.
*/
+ @SuppressWarnings("rawtypes")
private Object unmarshal(Class expectedClass, String input, boolean tryStatusOnFailure) {
try {
// create JAXB context and instantiate marshaller