Skip to content
This repository has been archived by the owner on Jul 11, 2022. It is now read-only.

Commit

Permalink
[BZ 1083894] - Storage node's cluster status "NORMAL" written in RED …
Browse files Browse the repository at this point in the history
…cannot be changed - Adding a way to our UI to explicitly reset error message and last failed operation on the rhq_storage_node table.

(cherry picked from commit ed4714e)
Signed-off-by: Jirka Kremser <jkremser@redhat.com>
  • Loading branch information
jkremser committed Sep 25, 2014
1 parent d01a75e commit 5880b8b
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 21 deletions.
Expand Up @@ -56,6 +56,10 @@ public static String getStatusComplete() {
public static String getStatusError() {
return "status_error.gif";
}

public static String getCloseIcon() {
return "[SKIN]/actions/close.png";
}

/**
* Returns a generic "upload" icon.
Expand Down
Expand Up @@ -37,11 +37,17 @@
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.VisibilityMode;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.form.fields.events.IconClickEvent;
import com.smartgwt.client.widgets.form.fields.events.IconClickHandler;
import com.smartgwt.client.widgets.layout.LayoutSpacer;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;
Expand Down Expand Up @@ -91,6 +97,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab
private HTMLFlow header;
private boolean alerts = false;
private StaticTextItem jmxPortItem;
private Integer jmxPort = null;

private volatile int initSectionCount = 0;
private int unackAlerts = -1;
Expand Down Expand Up @@ -170,7 +177,8 @@ public void onFailure(Throwable caught) {

@Override
public void onSuccess(StorageNodeConfigurationComposite result) {
jmxPortItem.setValue(result.getJmxPort());
jmxPort = result.getJmxPort();
jmxPortItem.setValue(jmxPort);
prepareResourceConfigEditor(result);
}
});
Expand Down Expand Up @@ -290,6 +298,16 @@ public void run() {
}

private void prepareDetailsSection(final StorageNode storageNode) {
detailsLayout = new EnhancedVLayout();
detailsLayout.setWidth("35%");
detailsLayout.addMember(buildDetailsForm(storageNode));
if (detailsAndLoadLayout == null) {
detailsAndLoadLayout = new EnhancedHLayout(0);
}
initSectionCount++;
}

private DynamicForm buildDetailsForm(final StorageNode storageNode) {
final DynamicForm form = new DynamicForm();
form.setMargin(10);
form.setWidth100();
Expand Down Expand Up @@ -372,14 +390,16 @@ private void prepareDetailsSection(final StorageNode storageNode) {
message.append(storageNode.getErrorMessage()).append("<br />");
isOk = false;
} else if (storageNode.getFailedOperation() != null) {
message.append(MSG.view_adminTopology_storageNodes_detail_errorLastOperationFailed() + "<br />");
message.append(MSG.view_adminTopology_storageNodes_detail_errorLastOperationFailed());
isOk = false;
}
if (isOk) {
message.append(MSG.view_adminTopology_storageNodes_detail_ok());
}
messageItem.setValue(message.toString());

StaticTextItem lastOperation = null;
StaticTextItem lastOperationAck = null;
boolean isOperationFailed = storageNode.getFailedOperation() != null
&& storageNode.getFailedOperation().getResource() != null;
if (isOperationFailed) {
Expand All @@ -403,15 +423,43 @@ private void prepareDetailsSection(final StorageNode storageNode) {
if (isOperationFailed) {
formItems.add(lastOperation);
}
if (null != storageNode.getErrorMessage() || null != storageNode.getFailedOperation()) {
lastOperationAck = new StaticTextItem("lastOpAck", "");
lastOperationAck.setValue("<span style='color: #0099D3;'>" + MSG.common_button_ack() + "</span>");
lastOperationAck.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
ackFailedOperation(storageNode);
}
});
formItems.add(lastOperationAck);
}
form.setItems(formItems.toArray(new FormItem[formItems.size()]));

detailsLayout = new EnhancedVLayout();
detailsLayout.setWidth("35%");
detailsLayout.addMember(form);
if (detailsAndLoadLayout == null) {
detailsAndLoadLayout = new EnhancedHLayout(0);
}
initSectionCount++;
return form;
}

private void ackFailedOperation(final StorageNode storageNode) {
GWTServiceLookup.getStorageService().ackFailedOperation(storageNodeId, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Message message = new Message(MSG.view_adminTopology_storageNodes_detail_loadDataFetchFail(),
Message.Severity.Warning);
CoreGUI.getMessageCenter().notify(message);
}

@Override
public void onSuccess(Void result) {
storageNode.setFailedOperation(null);
storageNode.setErrorMessage(null);
detailsLayout.removeMember(detailsLayout.getMember(0));
detailsLayout.addMember(buildDetailsForm(storageNode));
if (null != jmxPort) {
jmxPortItem.setValue(jmxPort);
}
}

});
}

private void prepareLoadSection(SectionStack stack, final StorageNode storageNode,
Expand Down
Expand Up @@ -98,4 +98,6 @@ public interface StorageGWTService extends RemoteService {
void undeployStorageNode(StorageNode storageNode) throws RuntimeException;

void deployStorageNode(StorageNode storageNode) throws RuntimeException;

void ackFailedOperation(int storageNodeId) throws RuntimeException;
}
Expand Up @@ -230,4 +230,13 @@ public void deployStorageNode(StorageNode storageNode) throws RuntimeException {
throw getExceptionToThrowToClient(t);
}
}

@Override
public void ackFailedOperation(int storageNodeId) throws RuntimeException {
try {
storageNodeManager.ackFailedOperation(getSessionSubject(), storageNodeId);
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
}
}
Expand Up @@ -33,8 +33,6 @@
import javax.persistence.Query;
import javax.transaction.Transaction;

import org.testng.annotations.Test;

import org.rhq.core.domain.cloud.StorageNode;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
Expand All @@ -46,10 +44,9 @@
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.testng.annotations.Test;

/**
* @author Jirka Kremser
Expand All @@ -60,17 +57,13 @@ public class StorageNodeManagerBeanTest extends AbstractEJB3Test {
@EJB
private StorageNodeManagerLocal nodeManager;

@EJB
private ResourceTypeManagerLocal typeManager;

@EJB
private ResourceGroupManagerLocal resourceGroupManager;

@EJB
private SubjectManagerLocal subjectManager;


private static final String TEST_PREFIX = "test-";

private static final String TEST_PREFIX = "test-";

@Test(groups = "integration.ejb3")
public void testStorageNodeCriteriaFinder() throws Exception {

Expand Down Expand Up @@ -134,6 +127,42 @@ public void execute() throws Exception {
}
});
}

@Test(groups = "integration.ejb3")
public void testStorageNodeAckFailedOperation() throws Exception {
executeInTransaction(new TransactionCallback() {

@Override
public void execute() throws Exception {
StorageNode node = new StorageNode();
final String address = TEST_PREFIX + "foo.com";
node.setAddress(address);
node.setOperationMode(StorageNode.OperationMode.ANNOUNCE);
node.setCqlPort(9142);
node.setErrorMessage("It is broken");
em.persist(node);
em.flush();
assertEquals("The cluster status should be DOWN", StorageNode.Status.DOWN, node.getStatus());

// we need to do this to obtain the new id
StorageNodeCriteria criteria = new StorageNodeCriteria();
criteria.addFilterAddress(address);
StorageNode node2 = nodeManager.findStorageNodeByAddress(address);

nodeManager.ackFailedOperation(subjectManager.getOverlord(), node2.getId());

criteria = new StorageNodeCriteria();
criteria.addFilterAddress(address);
StorageNode node3 = nodeManager.findStorageNodeByAddress(address);

assertEquals("The error message should not affect the equals method", node, node2);
assertEquals("The error message should not affect the equals method", node2, node3);
assertEquals("The cluster status should be JOINING", StorageNode.Status.JOINING, node3.getStatus());
assertNull("The error message should be clean now", node3.getErrorMessage());
}

});
}

private void cleanDatabase() throws Exception {
// this method is still needed, because tests calls SLSB methods that are executed in their own transaction
Expand Down Expand Up @@ -164,6 +193,7 @@ private void cleanDatabase() throws Exception {
// resume the currently running TX
getTransactionManager().resume(runningTransaction);
}


private ResourceType createResourceType() throws Exception {
ResourceType resourceType = new ResourceType("RHQ Storage Node", "RHQStorage", ResourceCategory.SERVER, null);
Expand Down
Expand Up @@ -64,7 +64,6 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
Expand Down Expand Up @@ -1330,5 +1329,18 @@ public void scheduleSnapshotManagement(Subject subject, StorageClusterSettings c
scheduleSnapshotManagementOperationsForStorageNode(subject, storageNode, clusterSettings);
}
}

@Override
@RequiredPermission(Permission.MANAGE_SETTINGS)
public void ackFailedOperation(Subject subject, int storageNodeId) {
StorageNode existingStorageNode = entityManager.find(StorageNode.class, storageNodeId);
if (null != existingStorageNode) {
existingStorageNode.setFailedOperation(null);
existingStorageNode.setErrorMessage(null);
entityManager.merge(existingStorageNode);
} else {
log.info("Storage node did not exist. Cannot ack/clear the failed operation.");
}
}

}
Expand Up @@ -117,4 +117,6 @@ void scheduleSnapshotManagementOperationsForStorageNode(Subject subject, Storage
StorageClusterSettings settings);

void scheduleSnapshotManagement(Subject subject, StorageClusterSettings clusterSettings);

void ackFailedOperation(Subject subject, int storageNodeId);
}

0 comments on commit 5880b8b

Please sign in to comment.