summaryrefslogtreecommitdiffstats
path: root/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java')
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java315
1 files changed, 315 insertions, 0 deletions
diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java
new file mode 100644
index 0000000000..6787e72df6
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java
@@ -0,0 +1,315 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.openstack.utils;
+
+
+import java.lang.StackTraceElement;
+import org.openecomp.mso.logger.MsoAlarmLogger;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
+import org.openecomp.mso.openstack.exceptions.MsoException;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.openstack.exceptions.MsoIOException;
+import org.openecomp.mso.openstack.exceptions.MsoOpenstackException;
+import org.openecomp.mso.properties.MsoJavaProperties;
+import com.woorea.openstack.base.client.OpenStackBaseException;
+import com.woorea.openstack.base.client.OpenStackConnectException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+import com.woorea.openstack.heat.model.Explanation;
+import com.woorea.openstack.keystone.model.Error;
+import com.woorea.openstack.quantum.model.NeutronError;
+
+public class MsoCommonUtils {
+
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
+ protected static MsoAlarmLogger alarmLogger = new MsoAlarmLogger();
+
+ protected static String retryDelayProp = "ecomp.mso.adapters.po.retryDelay";
+ protected static String retryCountProp = "ecomp.mso.adapters.po.retryCount";
+ protected static String retryCodesProp = "ecomp.mso.adapters.po.retryCodes";
+
+ protected static int retryDelayDefault = 5;
+ protected static int retryCountDefault = 3;
+ protected static String retryCodesDefault = "504";
+
+ /*
+ * Method to execute an Openstack command and track its execution time.
+ * For the metrics log, a category of "Openstack" is used along with a
+ * sub-category that identifies the specific call (using the real
+ * openstack-java-sdk classname of the OpenStackRequest<T> parameter).
+ */
+
+ protected static <T> T executeAndRecordOpenstackRequest (OpenStackRequest <T> request)
+ {
+ return executeAndRecordOpenstackRequest (request, null);
+ }
+ protected static <T> T executeAndRecordOpenstackRequest (OpenStackRequest <T> request, MsoJavaProperties msoProps) {
+
+ int limit;
+ // Get the name and method name of the parent class, which triggered this method
+ StackTraceElement[] classArr = new Exception ().getStackTrace ();
+ if (classArr.length >=2) {
+ limit = 3;
+ } else {
+ limit = classArr.length;
+ }
+ String parentServiceMethodName = classArr[0].getClassName () + "." + classArr[0].getMethodName ();
+ for (int i = 1; i < limit; i++) {
+ String className = classArr[i].getClassName ();
+ if (!className.equals (MsoCommonUtils.class.getName ())) {
+ parentServiceMethodName = className + "." + classArr[i].getMethodName ();
+ break;
+ }
+ }
+
+ long start = System.currentTimeMillis ();
+ String requestType;
+ if (request.getClass ().getEnclosingClass () != null) {
+ requestType = request.getClass ().getEnclosingClass ().getSimpleName () + "."
+ + request.getClass ().getSimpleName ();
+ } else {
+ requestType = request.getClass ().getSimpleName ();
+ }
+
+ int retryDelay = retryDelayDefault;
+ int retryCount = retryCountDefault;
+ String retryCodes = retryCodesDefault;
+ if (msoProps != null) //extra check to avoid NPE
+ {
+ retryDelay = msoProps.getIntProperty (retryDelayProp, retryDelayDefault);
+ retryCount = msoProps.getIntProperty (retryCountProp, retryCountDefault);
+ retryCodes = msoProps.getProperty (retryCodesProp, retryCodesDefault);
+ }
+
+ // Run the actual command. All exceptions will be propagated
+ while (true)
+ {
+ try {
+ return request.execute ();
+ }
+ catch (OpenStackResponseException e) {
+ boolean retry = false;
+ if (retryCodes != null ) {
+ int code = e.getStatus();
+ LOGGER.debug ("Config values RetryDelay:" + retryDelay + " RetryCount:" + retryCount + " RetryCodes:" + retryCodes + " ResponseCode:" + code);
+ for (String rCode : retryCodes.split (",")) {
+ try {
+ if (retryCount > 0 && code == Integer.parseInt (rCode))
+ {
+ retryCount--;
+ retry = true;
+ LOGGER.debug ("OpenStackResponseException ResponseCode:" + code + " at:" + parentServiceMethodName + " request:" + requestType + " Retry indicated. Attempts remaining:" + retryCount);
+ break;
+ }
+ } catch (NumberFormatException e1) {
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, "No retries. Exception in parsing retry code in config:" + rCode, "", "", MsoLogger.ErrorCode.SchemaError, "Exception in parsing retry code in config");
+ throw e;
+ }
+ }
+ }
+ if (retry)
+ {
+ try {
+ Thread.sleep (retryDelay * 1000L);
+ } catch (InterruptedException e1) {
+ LOGGER.debug ("Thread interrupted while sleeping", e1);
+ }
+ }
+ else
+ throw e; // exceeded retryCount or code is not retryable
+ }
+ catch (OpenStackConnectException e) {
+ // Connection to Openstack failed
+ if (retryCount > 0)
+ {
+ retryCount--;
+ LOGGER.debug ("OpenstackConnectException at:" + parentServiceMethodName + " request:" + requestType + " Retry indicated. Attempts remaining:" + retryCount);
+ try {
+ Thread.sleep (retryDelay * 1000L);
+ } catch (InterruptedException e1) {
+ LOGGER.debug ("Thread interrupted while sleeping", e1);
+ }
+ }
+ else
+ throw e;
+
+ }
+ }
+ }
+
+ /*
+ * Convert an Openstack Exception on a Keystone call to an MsoException.
+ * This method supports both OpenstackResponseException and OpenStackConnectException.
+ */
+ protected static MsoException keystoneErrorToMsoException (OpenStackBaseException e, String context) {
+ MsoException me = null;
+
+ if (e instanceof OpenStackResponseException) {
+ OpenStackResponseException re = (OpenStackResponseException) e;
+
+ try {
+ // Failed Keystone calls return an Error entity body.
+ Error error = re.getResponse ().getErrorEntity (Error.class);
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack Keystone Error on " + context + ": " + error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Openstack Keystone Error on " + context);
+ me = new MsoOpenstackException (error.getCode (), error.getTitle (), error.getMessage ());
+ } catch (Exception e2) {
+ // Can't parse the body as an "Error". Report the HTTP error
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "HTTP Error on " + context + ": " + re.getStatus() + "," + re.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "HTTP Error on " + context, e2);
+ me = new MsoOpenstackException (re.getStatus (), re.getMessage (), "");
+ }
+
+ // Add the context of the error
+ me.addContext (context);
+
+ // Generate an alarm for 5XX and higher errors.
+ if (re.getStatus () >= 500) {
+ alarmLogger.sendAlarm ("KeystoneError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ }
+ } else if (e instanceof OpenStackConnectException) {
+ OpenStackConnectException ce = (OpenStackConnectException) e;
+
+ me = new MsoIOException (ce.getMessage ());
+ me.addContext (context);
+
+ // Generate an alarm for all connection errors.
+ LOGGER.error(MessageEnum.RA_GENERAL_EXCEPTION_ARG, "Openstack Keystone connection error on " + context + ": " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Openstack Keystone connection error on " + context);
+ alarmLogger.sendAlarm ("KeystoneIOError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ }
+
+ return me;
+ }
+
+ /*
+ * Convert an Openstack Exception on a Heat call to an MsoOpenstackException.
+ * This method supports both OpenstackResponseException and OpenStackConnectException.
+ */
+ protected MsoException heatExceptionToMsoException (OpenStackBaseException e, String context) {
+ MsoException me = null;
+
+ if (e instanceof OpenStackResponseException) {
+ OpenStackResponseException re = (OpenStackResponseException) e;
+
+ try {
+ // Failed Heat calls return an Explanation entity body.
+ Explanation explanation = re.getResponse ().getErrorEntity (Explanation.class);
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Error on " + context + ": " + explanation.toString(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Openstack Error on " + context);
+ String fullError = explanation.getExplanation() + ", error.type=" + explanation.getError().getType() + ", error.message=" + explanation.getError().getMessage();
+ LOGGER.debug(fullError);
+ me = new MsoOpenstackException (explanation.getCode (),
+ explanation.getTitle (),
+ //explanation.getExplanation ());
+ fullError);
+ } catch (Exception e2) {
+ // Couldn't parse the body as an "Explanation". Report the original HTTP error.
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "HTTP Error on " + context + ": " + re.getStatus() + "," + e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - HTTP Error on " + context, e2);
+ me = new MsoOpenstackException (re.getStatus (), re.getMessage (), "");
+ }
+
+ // Add the context of the error
+ me.addContext (context);
+
+ // Generate an alarm for 5XX and higher errors.
+ if (re.getStatus () >= 500) {
+ alarmLogger.sendAlarm ("HeatError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ }
+ } else if (e instanceof OpenStackConnectException) {
+ OpenStackConnectException ce = (OpenStackConnectException) e;
+
+ me = new MsoIOException (ce.getMessage ());
+ me.addContext (context);
+
+ // Generate an alarm for all connection errors.
+ alarmLogger.sendAlarm ("HeatIOError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ LOGGER.error(MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Heat connection error on " + context + ": " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Openstack Heat connection error on " + context);
+ }
+
+ return me;
+ }
+
+ /*
+ * Convert an Openstack Exception on a Neutron call to an MsoOpenstackException.
+ * This method supports both OpenstackResponseException and OpenStackConnectException.
+ */
+ protected MsoException neutronExceptionToMsoException (OpenStackBaseException e, String context) {
+ MsoException me = null;
+
+ if (e instanceof OpenStackResponseException) {
+ OpenStackResponseException re = (OpenStackResponseException) e;
+
+ try {
+ // Failed Neutron calls return an NeutronError entity body
+ NeutronError error = re.getResponse ().getErrorEntity (NeutronError.class);
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Neutron Error on " + context + ": " + error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Openstack Neutron Error on " + context);
+ me = new MsoOpenstackException (re.getStatus (), error.getType (), error.getMessage ());
+ } catch (Exception e2) {
+ // Couldn't parse body as a NeutronError. Report the HTTP error.
+ LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "HTTP Error on " + context + ": " + re.getStatus() + "," + e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Openstack HTTP Error on " + context, e2);
+ me = new MsoOpenstackException (re.getStatus (), re.getMessage (), null);
+ }
+
+ // Add the context of the error
+ me.addContext (context);
+
+ // Generate an alarm for 5XX and higher errors.
+ if (re.getStatus () >= 500) {
+ alarmLogger.sendAlarm ("NeutronError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ }
+ } else if (e instanceof OpenStackConnectException) {
+ OpenStackConnectException ce = (OpenStackConnectException) e;
+
+ me = new MsoIOException (ce.getMessage ());
+ me.addContext (context);
+
+ // Generate an alarm for all connection errors.
+ alarmLogger.sendAlarm ("NeutronIOError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+ LOGGER.error(MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Neutron Connection error on "+ context + ": " + e, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Openstack Neutron Connection error on "+ context);
+ }
+
+ return me;
+ }
+
+ /*
+ * Convert a Java Runtime Exception to an MsoException.
+ * All Runtime exceptions will be translated into an MsoAdapterException,
+ * which captures internal errors.
+ * Alarms will be generated on all such exceptions.
+ */
+ protected MsoException runtimeExceptionToMsoException (RuntimeException e, String context) {
+ MsoAdapterException me = new MsoAdapterException (e.getMessage (), e);
+ me.addContext (context);
+ me.setCategory (MsoExceptionCategory.INTERNAL);
+
+ // Always generate an alarm for internal exceptions
+ LOGGER.error(MessageEnum.RA_GENERAL_EXCEPTION_ARG, "An exception occured on "+ context + ": " + e, "OpenStack", "", MsoLogger.ErrorCode.DataError, "An exception occured on "+ context);
+ alarmLogger.sendAlarm ("AdapterInternalError", MsoAlarmLogger.CRITICAL, me.getContextMessage ());
+
+ return me;
+ }
+
+ public static boolean isNullOrEmpty (String s) {
+ return s == null || s.isEmpty();
+ }
+
+
+
+}