if (isValid(incoming)) {
String requestIdWithSubId = getRequestIdWithSubId(incoming.getBody());
LOG.info("Acknowledging Message: " + requestIdWithSubId);
-// dmaap.postStatus(incoming.toOutgoing(OperationStatus.PENDING));
}
}
for (DmaapIncomingMessage incoming : messages) {
package org.openecomp.appc.listener.LCM.model;
-import org.openecomp.appc.listener.LCM.operation.OperationStatus;
-
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class InputBody {
this.commonHeader = commonHeader;
}
-// public String toOutgoing(OperationStatus operationStatus) {
-// OutputBody out = new OutputBody(this);
-// out.setStatus(new ResponseStatus(operationStatus.getCode(), operationStatus.getValue()));
-// return out.toResponse().toString();
-// }
-
-// public String toOutgoing(OperationStatus operationStatus,String islocked) {
-// OutputBody out = new OutputBody(this);
-// out.setStatus(new ResponseStatus(operationStatus.getCode(), operationStatus.getValue()));
-// out.setLocked(islocked);
-// return out.toResponse().toString();
-// }
-
@JsonIgnore
public boolean isValid() {
return getCommonHeader() != null;
import java.net.URL;
-
-
public class GenericProviderOperationRequestFormatter implements ProviderOperationRequestFormatter {
private final EELFLogger LOG = EELFManager.getInstance().getLogger(GenericProviderOperationRequestFormatter.class);
return url.getPath() + ":"+rpcName;
}
-// private String convertActionToUrl(String action) {
-// String res = "";
-// switch (action) {
-// case "SoftwareUpload":
-// res = "software-upload";
-// break;
-// case "LiveUpgrade":
-// res = "live-upgrade";
-// break;
-// case "HealthCheck":
-// res = "health-check";
-// break;
-// case "CheckLock":
-// res = "check-lock";
-// break;
-// default :
-// res = action;
-// }
-// return res.toLowerCase();
-// }
-
@Override
public String buildRequest(InputBody msg) {
JSONObject jsonObject = Mapper.toJsonObject(msg);
return String.format(TEMPLATE, jsonObject.toString());
}
-/* @Override
- public OperationStatus getOperationStatus(JSONObject responseBody) throws APPCException {
- try {
- JSONObject status = responseBody.getJSONObject("output").getJSONObject("status");
- return new OperationStatus(String.valueOf(status.getInt("code")), status.getString("message"));
- } catch (Exception e) {
- LOG.error("Unknown error processing failed response from provider. Json not in expected format", e);
- throw new APPCException("APPC has an unknown RPC error");
- }
- }*/
-
@Override
public ResponseStatus getResponseStatus(JsonNode responseBody)throws APPCException{
try {
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP : APPC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Copyright (C) 2017 Amdocs
- * =============================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.appc.listener.LCM.operation;
-
-
-public class OperationStatus {
- public final static OperationStatus PENDING = new OperationStatus("PENDING", "PENDING");
- public final static OperationStatus ACTIVE = new OperationStatus("ACTIVE", "ACTIVE");
- public final static OperationStatus SUCCESS = new OperationStatus("SUCCESS", "SUCCESS");
- public final static OperationStatus FAILURE = new OperationStatus("FAILURE", "FAILURE");
-
- private String code;
- private String value;
-
- public OperationStatus() {
- }
-
-
- public OperationStatus(String code, String value) {
- this.code = code;
- this.value = value;
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- public boolean isSucceeded() {
- if (code == null) {
- return false;
- }
- int intCode = Integer.parseInt(code);
- return (intCode >= 200) && (intCode < 300); // All 2xx statuses are success
- }
-}
final String ABORT_MESSAGE_FORMAT = "Aborting %s operation.";
/** Timeout message format with flexible operation name */
final String TIMEOUT_MESSAGE_FORMAT = "%s operation has reached timeout %d milliseconds.";
+ /** Failure message format with flexible number of bundles */
+ final String BUNDLE_OPERATION_FAILED_FORMAT = "%d bundle(s) failed, see logs for details.";
private boolean isWaiting = false;
private AppcOamStates currentState;
BaseProcessor myParent;
Map<String, Future<?>> bundleNameToFuture = new HashMap<>();
+ /**
+ * Constructor
+ *
+ * @param parent BaseProcessor who has called this constructor.
+ */
BaseActionRunnable(BaseProcessor parent) {
super(parent.logger, parent.configurationHelper, parent.stateHelper, parent.operationHelper);
setTimeoutValues();
}
+ /**
+ * Set timeout in milliseconds
+ */
void setTimeoutValues() {
Integer timeoutSeconds = myParent.timeoutSeconds;
if (timeoutSeconds == null) {
}
}
+ /**
+ * Keep waiting to be override by children classes for different behaviors.
+ * Timeout is validated here.
+ */
void keepWaiting() {
logDebug(String.format("%s runnable waiting, current state is %s.",
actionName, currentState == null ? "null" : currentState.toString()));
isTimeout("keepWaiting");
}
+ /**
+ * Check if the timeout milliseconds has reached.
+ *
+ * @param parentName String of the caller, for logging purpose.
+ * @return true if the timeout has reached, otherwise false.
+ */
boolean isTimeout(String parentName) {
logDebug(String.format("%s task isTimeout called from %s", actionName, parentName));
if (doTimeoutChecking
return false;
}
+ /**
+ * Check if all bundle operations are successful through BundleHelper.
+ * If there's failed bundler operation, set error status and trigger postAction with Error state.
+ *
+ * @return true if bundler operations have failure, otherwise false.
+ */
+ boolean hasBundleOperationFailure() {
+ long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
+ if (failedTask == 0) {
+ return false;
+ }
+
+ setStatus(OAMCommandStatus.UNEXPECTED_ERROR, String.format(BUNDLE_OPERATION_FAILED_FORMAT, failedTask));
+ postAction(AppcOamStates.Error);
+ return true;
+ }
+
/**
* Set class <b>status</b> to REJECTED with abort message.
*/
/**
* Final handling. The thread is cancelled.
+ *
* @param setState boolean to indicate if set OAM state or not
*/
void postDoAction(boolean setState) {
}
/**
- * Handling for after doAction. does post notification, issue audit log and set OAM state based on input
+ * Handling for after doAction. does post notification, issue audit log and set OAM state based on input.
+ *
* @param state of AppcOamState to be set as OAM state when it is not null.
*/
void postAction(AppcOamStates state) {
/**
* Check state
+ *
* @return true if final state reached, otherwise return false
*/
boolean checkState() {
return false;
}
- long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
- if (failedTask != 0) {
- String errorMsg = failedTask + " bundle(s) failed, see logs for details.";
- setStatus(OAMCommandStatus.UNEXPECTED_ERROR, errorMsg);
- postAction(AppcOamStates.Error);
+ if (hasBundleOperationFailure()) {
return true;
}
* <br> -Stopped: check if all bundle state reached stopped
* <br> -ToStart: call bundles start
* <br> -Started: action is full completed
- * <br> -Timeout: indication of timeout reached
+ * <br> -Error: indication of error, such as timeout reached, bundler operation failure and etc.
*/
private enum ActionPhases {
ToStop,
Stopped,
ToStart,
Started,
- Timeout
+ Error
}
/**
AppcOam.RPC.start, bundleNameToFuture, myParent.asyncTaskHelper);
currentPhase = ActionPhases.Started;
break;
- case Timeout:
+ case Error:
// do nothing
break;
default:
return false;
}
- if (isTimeout("restart doAction")) {
- currentPhase = ActionPhases.Timeout;
+ if (isTimeout("restart doAction")
+ || hasBundleOperationFailure()) {
+ currentPhase = ActionPhases.Error;
return true;
}
if (isBundleOperationCompleted) {
import org.openecomp.appc.oam.AppcOam;
import org.openecomp.appc.oam.OAMCommandStatus;
import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.BundleHelper;
import org.openecomp.appc.oam.util.ConfigurationHelper;
import org.openecomp.appc.oam.util.OperationHelper;
import org.openecomp.appc.oam.util.StateHelper;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyMap;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
private OperationHelper mockOperHelper = mock(OperationHelper.class);
private ConfigurationHelper mockConfigHelper = mock(ConfigurationHelper.class);
private Configuration mockConfig = mock(Configuration.class);
+ private BundleHelper mockBundleHelper = mock(BundleHelper.class);
@SuppressWarnings("ResultOfMethodCallIgnored")
@Before
testProcessor = spy(
new TestProcessor(mockLogger, mockConfigHelper, mockStateHelper, null, mockOperHelper));
- testBaseAcionRunnable = spy(new TestAbc(testProcessor));
+ Whitebox.setInternalState(testProcessor, "bundleHelper", mockBundleHelper);
+ testBaseAcionRunnable = spy(new TestAbc(testProcessor));
Whitebox.setInternalState(testBaseAcionRunnable, "commonHeader", mock(CommonHeader.class));
}
Whitebox.setInternalState(testBaseAcionRunnable, "doActionResult", true);
// with checkState return true
- Mockito.doReturn(targetState).when(mockStateHelper).getBundlesState();
+ Mockito.doReturn(true).when(testBaseAcionRunnable).checkState();
testBaseAcionRunnable.run();
Assert.assertFalse("isWaiting should still be false",
Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting"));
// with checkState return false
- Mockito.doReturn(AppcOamStates.Started).when(mockStateHelper).getBundlesState();
+ Mockito.doReturn(false).when(testBaseAcionRunnable).checkState();
testBaseAcionRunnable.run();
Assert.assertTrue("isWaiting should still be true",
Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting"));
@Test
public void testCheckState() throws Exception {
+ // 1. with isTimeout true
+ Mockito.doReturn(true).when(testBaseAcionRunnable).isTimeout("checkState");
+ Assert.assertTrue("Should return true", testBaseAcionRunnable.checkState());
+
+ // 2. with isTimeout false and
+ Mockito.doReturn(false).when(testBaseAcionRunnable).isTimeout("checkState");
+
+ // 2.1 with task not all done
+ Mockito.doReturn(false).when(mockBundleHelper).isAllTaskDone(any());
+ Assert.assertFalse("Should return false", testBaseAcionRunnable.checkState());
+
+ // 2. 2 with task all done
+ Mockito.doReturn(true).when(mockBundleHelper).isAllTaskDone(any());
+
+ // 2.2.1 with has bundle failure
+ Mockito.doReturn(true).when(testBaseAcionRunnable).hasBundleOperationFailure();
+ Assert.assertTrue("Should return true", testBaseAcionRunnable.checkState());
+
+ // 2.2.2 with no bundle failure
+ Mockito.doReturn(false).when(testBaseAcionRunnable).hasBundleOperationFailure();
+
Mockito.doReturn(targetState).when(mockStateHelper).getBundlesState();
Assert.assertTrue("Should return true", testBaseAcionRunnable.checkState());
testBaseAcionRunnable.status.getMessage().endsWith(
String.format(testBaseAcionRunnable.TIMEOUT_MESSAGE_FORMAT, testRpc.name(), timeoutMs)));
}
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHasBundleOperationFailure() throws Exception {
+ Mockito.when(mockBundleHelper.getFailedMetrics(anyMap())).thenReturn(Long.valueOf("0"));
+ Assert.assertFalse("should return false", testBaseAcionRunnable.hasBundleOperationFailure());
+
+ Mockito.when(mockStateHelper.getCurrentOamState()).thenReturn(AppcOamStates.Restarting);
+ long failedNumber = 1;
+ Mockito.doReturn(failedNumber).when(mockBundleHelper).getFailedMetrics(anyMap());
+ Assert.assertTrue("should return true", testBaseAcionRunnable.hasBundleOperationFailure());
+ Mockito.verify(testBaseAcionRunnable,
+ times(1)).setStatus(OAMCommandStatus.UNEXPECTED_ERROR,
+ String.format(testBaseAcionRunnable.BUNDLE_OPERATION_FAILED_FORMAT, failedNumber));
+ Mockito.verify(testBaseAcionRunnable, times(1)).postAction(AppcOamStates.Error);
+ }
}