diff options
author | 2018-07-30 15:56:09 -0400 | |
---|---|---|
committer | 2018-07-31 11:09:25 -0400 | |
commit | 5a6a6de6f1a26a1897e4917a0df613e25a24eb70 (patch) | |
tree | 59a968f27b4b603aacc9d5e7b51fb598aeec5321 /adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils | |
parent | b6dc38501f3b746426b42d9de4cc883d894149e8 (diff) |
Containerization feature of SO
Change-Id: I95381232eeefcd247a66a5cec370a8ce1c288e18
Issue-ID: SO-670
Signed-off-by: Benjamin, Max (mb388a) <mb388a@us.att.com>
Diffstat (limited to 'adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils')
12 files changed, 0 insertions, 4648 deletions
diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/CloudConfigInitializer.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/CloudConfigInitializer.java deleted file mode 100644 index 43a6171699..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/CloudConfigInitializer.java +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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 javax.ejb.EJB; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; - -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudConfigIdentityMapper; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.logger.MsoLogger; - -/** - * This class will attempt to initialize Cloud Config when part of a web application. - * - * - * - */ -@WebListener -public class CloudConfigInitializer implements ServletContextListener -{ - - private CloudConfigFactory cloudConfigFactory=new CloudConfigFactory(); - - public CloudConfigInitializer () { - } - - @Override - public void contextDestroyed(ServletContextEvent event) { - // Nothing to do... - } - - - @Override - public void contextInitialized(ServletContextEvent event) - { - - // Note - this logger may be before or after MSO Logging configuration applied - MsoLogger initLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL); - try { - // Look first in the init-parameters - String msoPropConfigParam = event.getServletContext().getInitParameter("mso.cloud_config.configuration"); - - String[] configFileSplit = msoPropConfigParam.split(","); - for (String msoPropConfig:configFileSplit) { - String[] msoPropDecoded = msoPropConfig.split("="); - - try { - cloudConfigFactory.initializeCloudConfig(msoPropDecoded[0], Integer.valueOf(msoPropDecoded[1])); - initLogger.info(MessageEnum.RA_CONFIG_LOAD, msoPropDecoded[0], "", ""); - initLogger.debug("Mso properties successfully loaded:"+msoPropDecoded[0]+"(Timer(mins):"+Integer.valueOf(msoPropDecoded[1])); - } catch (NumberFormatException ne) { - initLogger.error(MessageEnum.RA_CONFIG_EXC, msoPropDecoded[0] + ". MSO Properties failed due to conversion error (in web.xml file)", "", "", MsoLogger.ErrorCode.DataError, "MSO Properties failed due to conversion error (in web.xml file)", ne); - } - } - - // Second, obtain class name that will register all mappings - String msoMapperClassParam = event.getServletContext().getInitParameter("mso.cloud_config.mapper.class"); - if (msoMapperClassParam != null) { - Class<?> mapperClass = Class.forName(msoMapperClassParam); - if (CloudConfigIdentityMapper.class.isAssignableFrom(mapperClass)) { - ((CloudConfigIdentityMapper)mapperClass.newInstance()).registerAllMappings(); - initLogger.info(MessageEnum.RA_CONFIG_LOAD,msoMapperClassParam+"(Openstack authentication mapper class)","",""); - } else { - initLogger.info(MessageEnum.RA_CONFIG_LOAD,msoMapperClassParam+"(Openstack authentication mapper class not an implementation of CloudConfigIdentityMapper)","",""); - } - } else { - initLogger.info(MessageEnum.RA_CONFIG_LOAD,"Openstack authentication mapper class not specified in web.xml (ONLY core authentication mechanisms will be loaded)","",""); - } - - } - catch (Exception e) { - initLogger.error(MessageEnum.RA_CONFIG_EXC, "Unknown. MSO Properties failed to initialize completely", "", "", MsoLogger.ErrorCode.AvailabilityError, "Exception - MSO Properties failed to initialize completely", e); - } - } -} 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 deleted file mode 100644 index 7d6de317ad..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoCommonUtils.java +++ /dev/null @@ -1,313 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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 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; - } - } - - 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); - Thread.currentThread().interrupt(); - } - } - 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); - Thread.currentThread().interrupt(); - } - } - 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(); - } - - - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentEntry.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentEntry.java deleted file mode 100644 index 7046096979..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentEntry.java +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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.util.HashSet; -import java.util.ArrayList; -import java.util.Set; - -import org.openecomp.mso.db.catalog.beans.HeatTemplateParam; -import org.openecomp.mso.logger.MsoLogger; - -public class MsoHeatEnvironmentEntry { - - private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA); - - private Set<MsoHeatEnvironmentParameter> parameters = null; - private Set<MsoHeatEnvironmentResource> resources = null; - private StringBuilder rawEntry = null; - private boolean valid = true; - private String errorString = null; - private StringBuilder resourceRegistryEntryRaw = null; - - public MsoHeatEnvironmentEntry() { - super(); - } - - public MsoHeatEnvironmentEntry(StringBuilder sb) { - this(); - this.rawEntry = sb; - this.processRawEntry(); - } - - private void processRawEntry() { - try { - if (this.rawEntry == null || "".equals(this.rawEntry)) - return; - byte[] b = this.rawEntry.toString().getBytes(); - MsoYamlEditorWithEnvt yaml = new MsoYamlEditorWithEnvt(b); - this.parameters = yaml.getParameterListFromEnvt(); - //this.resources = yaml.getResourceListFromEnvt(); - StringBuilder sb = this.getResourceRegistryRawEntry(); - if (sb == null) { - this.resourceRegistryEntryRaw = new StringBuilder(""); - } else { - this.resourceRegistryEntryRaw = sb; - } - } catch (Exception e) { - LOGGER.debug("Exception:", e); - this.valid = false; - this.errorString = e.getMessage(); - //e.printStackTrace(); - } - } - - public boolean isValid() { - return this.valid; - } - - public String getErrorString() { - return this.errorString; - } - - public Set<MsoHeatEnvironmentParameter> getParameters() { - return this.parameters; - } - - public Set<MsoHeatEnvironmentResource> getResources() { - return this.resources; - } - - public void setParameters(Set<MsoHeatEnvironmentParameter> paramSet) { - if (paramSet == null) { - this.parameters = null; - } else { - this.parameters = paramSet; - } - } - - public void setResources(Set<MsoHeatEnvironmentResource> resourceSet) { - if (resourceSet == null) { - this.resources = null; - } else { - this.resources = resourceSet; - } - } - - public void addParameter(MsoHeatEnvironmentParameter hep) { - if (this.parameters == null) { - this.parameters = new HashSet<>(); - } - this.parameters.add(hep); - } - - public void addResource(MsoHeatEnvironmentResource her) { - if (this.resources == null) { - this.resources = new HashSet<>(); - } - this.resources.add(her); - } - - public int getNumberOfParameters() { - return this.parameters.size(); - } - - public int getNumberOfResources() { - return this.resources.size(); - } - - public boolean hasResources() { - if (this.resources != null && this.resources.size() > 0) { - return true; - } - return false; - } - - public boolean hasParameters() { - if (this.parameters != null && this.parameters.size() > 0) { - return true; - } - return false; - } - - public boolean containsParameter(String paramName) { - boolean contains = false; - if (this.parameters == null || this.parameters.size() < 1) { - return false; - } - if (this.parameters.contains(new MsoHeatEnvironmentParameter(paramName))) { - contains = true; - } - return contains; - } - - public boolean containsParameter(String paramName, String paramAlias) { - if (this.containsParameter(paramName)) { - return true; - } - if (this.containsParameter(paramAlias)) { - return true; - } - return false; - } - - @Override - public String toString() { - return "MsoHeatEnvironmentEntry{" + "parameters=" + parameters + - ", resourceRegistryEntryRaw='" + resourceRegistryEntryRaw + '\'' + - '}'; - } - - public StringBuilder toFullStringExcludeNonParams(Set<HeatTemplateParam> params) { - // Basically give back the envt - but exclude the params that aren't in the HeatTemplate - - StringBuilder sb = new StringBuilder(); - ArrayList<String> paramNameList = new ArrayList<String>(params.size()); - for (HeatTemplateParam htp : params) { - paramNameList.add(htp.getParamName()); - } - - if (this.hasParameters()) { - sb.append("parameters:\n"); - for (MsoHeatEnvironmentParameter hep : this.parameters) { - String paramName = hep.getName(); - if (paramNameList.contains(paramName)) { - // This parameter *is* in the Heat Template - so include it: - sb.append(" " + hep.getName() + ": " + hep.getValue() + "\n"); - // New - 1607 - if any of the params mapped badly - JUST RETURN THE ORIGINAL ENVT! - if (hep.getValue().startsWith("_BAD")) { - return this.rawEntry; - } - } - } - sb.append("\n"); - } -// if (this.hasResources()) { -// sb.append("resource_registry:\n"); -// for (MsoHeatEnvironmentResource her : this.resources) { -// sb.append(" \"" + her.getName() + "\": " + her.getValue() + "\n"); -// } -// } - sb.append("\n"); - sb.append(this.resourceRegistryEntryRaw); - return sb; - } - - public StringBuilder toFullString() { - StringBuilder sb = new StringBuilder(); - - if (this.hasParameters()) { - sb.append("parameters:\n"); - for (MsoHeatEnvironmentParameter hep : this.parameters) { - sb.append(" " + hep.getName() + ": " + hep.getValue() + "\n"); - } - sb.append("\n"); - } -// if (this.hasResources()) { -// sb.append("resource_registry:\n"); -// for (MsoHeatEnvironmentResource her : this.resources) { -// sb.append(" \"" + her.getName() + "\": " + her.getValue() + "\n"); -// } -// } - sb.append("\n"); - sb.append(this.resourceRegistryEntryRaw); - return sb; - } - - public StringBuilder getRawEntry() { - return this.rawEntry; - } - - private StringBuilder getResourceRegistryRawEntry() { - - if (this.rawEntry == null) { - return null; - } - - StringBuilder sb = new StringBuilder(); - int indexOf = this.rawEntry.indexOf("resource_registry:"); - if (indexOf < 0) { // no resource_registry: - return null; - } - sb.append(this.rawEntry.substring(indexOf)); - return sb; - } - - public void setHPAParameters(StringBuilder hpasb) { - try { - MsoYamlEditorWithEnvt yaml = new MsoYamlEditorWithEnvt(hpasb.toString().getBytes()); - Set<MsoHeatEnvironmentParameter> hpaParams = yaml.getParameterListFromEnvt(); - for (MsoHeatEnvironmentParameter hpaparam : hpaParams) { - for (MsoHeatEnvironmentParameter param : this.parameters) { - if (param.getName() == hpaparam.getName()) { - param.setValue(hpaparam.getValue()); - } - } - } - } catch (Exception e) { - LOGGER.debug("Exception:", e); - this.errorString = e.getMessage(); - //e.printStackTrace(); - } - } -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentParameter.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentParameter.java deleted file mode 100644 index cd1a3e5130..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentParameter.java +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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.util.Objects; - -public class MsoHeatEnvironmentParameter { - - private String name; - private String value; - - public MsoHeatEnvironmentParameter(String name, String value) { - super(); - this.name = name; - this.value = value; - } - public MsoHeatEnvironmentParameter(String name) { - // Allow to initialize with a null value - this(name, null); - } - public MsoHeatEnvironmentParameter() { - this(null, null); - } - - public String getName() { - return this.name; - } - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return this.value; - } - public void setValue(String value) { - this.value = value; - } - public String toString() { - return this.name + ": " + this.value; - } - - public boolean equals(Object o) { - if (!(o instanceof MsoHeatEnvironmentParameter)) { - return false; - } - if (this == o) { - return true; - } - MsoHeatEnvironmentParameter hep = (MsoHeatEnvironmentParameter) o; - // If the name of the parameter is the same, then they're equal - return hep.getName().equals(this.getName()); - } - - public int hashCode() { - return Objects.hashCode(this.name); - } - - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentResource.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentResource.java deleted file mode 100644 index a0c9b7a105..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatEnvironmentResource.java +++ /dev/null @@ -1,96 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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 org.openecomp.mso.logger.MsoLogger; - -public class MsoHeatEnvironmentResource { - - private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - - private String name; - private String value; - - public MsoHeatEnvironmentResource(String name, String value) { - super(); - this.name = name; - this.value = value; - } - public MsoHeatEnvironmentResource(String name) { - // Allow to initialize with a null value - this(name, null); - } - public MsoHeatEnvironmentResource() { - this(null, null); - } - - public String getName() { - return this.name; - } - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return this.value; - } - public void setValue(String value) { - this.value = value; - } - - @Override - public String toString() { - return "\"" + - this.name + - "\": " + - this.value; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof MsoHeatEnvironmentResource)) { - return false; - } - if (this == o) { - return true; - } - MsoHeatEnvironmentResource her = (MsoHeatEnvironmentResource) o; - // If the name of the parameter is the same, then they're equal - if (her.getName().equals(this.getName())) { - return true; - } - return false; - } - - @Override - public int hashCode() { - int result = 0; - try { - result = this.name.hashCode(); - } catch (Exception e) { - LOGGER.debug("Exception:", e); - } - return result; - } - - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtils.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtils.java deleted file mode 100644 index f7723b6a8f..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtils.java +++ /dev/null @@ -1,1860 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.openecomp.mso.adapters.vdu.CloudInfo; -import org.openecomp.mso.adapters.vdu.PluginAction; -import org.openecomp.mso.adapters.vdu.VduArtifact; -import org.openecomp.mso.adapters.vdu.VduArtifact.ArtifactType; -import org.openecomp.mso.adapters.vdu.VduException; -import org.openecomp.mso.adapters.vdu.VduInstance; -import org.openecomp.mso.adapters.vdu.VduModelInfo; -import org.openecomp.mso.adapters.vdu.VduPlugin; -import org.openecomp.mso.adapters.vdu.VduStateType; -import org.openecomp.mso.adapters.vdu.VduStatus; -import org.openecomp.mso.cloud.CloudConfig; -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudIdentity; -import org.openecomp.mso.cloud.CloudSite; -import org.openecomp.mso.db.catalog.beans.HeatTemplate; -import org.openecomp.mso.db.catalog.beans.HeatTemplateParam; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.logger.MsoAlarmLogger; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.openstack.beans.HeatStatus; -import org.openecomp.mso.openstack.beans.StackInfo; -import org.openecomp.mso.openstack.exceptions.MsoAdapterException; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; -import org.openecomp.mso.openstack.exceptions.MsoException; -import org.openecomp.mso.openstack.exceptions.MsoIOException; -import org.openecomp.mso.openstack.exceptions.MsoOpenstackException; -import org.openecomp.mso.openstack.exceptions.MsoStackAlreadyExists; -import org.openecomp.mso.openstack.exceptions.MsoTenantNotFound; -import org.openecomp.mso.properties.MsoJavaProperties; -import org.openecomp.mso.properties.MsoPropertiesException; -import org.openecomp.mso.properties.MsoPropertiesFactory; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -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.Heat; -import com.woorea.openstack.heat.model.CreateStackParam; -import com.woorea.openstack.heat.model.Stack; -import com.woorea.openstack.heat.model.Stack.Output; -import com.woorea.openstack.heat.model.Stacks; -import com.woorea.openstack.keystone.Keystone; -import com.woorea.openstack.keystone.model.Access; -import com.woorea.openstack.keystone.model.Authentication; -import com.woorea.openstack.keystone.utils.KeystoneUtils; - -public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin{ - - private MsoPropertiesFactory msoPropertiesFactory; - - private CloudConfigFactory cloudConfigFactory; - - private static final String TOKEN_AUTH = "TokenAuth"; - - private static final String QUERY_ALL_STACKS = "QueryAllStacks"; - - private static final String DELETE_STACK = "DeleteStack"; - - private static final String HEAT_ERROR = "HeatError"; - - private static final String CREATE_STACK = "CreateStack"; - - // Cache Heat Clients statically. Since there is just one MSO user, there is no - // benefit to re-authentication on every request (or across different flows). The - // token will be used until it expires. - // - // The cache key is "tenantId:cloudId" - private static Map <String, HeatCacheEntry> heatClientCache = new HashMap <> (); - - private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - - protected MsoJavaProperties msoProps = null; - - // Properties names and variables (with default values) - protected String createPollIntervalProp = "ecomp.mso.adapters.heat.create.pollInterval"; - private String deletePollIntervalProp = "ecomp.mso.adapters.heat.delete.pollInterval"; - private String deletePollTimeoutProp = "ecomp.mso.adapters.heat.delete.pollTimeout"; - - protected int createPollIntervalDefault = 15; - private int deletePollIntervalDefault = 15; - private int deletePollTimeoutDefault = 300; - private String msoPropID; - - private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); - - /** - * This constructor MUST be used ONLY in the JUNIT tests, not for real code. - */ - public MsoHeatUtils() { - - } - - /** - * This constructor MUST be used ONLY in the JUNIT tests, not for real code. - * The MsoPropertiesFactory will be added by EJB injection. - * - * @param msoPropID ID of the mso pro config as defined in web.xml - * @param msoPropFactory The mso properties factory instanciated by EJB injection - * @param cloudConfFactory the Cloud Config instantiated by EJB injection - */ - public MsoHeatUtils (String msoPropID, MsoPropertiesFactory msoPropFactory, CloudConfigFactory cloudConfFactory) { - msoPropertiesFactory = msoPropFactory; - cloudConfigFactory = cloudConfFactory; - this.msoPropID = msoPropID; - // Dynamically get properties each time (in case reloaded). - - try { - msoProps = msoPropertiesFactory.getMsoJavaProperties (msoPropID); - } catch (MsoPropertiesException e) { - LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. Mso Properties ID not found in cache: " + msoPropID, "", "", MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e); - } - LOGGER.debug("MsoHeatUtils:" + msoPropID); - } - - protected CloudConfigFactory getCloudConfigFactory() { - return cloudConfigFactory; - } - - /** - * keep this old method signature here to maintain backwards compatibility. keep others as well. - * this method does not include environment, files, or heatFiles - */ - public StackInfo createStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, ?> stackInputs, - boolean pollForCompletion, - int timeoutMinutes) throws MsoException { - // Just call the new method with the environment & files variable set to null - return this.createStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - null, - null, - null, - true); - } - - // This method has environment, but not files or heatFiles - public StackInfo createStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, ?> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment) throws MsoException { - // Just call the new method with the files/heatFiles variables set to null - return this.createStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - environment, - null, - null, - true); - } - - // This method has environment and files, but not heatFiles. - public StackInfo createStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, ?> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment, - Map <String, Object> files) throws MsoException { - return this.createStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - environment, - files, - null, - true); - } - - // This method has environment, files, heatfiles - public StackInfo createStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, ?> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment, - Map <String, Object> files, - Map <String, Object> heatFiles) throws MsoException { - return this.createStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - environment, - files, - heatFiles, - true); - } - - /** - * Create a new Stack in the specified cloud location and tenant. The Heat template - * and parameter map are passed in as arguments, along with the cloud access credentials. - * It is expected that parameters have been validated and contain at minimum the required - * parameters for the given template with no extra (undefined) parameters.. - * - * The Stack name supplied by the caller must be unique in the scope of this tenant. - * However, it should also be globally unique, as it will be the identifier for the - * resource going forward in Inventory. This latter is managed by the higher levels - * invoking this function. - * - * The caller may choose to let this function poll Openstack for completion of the - * stack creation, or may handle polling itself via separate calls to query the status. - * In either case, a StackInfo object will be returned containing the current status. - * When polling is enabled, a status of CREATED is expected. When not polling, a - * status of BUILDING is expected. - * - * An error will be thrown if the requested Stack already exists in the specified - * Tenant and Cloud. - * - * For 1510 - add "environment", "files" (nested templates), and "heatFiles" (get_files) as - * parameters for createStack. If environment is non-null, it will be added to the stack. - * The nested templates and get_file entries both end up being added to the "files" on the - * stack. We must combine them before we add them to the stack if they're both non-null. - * - * @param cloudSiteId The cloud (may be a region) in which to create the stack. - * @param tenantId The Openstack ID of the tenant in which to create the Stack - * @param stackName The name of the stack to create - * @param heatTemplate The Heat template - * @param stackInputs A map of key/value inputs - * @param pollForCompletion Indicator that polling should be handled in Java vs. in the client - * @param environment An optional yaml-format string to specify environmental parameters - * @param files a Map<String, Object> that lists the child template IDs (file is the string, object is an int of - * Template id) - * @param heatFiles a Map<String, Object> that lists the get_file entries (fileName, fileBody) - * @param backout Donot delete stack on create Failure - defaulted to True - * @return A StackInfo object - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception. - */ - - @SuppressWarnings("unchecked") - public StackInfo createStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, ?> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment, - Map <String, Object> files, - Map <String, Object> heatFiles, - boolean backout) throws MsoException { - // Create local variables checking to see if we have an environment, nested, get_files - // Could later add some checks to see if it's valid. - boolean haveEnvtVariable = true; - if (environment == null || "".equalsIgnoreCase (environment.trim ())) { - haveEnvtVariable = false; - LOGGER.debug ("createStack called with no environment variable"); - } else { - LOGGER.debug ("createStack called with an environment variable: " + environment); - } - - boolean haveFiles = true; - if (files == null || files.isEmpty ()) { - haveFiles = false; - LOGGER.debug ("createStack called with no files / child template ids"); - } else { - LOGGER.debug ("createStack called with " + files.size () + " files / child template ids"); - } - - boolean haveHeatFiles = true; - if (heatFiles == null || heatFiles.isEmpty ()) { - haveHeatFiles = false; - LOGGER.debug ("createStack called with no heatFiles"); - } else { - LOGGER.debug ("createStack called with " + heatFiles.size () + " heatFiles"); - } - - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - LOGGER.debug("Found: " + cloudSite.toString()); - // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId) - // This could throw MsoTenantNotFound or MsoOpenstackException (both propagated) - Heat heatClient = getHeatClient (cloudSite, tenantId); - if (heatClient != null) { - LOGGER.debug("Found: " + heatClient.toString()); - } - - LOGGER.debug ("Ready to Create Stack (" + heatTemplate + ") with input params: " + stackInputs); - - // Build up the stack to create - // Disable auto-rollback, because error reason is lost. Always rollback in the code. - CreateStackParam stack = new CreateStackParam (); - stack.setStackName (stackName); - stack.setTimeoutMinutes (timeoutMinutes); - stack.setParameters ((Map <String, Object>) stackInputs); - stack.setTemplate (heatTemplate); - stack.setDisableRollback (true); - // TJM New for PO Adapter - add envt variable - if (haveEnvtVariable) { - LOGGER.debug ("Found an environment variable - value: " + environment); - stack.setEnvironment (environment); - } - // Now handle nested templates or get_files - have to combine if we have both - // as they're both treated as "files:" on the stack. - if (haveFiles && haveHeatFiles) { - // Let's do this here - not in the bean - LOGGER.debug ("Found files AND heatFiles - combine and add!"); - Map <String, Object> combinedFiles = new HashMap <> (); - for (String keyString : files.keySet ()) { - combinedFiles.put (keyString, files.get (keyString)); - } - for (String keyString : heatFiles.keySet ()) { - combinedFiles.put (keyString, heatFiles.get (keyString)); - } - stack.setFiles (combinedFiles); - } else { - // Handle if we only have one or neither: - if (haveFiles) { - LOGGER.debug ("Found files - adding to stack"); - stack.setFiles (files); - } - if (haveHeatFiles) { - LOGGER.debug ("Found heatFiles - adding to stack"); - // the setFiles was modified to handle adding the entries - stack.setFiles (heatFiles); - } - } - - // 1802 - attempt to add better formatted printout of request to openstack - try { - Map<String, Object> inputs = new HashMap<String, Object>(); - for (String key : stackInputs.keySet()) { - Object o = (Object) stackInputs.get(key); - if (o != null) { - inputs.put(key, o); - } - } - LOGGER.debug(this.printStackRequest(tenantId, heatFiles, files, environment, inputs, stackName, heatTemplate, timeoutMinutes, backout, cloudSiteId)); - } catch (Exception e) { - // that's okay - this is a nice-to-have - LOGGER.debug("(had an issue printing nicely formatted request to debuglog) " + e.getMessage()); - } - - Stack heatStack = null; - try { - // Execute the actual Openstack command to create the Heat stack - OpenStackRequest <Stack> request = heatClient.getStacks ().create (stack); - // Begin X-Auth-User - // Obtain an MSO token for the tenant - CloudIdentity cloudIdentity = cloudSite.getIdentityService (); - // cloudIdentity.getMsoId(), cloudIdentity.getMsoPass() - //req - request.header ("X-Auth-User", cloudIdentity.getMsoId ()); - request.header ("X-Auth-Key", cloudIdentity.getMsoPass ()); - LOGGER.debug ("headers added, about to executeAndRecordOpenstackRequest"); - //LOGGER.debug(this.requestToStringBuilder(stack).toString()); - // END - try to fix X-Auth-User - heatStack = executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - // Since this came on the 'Create Stack' command, nothing was changed - // in the cloud. Return the error as an exception. - if (e.getStatus () == 409) { - // Stack already exists. Return a specific error for this case - MsoStackAlreadyExists me = new MsoStackAlreadyExists (stackName, tenantId, cloudSiteId); - me.addContext (CREATE_STACK); - throw me; - } else { - // Convert the OpenStackResponseException to an MsoOpenstackException - LOGGER.debug("ERROR STATUS = " + e.getStatus() + ",\n" + e.getMessage() + "\n" + e.getLocalizedMessage()); - throw heatExceptionToMsoException (e, CREATE_STACK); - } - } catch (OpenStackConnectException e) { - // Error connecting to Openstack instance. Convert to an MsoException - throw heatExceptionToMsoException (e, CREATE_STACK); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, CREATE_STACK); - } - - // Subsequent access by the canonical name "<stack name>/<stack-id>". - // Otherwise, simple query by name returns a 302 redirect. - // NOTE: This is specific to the v1 Orchestration API. - String canonicalName = stackName + "/" + heatStack.getId (); - - // If client has requested a final response, poll for stack completion - if (pollForCompletion) { - // Set a time limit on overall polling. - // Use the resource (template) timeout for Openstack (expressed in minutes) - // and add one poll interval to give Openstack a chance to fail on its own. - int createPollInterval = msoProps.getIntProperty (createPollIntervalProp, createPollIntervalDefault); - int pollTimeout = (timeoutMinutes * 60) + createPollInterval; - // New 1610 - poll on delete if we rollback - use same values for now - int deletePollInterval = createPollInterval; - int deletePollTimeout = pollTimeout; - boolean createTimedOut = false; - StringBuilder stackErrorStatusReason = new StringBuilder(""); - LOGGER.debug("createPollInterval=" + createPollInterval + ", pollTimeout=" + pollTimeout); - - while (true) { - try { - heatStack = queryHeatStack (heatClient, canonicalName); - LOGGER.debug (heatStack.getStackStatus () + " (" + canonicalName + ")"); - try { - LOGGER.debug("Current stack " + this.getOutputsAsStringBuilder(heatStack).toString()); - } catch (Exception e) { - LOGGER.debug("an error occurred trying to print out the current outputs of the stack", e); - } - - if ("CREATE_IN_PROGRESS".equals (heatStack.getStackStatus ())) { - // Stack creation is still running. - // Sleep and try again unless timeout has been reached - if (pollTimeout <= 0) { - // Note that this should not occur, since there is a timeout specified - // in the Openstack call. - LOGGER.error (MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName, heatStack.getStackStatus (), "", "", MsoLogger.ErrorCode.AvailabilityError, "Create stack timeout"); - createTimedOut = true; - break; - } - try { - Thread.sleep (createPollInterval * 1000L); - } catch (InterruptedException e) { - LOGGER.debug ("Thread interrupted while sleeping", e); - } - - pollTimeout -= createPollInterval; - LOGGER.debug("pollTimeout remaining: " + pollTimeout); - } else { - //save off the status & reason msg before we attempt delete - stackErrorStatusReason.append("Stack error (" + heatStack.getStackStatus() + "): " + heatStack.getStackStatusReason()); - break; - } - } catch (MsoException me) { - // Cannot query the stack status. Something is wrong. - // Try to roll back the stack - if (!backout) - { - LOGGER.warn(MessageEnum.RA_CREATE_STACK_ERR, "Create Stack errored, stack deletion suppressed", "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in Create Stack, stack deletion suppressed"); - } - else - { - try { - LOGGER.debug("Create Stack error - unable to query for stack status - attempting to delete stack: " + canonicalName + " - This will likely fail and/or we won't be able to query to see if delete worked"); - OpenStackRequest <Void> request = heatClient.getStacks ().deleteByName (canonicalName); - executeAndRecordOpenstackRequest (request, msoProps); - // this may be a waste of time - if we just got an exception trying to query the stack - we'll just - // get another one, n'est-ce pas? - boolean deleted = false; - while (!deleted) { - try { - heatStack = queryHeatStack(heatClient, canonicalName); - if (heatStack != null) { - LOGGER.debug(heatStack.getStackStatus()); - if ("DELETE_IN_PROGRESS".equals(heatStack.getStackStatus())) { - if (deletePollTimeout <= 0) { - LOGGER.error (MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName, - heatStack.getStackStatus (), "", "", MsoLogger.ErrorCode.AvailabilityError, - "Rollback: DELETE stack timeout"); - break; - } else { - try { - Thread.sleep(deletePollInterval * 1000L); - } catch (InterruptedException ie) { - LOGGER.debug("Thread interrupted while sleeping", ie); - } - deletePollTimeout -= deletePollInterval; - } - } else if ("DELETE_COMPLETE".equals(heatStack.getStackStatus())){ - LOGGER.debug("DELETE_COMPLETE for " + canonicalName); - deleted = true; - continue; - } else { - //got a status other than DELETE_IN_PROGRESS or DELETE_COMPLETE - so break and evaluate - break; - } - } else { - // assume if we can't find it - it's deleted - LOGGER.debug("heatStack returned null - assume the stack " + canonicalName + " has been deleted"); - deleted = true; - continue; - } - - } catch (Exception e3) { - // Just log this one. We will report the original exception. - LOGGER.error (MessageEnum.RA_CREATE_STACK_ERR, "Create Stack: Nested exception rolling back stack: " + e3, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create Stack: Nested exception rolling back stack on error on query"); - - } - } - } catch (Exception e2) { - // Just log this one. We will report the original exception. - LOGGER.error (MessageEnum.RA_CREATE_STACK_ERR, "Create Stack: Nested exception rolling back stack: " + e2, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create Stack: Nested exception rolling back stack"); - } - } - - // Propagate the original exception from Stack Query. - me.addContext (CREATE_STACK); - throw me; - } - } - - if (!"CREATE_COMPLETE".equals (heatStack.getStackStatus ())) { - LOGGER.error (MessageEnum.RA_CREATE_STACK_ERR, "Create Stack error: Polling complete with non-success status: " - + heatStack.getStackStatus () + ", " + heatStack.getStackStatusReason (), "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create Stack error"); - - // Rollback the stack creation, since it is in an indeterminate state. - if (!backout) - { - LOGGER.warn(MessageEnum.RA_CREATE_STACK_ERR, "Create Stack errored, stack deletion suppressed", "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create Stack error, stack deletion suppressed"); - } - else - { - try { - LOGGER.debug("Create Stack errored - attempting to DELETE stack: " + canonicalName); - LOGGER.debug("deletePollInterval=" + deletePollInterval + ", deletePollTimeout=" + deletePollTimeout); - OpenStackRequest <Void> request = heatClient.getStacks ().deleteByName (canonicalName); - executeAndRecordOpenstackRequest (request, msoProps); - boolean deleted = false; - while (!deleted) { - try { - heatStack = queryHeatStack(heatClient, canonicalName); - if (heatStack != null) { - LOGGER.debug(heatStack.getStackStatus() + " (" + canonicalName + ")"); - if ("DELETE_IN_PROGRESS".equals(heatStack.getStackStatus())) { - if (deletePollTimeout <= 0) { - LOGGER.error (MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName, - heatStack.getStackStatus (), "", "", MsoLogger.ErrorCode.AvailabilityError, - "Rollback: DELETE stack timeout"); - break; - } else { - try { - Thread.sleep(deletePollInterval * 1000L); - } catch (InterruptedException ie) { - LOGGER.debug("Thread interrupted while sleeping", ie); - } - deletePollTimeout -= deletePollInterval; - LOGGER.debug("deletePollTimeout remaining: " + deletePollTimeout); - } - } else if ("DELETE_COMPLETE".equals(heatStack.getStackStatus())){ - LOGGER.debug("DELETE_COMPLETE for " + canonicalName); - deleted = true; - continue; - } else if ("DELETE_FAILED".equals(heatStack.getStackStatus())) { - // Warn about this (?) - but still throw the original exception - LOGGER.warn(MessageEnum.RA_CREATE_STACK_ERR, "Create Stack errored, stack deletion FAILED", "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create Stack error, stack deletion FAILED"); - LOGGER.debug("Stack deletion FAILED on a rollback of a create - " + canonicalName + ", status=" + heatStack.getStackStatus() + ", reason=" + heatStack.getStackStatusReason()); - break; - } else { - //got a status other than DELETE_IN_PROGRESS or DELETE_COMPLETE - so break and evaluate - break; - } - } else { - // assume if we can't find it - it's deleted - LOGGER.debug("heatStack returned null - assume the stack " + canonicalName + " has been deleted"); - deleted = true; - continue; - } - - } catch (MsoException me2) { - // We got an exception on the delete - don't throw this exception - throw the original - just log. - LOGGER.debug("Exception thrown trying to delete " + canonicalName + " on a create->rollback: " + me2.getContextMessage(), me2); - LOGGER.warn(MessageEnum.RA_CREATE_STACK_ERR, "Create Stack errored, then stack deletion FAILED - exception thrown", "", "", MsoLogger.ErrorCode.BusinessProcesssError, me2.getContextMessage()); - } - - } // end while !deleted - StringBuilder errorContextMessage; - if (createTimedOut) { - errorContextMessage = new StringBuilder("Stack Creation Timeout"); - } else { - errorContextMessage = stackErrorStatusReason; - } - if (deleted) { - errorContextMessage.append(" - stack successfully deleted"); - } else { - errorContextMessage.append(" - encountered an error trying to delete the stack"); - } -// MsoOpenstackException me = new MsoOpenstackException(0, "", stackErrorStatusReason.toString()); - // me.addContext(CREATE_STACK); - // alarmLogger.sendAlarm(HEAT_ERROR, MsoAlarmLogger.CRITICAL, me.getContextMessage()); - // throw me; - } catch (Exception e2) { - // shouldn't happen - but handle - LOGGER.error (MessageEnum.RA_CREATE_STACK_ERR, "Create Stack: Nested exception rolling back stack: " + e2, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in Create Stack: rolling back stack"); - } - } - MsoOpenstackException me = new MsoOpenstackException(0, "", stackErrorStatusReason.toString()); - me.addContext(CREATE_STACK); - alarmLogger.sendAlarm(HEAT_ERROR, MsoAlarmLogger.CRITICAL, me.getContextMessage()); - throw me; - } - - } else { - // Get initial status, since it will have been null after the create. - heatStack = queryHeatStack (heatClient, canonicalName); - LOGGER.debug (heatStack.getStackStatus ()); - } - - return new StackInfo (heatStack); - } - - /** - * Query for a single stack (by Name) in a tenant. This call will always return a - * StackInfo object. If the stack does not exist, an "empty" StackInfo will be - * returned - containing only the stack name and a status of NOTFOUND. - * - * @param tenantId The Openstack ID of the tenant in which to query - * @param cloudSiteId The cloud identifier (may be a region) in which to query - * @param stackName The name of the stack to query (may be simple or canonical) - * @return A StackInfo object - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception. - */ - public StackInfo queryStack (String cloudSiteId, String tenantId, String stackName) throws MsoException { - LOGGER.debug ("Query HEAT stack: " + stackName + " in tenant " + tenantId); - - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - LOGGER.debug("Found: " + cloudSite.toString()); - - // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId) - Heat heatClient = null; - try { - heatClient = getHeatClient (cloudSite, tenantId); - if (heatClient != null) { - LOGGER.debug("Found: " + heatClient.toString()); - } - } catch (MsoTenantNotFound e) { - // Tenant doesn't exist, so stack doesn't either - LOGGER.debug ("Tenant with id " + tenantId + "not found.", e); - return new StackInfo (stackName, HeatStatus.NOTFOUND); - } catch (MsoException me) { - // Got an Openstack error. Propagate it - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Exception on Token request: " + me, "Openstack", "", MsoLogger.ErrorCode.AvailabilityError, "Connection Exception"); - me.addContext ("QueryStack"); - throw me; - } - - // Query the Stack. - // An MsoException will propagate transparently to the caller. - Stack heatStack = queryHeatStack (heatClient, stackName); - - if (heatStack == null) { - // Stack does not exist. Return a StackInfo with status NOTFOUND - StackInfo stackInfo = new StackInfo (stackName, HeatStatus.NOTFOUND); - return stackInfo; - } - - return new StackInfo (heatStack); - } - - /** - * Delete a stack (by Name/ID) in a tenant. If the stack is not found, it will be - * considered a successful deletion. The return value is a StackInfo object which - * contains the current stack status. - * - * The client may choose to let the adapter poll Openstack for completion of the - * stack deletion, or may handle polling itself via separate query calls. In either - * case, a StackInfo object will be returned. When polling is enabled, a final - * status of NOTFOUND is expected. When not polling, a status of DELETING is expected. - * - * There is no rollback from a successful stack deletion. A deletion failure will - * also result in an undefined stack state - the components may or may not have been - * all or partially deleted, so the resulting stack must be considered invalid. - * - * @param tenantId The Openstack ID of the tenant in which to perform the delete - * @param cloudSiteId The cloud identifier (may be a region) from which to delete the stack. - * @param stackName The name/id of the stack to delete. May be simple or canonical - * @param pollForCompletion Indicator that polling should be handled in Java vs. in the client - * @return A StackInfo object - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception. - * @throws MsoCloudSiteNotFound - */ - public StackInfo deleteStack (String tenantId, - String cloudSiteId, - String stackName, - boolean pollForCompletion) throws MsoException { - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - LOGGER.debug("Found: " + cloudSite.toString()); - - // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId) - Heat heatClient = null; - try { - heatClient = getHeatClient (cloudSite, tenantId); - if (heatClient != null) { - LOGGER.debug("Found: " + heatClient.toString()); - } - } catch (MsoTenantNotFound e) { - // Tenant doesn't exist, so stack doesn't either - LOGGER.debug ("Tenant with id " + tenantId + "not found.", e); - return new StackInfo (stackName, HeatStatus.NOTFOUND); - } catch (MsoException me) { - // Got an Openstack error. Propagate it - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack", "Openstack Exception on Token request: " + me, "Openstack", "", MsoLogger.ErrorCode.AvailabilityError, "Connection Exception"); - me.addContext (DELETE_STACK); - throw me; - } - - // OK if stack not found, perform a query first - Stack heatStack = queryHeatStack (heatClient, stackName); - if (heatStack == null || "DELETE_COMPLETE".equals (heatStack.getStackStatus ())) { - // Not found. Return a StackInfo with status NOTFOUND - return new StackInfo (stackName, HeatStatus.NOTFOUND); - } - - // Delete the stack. - - // Use canonical name "<stack name>/<stack-id>" to delete. - // Otherwise, deletion by name returns a 302 redirect. - // NOTE: This is specific to the v1 Orchestration API. - String canonicalName = heatStack.getStackName () + "/" + heatStack.getId (); - - try { - OpenStackRequest <Void> request = null; - if(null != heatClient) { - request = heatClient.getStacks ().deleteByName (canonicalName); - } - else { - LOGGER.debug ("Heat Client is NULL" ); - } - - executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - // Not found. We are OK with this. Return a StackInfo with status NOTFOUND - return new StackInfo (stackName, HeatStatus.NOTFOUND); - } else { - // Convert the OpenStackResponseException to an MsoOpenstackException - throw heatExceptionToMsoException (e, DELETE_STACK); - } - } catch (OpenStackConnectException e) { - // Error connecting to Openstack instance. Convert to an MsoException - throw heatExceptionToMsoException (e, DELETE_STACK); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, DELETE_STACK); - } - - // Requery the stack for current status. - // It will probably still exist with "DELETE_IN_PROGRESS" status. - heatStack = queryHeatStack (heatClient, canonicalName); - - if (pollForCompletion) { - // Set a timeout on polling - int pollInterval = msoProps.getIntProperty (deletePollIntervalProp, deletePollIntervalDefault); - int pollTimeout = msoProps.getIntProperty (deletePollTimeoutProp, deletePollTimeoutDefault); - - // When querying by canonical name, Openstack returns DELETE_COMPLETE status - // instead of "404" (which would result from query by stack name). - while (heatStack != null && !"DELETE_COMPLETE".equals (heatStack.getStackStatus ())) { - LOGGER.debug ("Stack status: " + heatStack.getStackStatus ()); - - if ("DELETE_FAILED".equals (heatStack.getStackStatus ())) { - // Throw a 'special case' of MsoOpenstackException to report the Heat status - String error = "Stack delete error (" + heatStack.getStackStatus () - + "): " - + heatStack.getStackStatusReason (); - MsoOpenstackException me = new MsoOpenstackException (0, "", error); - me.addContext (DELETE_STACK); - - // Alarm this condition, stack deletion failed - alarmLogger.sendAlarm (HEAT_ERROR, MsoAlarmLogger.CRITICAL, me.getContextMessage ()); - - throw me; - } - - if (pollTimeout <= 0) { - LOGGER.error (MessageEnum.RA_DELETE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName, heatStack.getStackStatus (), "", "", MsoLogger.ErrorCode.AvailabilityError, "Delete Stack Timeout"); - - // Throw a 'special case' of MsoOpenstackException to report the Heat status - MsoOpenstackException me = new MsoOpenstackException (0, "", "Stack Deletion Timeout"); - me.addContext (DELETE_STACK); - - // Alarm this condition, stack deletion failed - alarmLogger.sendAlarm (HEAT_ERROR, MsoAlarmLogger.CRITICAL, me.getContextMessage ()); - - throw me; - } - - try { - Thread.sleep (pollInterval * 1000L); - } catch (InterruptedException e) { - LOGGER.debug ("Thread interrupted while sleeping", e); - } - - pollTimeout -= pollInterval; - - heatStack = queryHeatStack (heatClient, canonicalName); - } - - // The stack is gone when this point is reached - return new StackInfo (stackName, HeatStatus.NOTFOUND); - } - - // Return the current status (if not polling, the delete may still be in progress) - StackInfo stackInfo = new StackInfo (heatStack); - stackInfo.setName (stackName); - - return stackInfo; - } - - /** - * Query for all stacks in a tenant site. This call will return a List of StackInfo - * objects, one for each deployed stack. - * - * Note that this is limited to a single site. To ensure that a tenant is truly - * empty would require looping across all tenant endpoints. - * - * @param tenantId The Openstack ID of the tenant to query - * @param cloudSiteId The cloud identifier (may be a region) in which to query. - * @return A List of StackInfo objects - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception. - * @throws MsoCloudSiteNotFound - */ - public List <StackInfo> queryAllStacks (String tenantId, String cloudSiteId) throws MsoException { - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId) - Heat heatClient = getHeatClient (cloudSite, tenantId); - - try { - OpenStackRequest <Stacks> request = heatClient.getStacks ().list (); - Stacks stacks = executeAndRecordOpenstackRequest (request, msoProps); - - List <StackInfo> stackList = new ArrayList <> (); - - // Not sure if returns an empty list or null if no stacks exist - if (stacks != null) { - for (Stack stack : stacks) { - stackList.add (new StackInfo (stack)); - } - } - - return stackList; - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - // Not sure if this can happen, but return an empty list - LOGGER.debug ("queryAllStacks - stack not found: "); - return new ArrayList <> (); - } else { - // Convert the OpenStackResponseException to an MsoOpenstackException - throw heatExceptionToMsoException (e, QUERY_ALL_STACKS); - } - } catch (OpenStackConnectException e) { - // Error connecting to Openstack instance. Convert to an MsoException - throw heatExceptionToMsoException (e, QUERY_ALL_STACKS); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, QUERY_ALL_STACKS); - } - } - - /** - * Validate parameters to be passed to Heat template. This method performs - * three functions: - * 1. Apply default values to parameters which have them defined - * 2. Report any required parameters that are missing. This will generate an - * exception in the caller, since stack create/update operations would fail. - * 3. Report and remove any extraneous parameters. This will allow clients to - * pass supersets of parameters and not get errors. - * - * These functions depend on the HeatTemplate definition from the MSO Catalog DB, - * along with the input parameter Map. The output is an updated parameter map. - * If the parameters are invalid for the template, an IllegalArgumentException - * is thrown. - */ - public Map <String, Object> validateStackParams (Map <String, Object> inputParams, - HeatTemplate heatTemplate) throws IllegalArgumentException { - // Check that required parameters have been supplied for this template type - StringBuilder missingParams = null; - List <String> paramList = new ArrayList <> (); - - // TODO: Enhance DB to support defaults for Heat Template parameters - - for (HeatTemplateParam parm : heatTemplate.getParameters ()) { - if (parm.isRequired () && !inputParams.containsKey (parm.getParamName ())) { - if (missingParams == null) { - missingParams = new StringBuilder(parm.getParamName()); - } else { - missingParams.append("," + parm.getParamName()); - } - } - paramList.add (parm.getParamName ()); - } - if (missingParams != null) { - // Problem - missing one or more required parameters - String error = "Missing Required inputs for HEAT Template: " + missingParams; - LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams + " for HEAT Template", "", "", MsoLogger.ErrorCode.SchemaError, "Missing Required inputs for HEAT Template: " + missingParams); - throw new IllegalArgumentException (error); - } - - // Remove any extraneous parameters (don't throw an error) - Map <String, Object> updatedParams = new HashMap <> (); - List <String> extraParams = new ArrayList <> (); - for (String key : inputParams.keySet ()) { - if (!paramList.contains (key)) { - // This is not a valid parameter for this template - extraParams.add (key); - } else { - updatedParams.put (key, inputParams.get (key)); - } - } - if (!extraParams.isEmpty ()) { - LOGGER.warn (MessageEnum.RA_GENERAL_WARNING, "Heat Stack (" + heatTemplate.getTemplateName () - + ") extra input params received: " - + extraParams, "", "", MsoLogger.ErrorCode.DataError, "Heat Stack (" + heatTemplate.getTemplateName () + ") extra input params received: "+ extraParams); - } - - return updatedParams; - } - - // --------------------------------------------------------------- - // PRIVATE FUNCTIONS FOR USE WITHIN THIS CLASS - - /** - * Get a Heat client for the Openstack Identity service. - * This requires a 'member'-level userId + password, which will be retrieved from - * properties based on the specified cloud Id. The tenant in which to operate - * must also be provided. - * <p> - * On successful authentication, the Heat object will be cached for the - * tenantID + cloudId so that it can be reused without reauthenticating with - * Openstack every time. - * - * @return an authenticated Heat object - */ - public Heat getHeatClient (CloudSite cloudSite, String tenantId) throws MsoException { - String cloudId = cloudSite.getId (); - - // Check first in the cache of previously authorized clients - String cacheKey = cloudId + ":" + tenantId; - if (heatClientCache.containsKey (cacheKey)) { - if (!heatClientCache.get (cacheKey).isExpired ()) { - LOGGER.debug ("Using Cached HEAT Client for " + cacheKey); - return heatClientCache.get (cacheKey).getHeatClient (); - } else { - // Token is expired. Remove it from cache. - heatClientCache.remove (cacheKey); - LOGGER.debug ("Expired Cached HEAT Client for " + cacheKey); - } - } - - // Obtain an MSO token for the tenant - CloudIdentity cloudIdentity = cloudSite.getIdentityService (); - LOGGER.debug("Found: " + cloudIdentity.toString()); - String keystoneUrl = cloudIdentity.getKeystoneUrl (cloudId, msoPropID); - LOGGER.debug("keystoneUrl=" + keystoneUrl); - Keystone keystoneTenantClient = new Keystone (keystoneUrl); - Access access = null; - try { - Authentication credentials = cloudIdentity.getAuthentication (); - - OpenStackRequest <Access> request = keystoneTenantClient.tokens () - .authenticate (credentials).withTenantId (tenantId); - - access = executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 401) { - // Authentication error. - String error = "Authentication Failure: tenant=" + tenantId + ",cloud=" + cloudIdentity.getId (); - alarmLogger.sendAlarm ("MsoAuthenticationError", MsoAlarmLogger.CRITICAL, error); - throw new MsoAdapterException (error); - } else { - throw keystoneErrorToMsoException (e, TOKEN_AUTH); - } - } catch (OpenStackConnectException e) { - // Connection to Openstack failed - MsoIOException me = new MsoIOException (e.getMessage (), e); - me.addContext (TOKEN_AUTH); - throw me; - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, TOKEN_AUTH); - } - - // For DCP/LCP, the region should be the cloudId. - String region = cloudSite.getRegionId (); - String heatUrl = null; - try { - heatUrl = KeystoneUtils.findEndpointURL (access.getServiceCatalog (), "orchestration", region, "public"); - LOGGER.debug("heatUrl=" + heatUrl + ", region=" + region); - } catch (RuntimeException e) { - // This comes back for not found (probably an incorrect region ID) - String error = "Orchestration service not found: region=" + region + ",cloud=" + cloudIdentity.getId (); - alarmLogger.sendAlarm ("MsoConfigurationError", MsoAlarmLogger.CRITICAL, error); - throw new MsoAdapterException (error, e); - } - - Heat heatClient = new Heat (heatUrl); - heatClient.token (access.getToken ().getId ()); - - heatClientCache.put (cacheKey, - new HeatCacheEntry (heatUrl, - access.getToken ().getId (), - access.getToken ().getExpires ())); - LOGGER.debug ("Caching HEAT Client for " + cacheKey); - - return heatClient; - } - - /** - * Forcibly expire a HEAT client from the cache. This call is for use by - * the KeystoneClient in case where a tenant is deleted. In that case, - * all cached credentials must be purged so that fresh authentication is - * done if a similarly named tenant is re-created. - * <p> - * Note: This is probably only applicable to dev/test environments where - * the same Tenant Name is repeatedly used for creation/deletion. - * <p> - * - */ - public static void expireHeatClient (String tenantId, String cloudId) { - String cacheKey = cloudId + ":" + tenantId; - if (heatClientCache.containsKey (cacheKey)) { - heatClientCache.remove (cacheKey); - LOGGER.debug ("Deleted Cached HEAT Client for " + cacheKey); - } - } - - /* - * Query for a Heat Stack. This function is needed in several places, so - * a common method is useful. This method takes an authenticated Heat Client - * (which internally identifies the cloud & tenant to search), and returns - * a Stack object if found, Null if not found, or an MsoOpenstackException - * if the Openstack API call fails. - * - * The stack name may be a simple name or a canonical name ("{name}/{id}"). - * When simple name is used, Openstack always returns a 302 redirect which - * results in a 2nd request (to the canonical name). Note that query by - * canonical name for a deleted stack returns a Stack object with status - * "DELETE_COMPLETE" while query by simple name for a deleted stack returns - * HTTP 404. - * - * @param heatClient an authenticated Heat client - * - * @param stackName the stack name to query - * - * @return a Stack object that describes the current stack or null if the - * requested stack doesn't exist. - * - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - */ - protected Stack queryHeatStack (Heat heatClient, String stackName) throws MsoException { - if (stackName == null) { - return null; - } - try { - OpenStackRequest <Stack> request = heatClient.getStacks ().byName (stackName); - return executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - LOGGER.debug ("queryHeatStack - stack not found: " + stackName); - return null; - } else { - // Convert the OpenStackResponseException to an MsoOpenstackException - throw heatExceptionToMsoException (e, "QueryStack"); - } - } catch (OpenStackConnectException e) { - // Connection to Openstack failed - throw heatExceptionToMsoException (e, "QueryAllStack"); - } - } - - /* - * An entry in the Heat Client Cache. It saves the Heat client object - * along with the token expiration. After this interval, this cache - * item will no longer be used. - */ - private static class HeatCacheEntry implements Serializable { - - private static final long serialVersionUID = 1L; - - private String heatUrl; - private String token; - private Calendar expires; - - public HeatCacheEntry (String heatUrl, String token, Calendar expires) { - this.heatUrl = heatUrl; - this.token = token; - this.expires = expires; - } - - public Heat getHeatClient () { - Heat heatClient = new Heat (heatUrl); - heatClient.token (token); - return heatClient; - } - - public boolean isExpired () { - return expires == null || System.currentTimeMillis() > expires.getTimeInMillis(); - - } - } - - /** - * Clean up the Heat client cache to remove expired entries. - */ - public static void heatCacheCleanup () { - for (String cacheKey : heatClientCache.keySet ()) { - if (heatClientCache.get (cacheKey).isExpired ()) { - heatClientCache.remove (cacheKey); - LOGGER.debug ("Cleaned Up Cached Heat Client for " + cacheKey); - } - } - } - - /** - * Reset the Heat client cache. - * This may be useful if cached credentials get out of sync. - */ - public static void heatCacheReset () { - heatClientCache = new HashMap <> (); - } - - public Map<String, Object> queryStackForOutputs(String cloudSiteId, - String tenantId, String stackName) throws MsoException { - LOGGER.debug("MsoHeatUtils.queryStackForOutputs)"); - StackInfo heatStack = this.queryStack(cloudSiteId, tenantId, stackName); - if (heatStack == null || heatStack.getStatus() == HeatStatus.NOTFOUND) { - return null; - } - Map<String, Object> outputs = heatStack.getOutputs(); - return outputs; - } - - public void queryAndCopyOutputsToInputs(String cloudSiteId, - String tenantId, String stackName, Map<String, String> inputs, - boolean overWrite) throws MsoException { - LOGGER.debug("MsoHeatUtils.queryAndCopyOutputsToInputs"); - Map<String, Object> outputs = this.queryStackForOutputs(cloudSiteId, - tenantId, stackName); - this.copyStringOutputsToInputs(inputs, outputs, overWrite); - return; - } - - public void copyStringOutputsToInputs(Map<String, String> inputs, - Map<String, Object> otherStackOutputs, boolean overWrite) { - if (inputs == null || otherStackOutputs == null) - return; - for (String key : otherStackOutputs.keySet()) { - if (!inputs.containsKey(key)) { - Object obj = otherStackOutputs.get(key); - if (obj instanceof String) { - inputs.put(key, (String) otherStackOutputs.get(key)); - } else if (obj instanceof JsonNode ){ - // This is a bit of mess - but I think it's the least impacting - // let's convert it BACK to a string - then it will get converted back later - try { - String str = this.convertNode((JsonNode) obj); - inputs.put(key, str); - } catch (Exception e) { - LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key, e); - //effect here is this value will not have been copied to the inputs - and therefore will error out downstream - } - } else if (obj instanceof java.util.LinkedHashMap) { - LOGGER.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode"); - try { - String str = JSON_MAPPER.writeValueAsString(obj); - inputs.put(key, str); - } catch (Exception e) { - LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key, e); - } - } else if (obj instanceof Integer) { - try { - String str = "" + obj; - inputs.put(key, str); - } catch (Exception e) { - LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key, e); - } - } else { - try { - String str = obj.toString(); - inputs.put(key, str); - } catch (Exception e) { - LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for Other "+ key +" (" + e.getMessage() + ")", e); - //effect here is this value will not have been copied to the inputs - and therefore will error out downstream - } - } - } - } - return; - } - public StringBuilder requestToStringBuilder(CreateStackParam stack) { - StringBuilder sb = new StringBuilder(); - sb.append("Stack:\n"); - sb.append("\tStackName: " + stack.getStackName()); - sb.append("\tTemplateUrl: " + stack.getTemplateUrl()); - sb.append("\tTemplate: " + stack.getTemplate()); - sb.append("\tEnvironment: " + stack.getEnvironment()); - sb.append("\tTimeout: " + stack.getTimeoutMinutes()); - sb.append("\tParameters:\n"); - Map<String, Object> params = stack.getParameters(); - if (params == null || params.size() < 1) { - sb.append("\nNONE"); - } else { - for (String key : params.keySet()) { - if (params.get(key) instanceof String) { - sb.append("\n").append(key).append("=").append((String) params.get(key)); - } else if (params.get(key) instanceof JsonNode) { - String jsonStringOut = this.convertNode((JsonNode)params.get(key)); - sb.append("\n").append(key).append("=").append(jsonStringOut); - } else if (params.get(key) instanceof Integer) { - String integerOut = "" + params.get(key); - sb.append("\n").append(key).append("=").append(integerOut); - - } else { - try { - String str = params.get(key).toString(); - sb.append("\n").append(key).append("=").append(str); - } catch (Exception e) { - LOGGER.debug("Exception :",e); - } - } - } - } - return sb; - } - - private String convertNode(final JsonNode node) { - try { - final Object obj = JSON_MAPPER.treeToValue(node, Object.class); - final String json = JSON_MAPPER.writeValueAsString(obj); - return json; - } catch (Exception e) { - LOGGER.debug("Error converting json to string " + e.getMessage(), e); - } - return "[Error converting json to string]"; - } - - - private StringBuilder getOutputsAsStringBuilder(Stack heatStack) { - // This should only be used as a utility to print out the stack outputs - // to the log - StringBuilder sb = new StringBuilder(""); - if (heatStack == null) { - sb.append("(heatStack is null)"); - return sb; - } - List<Output> outputList = heatStack.getOutputs(); - if (outputList == null || outputList.isEmpty()) { - sb.append("(outputs is empty)"); - return sb; - } - Map<String, Object> outputs = new HashMap<>(); - for (Output outputItem : outputList) { - outputs.put(outputItem.getOutputKey(), outputItem.getOutputValue()); - } - int counter = 0; - sb.append("OUTPUTS:\n"); - for (String key : outputs.keySet()) { - sb.append("outputs[").append(counter++).append("]: ").append(key).append("="); - Object obj = outputs.get(key); - if (obj instanceof String) { - sb.append((String) obj).append(" (a string)"); - } else if (obj instanceof JsonNode) { - sb.append(this.convertNode((JsonNode) obj)).append(" (a JsonNode)"); - } else if (obj instanceof java.util.LinkedHashMap) { - try { - String str = JSON_MAPPER.writeValueAsString(obj); - sb.append(str).append(" (a java.util.LinkedHashMap)"); - } catch (Exception e) { - LOGGER.debug("Exception :",e); - sb.append("(a LinkedHashMap value that would not convert nicely)"); - } - } else if (obj instanceof Integer) { - String str = ""; - try { - str = obj.toString() + " (an Integer)\n"; - } catch (Exception e) { - LOGGER.debug("Exception :",e); - str = "(an Integer unable to call .toString() on)"; - } - sb.append(str); - } else if (obj instanceof ArrayList) { - String str = ""; - try { - str = obj.toString() + " (an ArrayList)"; - } catch (Exception e) { - LOGGER.debug("Exception :",e); - str = "(an ArrayList unable to call .toString() on?)"; - } - sb.append(str); - } else if (obj instanceof Boolean) { - String str = ""; - try { - str = obj.toString() + " (a Boolean)"; - } catch (Exception e) { - LOGGER.debug("Exception :",e); - str = "(an Boolean unable to call .toString() on?)"; - } - sb.append(str); - } - else { - String str = ""; - try { - str = obj.toString() + " (unknown Object type)"; - } catch (Exception e) { - LOGGER.debug("Exception :",e); - str = "(a value unable to call .toString() on?)"; - } - sb.append(str); - } - sb.append("\n"); - } - sb.append("[END]"); - return sb; - } - - - public void copyBaseOutputsToInputs(Map<String, Object> inputs, - Map<String, Object> otherStackOutputs, ArrayList<String> paramNames, HashMap<String, String> aliases) { - if (inputs == null || otherStackOutputs == null) - return; - for (String key : otherStackOutputs.keySet()) { - if (paramNames != null) { - if (!paramNames.contains(key) && !aliases.containsKey(key)) { - LOGGER.debug("\tParameter " + key + " is NOT defined to be in the template - do not copy to inputs"); - continue; - } - if (aliases.containsKey(key)) { - LOGGER.debug("Found an alias! Will move " + key + " to " + aliases.get(key)); - Object obj = otherStackOutputs.get(key); - key = aliases.get(key); - otherStackOutputs.put(key, obj); - } - } - if (!inputs.containsKey(key)) { - Object obj = otherStackOutputs.get(key); - LOGGER.debug("\t**Adding " + key + " to inputs (.toString()=" + obj.toString()); - if (obj instanceof String) { - LOGGER.debug("\t\t**A String"); - inputs.put(key, obj); - } else if (obj instanceof Integer) { - LOGGER.debug("\t\t**An Integer"); - inputs.put(key, obj); - } else if (obj instanceof JsonNode) { - LOGGER.debug("\t\t**A JsonNode"); - inputs.put(key, obj); - } else if (obj instanceof Boolean) { - LOGGER.debug("\t\t**A Boolean"); - inputs.put(key, obj); - } else if (obj instanceof java.util.LinkedHashMap) { - LOGGER.debug("\t\t**A java.util.LinkedHashMap **"); - //Object objJson = this.convertObjectToJsonNode(obj.toString()); - //if (objJson == null) { - // LOGGER.debug("\t\tFAILED!! Will just put LinkedHashMap on the inputs"); - inputs.put(key, obj); - //} - //else { - // LOGGER.debug("\t\tSuccessfully converted to JsonNode: " + objJson.toString()); - // inputs.put(key, objJson); - //} - } else if (obj instanceof java.util.ArrayList) { - LOGGER.debug("\t\t**An ArrayList"); - inputs.put(key, obj); - } else { - LOGGER.debug("\t\t**UNKNOWN OBJECT TYPE"); - inputs.put(key, obj); - } - } else { - LOGGER.debug("key=" + key + " is already in the inputs - will not overwrite"); - } - } - return; - } - - public JsonNode convertObjectToJsonNode(Object lhm) { - if (lhm == null) { - return null; - } - JsonNode jsonNode = null; - try { - String jsonString = lhm.toString(); - jsonNode = new ObjectMapper().readTree(jsonString); - } catch (Exception e) { - LOGGER.debug("Unable to convert " + lhm.toString() + " to a JsonNode " + e.getMessage(), e); - jsonNode = null; - } - return jsonNode; - } - - public ArrayList<String> convertCdlToArrayList(String cdl) { - String cdl2 = cdl.trim(); - String cdl3; - if (cdl2.startsWith("[") && cdl2.endsWith("]")) { - cdl3 = cdl2.substring(1, cdl2.lastIndexOf("]")); - } else { - cdl3 = cdl2; - } - ArrayList<String> list = new ArrayList<>(Arrays.asList(cdl3.split(","))); - return list; - } - - /** - * New with 1707 - this method will convert all the String *values* of the inputs - * to their "actual" object type (based on the param type: in the db - which comes from the template): - * (heat variable type) -> java Object type - * string -> String - * number -> Integer - * json -> JsonNode XXX Removed with MSO-1475 / 1802 - * comma_delimited_list -> ArrayList - * boolean -> Boolean - * if any of the conversions should fail, we will default to adding it to the inputs - * as a string - see if Openstack can handle it. - * Also, will remove any params that are extra. - * Any aliases will be converted to their appropriate name (anyone use this feature?) - * @param inputs - the Map<String, String> of the inputs received on the request - * @param template the HeatTemplate object - this is so we can also verify if the param is valid for this template - * @return HashMap<String, Object> of the inputs, cleaned and converted - */ - public HashMap<String, Object> convertInputMap(Map<String, String> inputs, HeatTemplate template) { - HashMap<String, Object> newInputs = new HashMap<>(); - HashMap<String, HeatTemplateParam> params = new HashMap<>(); - HashMap<String, HeatTemplateParam> paramAliases = new HashMap<>(); - - if (inputs == null) { - LOGGER.debug("convertInputMap - inputs is null - nothing to do here"); - return new HashMap<>(); - } - - LOGGER.debug("convertInputMap in MsoHeatUtils called, with " + inputs.size() + " inputs, and template " + template.getArtifactUuid()); - try { - LOGGER.debug(template.toString()); - Set<HeatTemplateParam> paramSet = template.getParameters(); - LOGGER.debug("paramSet has " + paramSet.size() + " entries"); - } catch (Exception e) { - LOGGER.debug("Exception occurred in convertInputMap:" + e.getMessage(), e); - } - - for (HeatTemplateParam htp : template.getParameters()) { - LOGGER.debug("Adding " + htp.getParamName()); - params.put(htp.getParamName(), htp); - if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) { - LOGGER.debug("\tFound ALIAS " + htp.getParamName() + "->" + htp.getParamAlias()); - paramAliases.put(htp.getParamAlias(), htp); - } - } - LOGGER.debug("Now iterate through the inputs..."); - for (String key : inputs.keySet()) { - LOGGER.debug("key=" + key); - boolean alias = false; - String realName = null; - if (!params.containsKey(key)) { - LOGGER.debug(key + " is not a parameter in the template! - check for an alias"); - // add check here for an alias - if (!paramAliases.containsKey(key)) { - LOGGER.debug("The parameter " + key + " is in the inputs, but it's not a parameter for this template - omit"); - continue; - } else { - alias = true; - realName = paramAliases.get(key).getParamName(); - LOGGER.debug("FOUND AN ALIAS! Will use " + realName + " in lieu of give key/alias " + key); - } - } - String type = params.get(key).getParamType(); - if (type == null || "".equals(type)) { - LOGGER.debug("**PARAM_TYPE is null/empty for " + key + ", will default to string"); - type = "string"; - } - LOGGER.debug("Parameter: " + key + " is of type " + type); - if ("string".equalsIgnoreCase(type)) { - // Easiest! - String str = inputs.get(key); - if (alias) - newInputs.put(realName, str); - else - newInputs.put(key, str); - } else if ("number".equalsIgnoreCase(type)) { - String integerString = inputs.get(key); - Integer anInteger = null; - try { - anInteger = Integer.parseInt(integerString); - } catch (Exception e) { - LOGGER.debug("Unable to convert " + integerString + " to an integer!!", e); - anInteger = null; - } - if (anInteger != null) { - if (alias) - newInputs.put(realName, anInteger); - else - newInputs.put(key, anInteger); - } - else { - if (alias) - newInputs.put(realName, integerString); - else - newInputs.put(key, integerString); - } - } else if ("json".equalsIgnoreCase(type)) { - // MSO-1475 - Leave this as a string now - String jsonString = inputs.get(key); - LOGGER.debug("Skipping conversion to jsonNode..."); - if (alias) - newInputs.put(realName, jsonString); - else - newInputs.put(key, jsonString); - //} - } else if ("comma_delimited_list".equalsIgnoreCase(type)) { - String commaSeparated = inputs.get(key); - try { - ArrayList<String> anArrayList = this.convertCdlToArrayList(commaSeparated); - if (alias) - newInputs.put(realName, anArrayList); - else - newInputs.put(key, anArrayList); - } catch (Exception e) { - LOGGER.debug("Unable to convert " + commaSeparated + " to an ArrayList!!", e); - if (alias) - newInputs.put(realName, commaSeparated); - else - newInputs.put(key, commaSeparated); - } - } else if ("boolean".equalsIgnoreCase(type)) { - String booleanString = inputs.get(key); - Boolean aBool = Boolean.valueOf(booleanString); - if (alias) - newInputs.put(realName, aBool); - else - newInputs.put(key, aBool); - } else { - // it's null or something undefined - just add it back as a String - String str = inputs.get(key); - if (alias) - newInputs.put(realName, str); - else - newInputs.put(key, str); - } - } - return newInputs; - } - - - /* - * Create a string suitable for being dumped to a debug log that creates a - * pseudo-JSON request dumping what's being sent to Openstack API in the create or update request - */ - - private String printStackRequest(String tenantId, - Map<String, Object> heatFiles, - Map<String, Object> nestedTemplates, - String environment, - Map<String, Object> inputs, - String vfModuleName, - String template, - int timeoutMinutes, - boolean backout, - String cloudSiteId) { - StringBuffer sb = new StringBuffer(); - sb.append("CREATE STACK REQUEST (formatted for readability)\n"); - sb.append("tenant=" + tenantId + ", cloud=" + cloudSiteId); - sb.append("{\n"); - sb.append(" \"stack_name\": \"" + vfModuleName + "\",\n"); - sb.append(" \"disable_rollback\": " + backout + ",\n"); - sb.append(" \"timeout_mins\": " + timeoutMinutes + ",\n"); - sb.append(" \"template\": {\n"); - sb.append(template); - sb.append(" },\n"); - sb.append(" \"environment\": {\n"); - if (environment == null) - sb.append("<none>"); - else - sb.append(environment); - sb.append(" },\n"); - sb.append(" \"files\": {\n"); - int filesCounter = 0; - if (heatFiles != null) { - for (String key : heatFiles.keySet()) { - filesCounter++; - if (filesCounter > 1) { - sb.append(",\n"); - } - sb.append(" \"" + key + "\": {\n"); - sb.append(heatFiles.get(key).toString() + "\n }"); - } - } - if (nestedTemplates != null) { - for (String key : nestedTemplates.keySet()) { - filesCounter++; - if (filesCounter > 1) { - sb.append(",\n"); - } - sb.append(" \"" + key + "\": {\n"); - sb.append(nestedTemplates.get(key).toString() + "\n }"); - } - } - sb.append("\n },\n"); - sb.append(" \"parameters\": {\n"); - int paramCounter = 0; - for (String name : inputs.keySet()) { - paramCounter++; - if (paramCounter > 1) { - sb.append(",\n"); - } - Object o = inputs.get(name); - if (o instanceof java.lang.String) { - sb.append(" \"" + name + "\": \"" + inputs.get(name).toString() + "\""); - } else if (o instanceof Integer) { - sb.append(" \"" + name + "\": " + inputs.get(name).toString() ); - } else if (o instanceof ArrayList) { - sb.append(" \"" + name + "\": " + inputs.get(name).toString() ); - } else if (o instanceof Boolean) { - sb.append(" \"" + name + "\": " + inputs.get(name).toString() ); - } else { - sb.append(" \"" + name + "\": " + "\"(there was an issue trying to dump this value...)\"" ); - } - } - sb.append("\n }\n}\n"); - - return sb.toString(); - } - - /******************************************************************************* - * - * Methods (and associated utilities) to implement the VduPlugin interface - * - *******************************************************************************/ - - /** - * VduPlugin interface for instantiate function. - * - * Translate the VduPlugin parameters to the corresponding 'createStack' parameters, - * and then invoke the existing function. - */ - public VduInstance instantiateVdu ( - CloudInfo cloudInfo, - String instanceName, - Map<String,Object> inputs, - VduModelInfo vduModel, - boolean rollbackOnFailure) - throws VduException - { - String cloudSiteId = cloudInfo.getCloudSiteId(); - String tenantId = cloudInfo.getTenantId(); - - // Translate the VDU ModelInformation structure to that which is needed for - // creating the Heat stack. Loop through the artifacts, looking specifically - // for MAIN_TEMPLATE and ENVIRONMENT. Any other artifact will - // be attached as a FILE. - String heatTemplate = null; - Map<String,Object> nestedTemplates = new HashMap<>(); - Map<String,Object> files = new HashMap<>(); - String heatEnvironment = null; - - for (VduArtifact vduArtifact: vduModel.getArtifacts()) { - if (vduArtifact.getType() == ArtifactType.MAIN_TEMPLATE) { - heatTemplate = new String(vduArtifact.getContent()); - } - else if (vduArtifact.getType() == ArtifactType.NESTED_TEMPLATE) { - nestedTemplates.put(vduArtifact.getName(), new String(vduArtifact.getContent())); - } - else if (vduArtifact.getType() == ArtifactType.ENVIRONMENT) { - heatEnvironment = new String(vduArtifact.getContent()); - } - } - - try { - StackInfo stackInfo = createStack (cloudSiteId, - tenantId, - instanceName, - heatTemplate, - inputs, - true, // poll for completion - vduModel.getTimeoutMinutes(), - heatEnvironment, - nestedTemplates, - files, - rollbackOnFailure); - - // Populate a vduInstance from the StackInfo - VduInstance vduInstance = stackInfoToVduInstance(stackInfo); - - return vduInstance; - } - catch (Exception e) { - throw new VduException ("MsoHeatUtils (instantiateVDU): createStack Exception", e); - } - } - - - /** - * VduPlugin interface for query function. - */ - public VduInstance queryVdu (CloudInfo cloudInfo, String instanceId) - throws VduException - { - String cloudSiteId = cloudInfo.getCloudSiteId(); - String tenantId = cloudInfo.getTenantId(); - - try { - // Query the Cloudify Deployment object and populate a VduInstance - StackInfo stackInfo = queryStack (cloudSiteId, tenantId, instanceId); - - VduInstance vduInstance = stackInfoToVduInstance(stackInfo); - - return vduInstance; - } - catch (Exception e) { - throw new VduException ("MsoHeatUtile (queryVdu): queryStack Exception ", e); - } - } - - - /** - * VduPlugin interface for delete function. - */ - public VduInstance deleteVdu (CloudInfo cloudInfo, String instanceId, int timeoutMinutes) - throws VduException - { - String cloudSiteId = cloudInfo.getCloudSiteId(); - String tenantId = cloudInfo.getTenantId(); - - try { - // Delete the Heat stack - StackInfo stackInfo = deleteStack (tenantId, cloudSiteId, instanceId, true); - - // Populate a VduInstance based on the deleted Cloudify Deployment object - VduInstance vduInstance = stackInfoToVduInstance(stackInfo); - - // Override return state to DELETED (HeatUtils sets to NOTFOUND) - vduInstance.getStatus().setState(VduStateType.DELETED); - - return vduInstance; - } - catch (Exception e) { - throw new VduException ("Delete VDU Exception", e); - } - } - - - /** - * VduPlugin interface for update function. - * - * Update is currently not supported in the MsoHeatUtils implementation of VduPlugin. - * Just return a VduException. - * - */ - public VduInstance updateVdu ( - CloudInfo cloudInfo, - String instanceId, - Map<String,Object> inputs, - VduModelInfo vduModel, - boolean rollbackOnFailure) - throws VduException - { - throw new VduException ("MsoHeatUtils: updateVdu interface not supported"); - } - - - /* - * Convert the local DeploymentInfo object (Cloudify-specific) to a generic VduInstance object - */ - private VduInstance stackInfoToVduInstance (StackInfo stackInfo) - { - VduInstance vduInstance = new VduInstance(); - - // The full canonical name as the instance UUID - vduInstance.setVduInstanceId(stackInfo.getCanonicalName()); - vduInstance.setVduInstanceName(stackInfo.getName()); - - // Copy inputs and outputs - vduInstance.setInputs(stackInfo.getParameters()); - vduInstance.setOutputs(stackInfo.getOutputs()); - - // Translate the status elements - vduInstance.setStatus(stackStatusToVduStatus (stackInfo)); - - return vduInstance; - } - - private VduStatus stackStatusToVduStatus (StackInfo stackInfo) - { - VduStatus vduStatus = new VduStatus(); - - // Map the status fields to more generic VduStatus. - // There are lots of HeatStatus values, so this is a bit long... - HeatStatus heatStatus = stackInfo.getStatus(); - String statusMessage = stackInfo.getStatusMessage(); - - if (heatStatus == HeatStatus.INIT || heatStatus == HeatStatus.BUILDING) { - vduStatus.setState(VduStateType.INSTANTIATING); - vduStatus.setLastAction((new PluginAction ("create", "in_progress", statusMessage))); - } - else if (heatStatus == HeatStatus.NOTFOUND) { - vduStatus.setState(VduStateType.NOTFOUND); - } - else if (heatStatus == HeatStatus.CREATED) { - vduStatus.setState(VduStateType.INSTANTIATED); - vduStatus.setLastAction((new PluginAction ("create", "complete", statusMessage))); - } - else if (heatStatus == HeatStatus.UPDATED) { - vduStatus.setState(VduStateType.INSTANTIATED); - vduStatus.setLastAction((new PluginAction ("update", "complete", statusMessage))); - } - else if (heatStatus == HeatStatus.UPDATING) { - vduStatus.setState(VduStateType.UPDATING); - vduStatus.setLastAction((new PluginAction ("update", "in_progress", statusMessage))); - } - else if (heatStatus == HeatStatus.DELETING) { - vduStatus.setState(VduStateType.DELETING); - vduStatus.setLastAction((new PluginAction ("delete", "in_progress", statusMessage))); - } - else if (heatStatus == HeatStatus.FAILED) { - vduStatus.setState(VduStateType.FAILED); - vduStatus.setErrorMessage(stackInfo.getStatusMessage()); - } else { - vduStatus.setState(VduStateType.UNKNOWN); - } - - return vduStatus; - } - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtilsWithUpdate.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtilsWithUpdate.java deleted file mode 100644 index 08ae9df4b5..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoHeatUtilsWithUpdate.java +++ /dev/null @@ -1,437 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudSite; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.openstack.beans.StackInfo; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; -import org.openecomp.mso.openstack.exceptions.MsoException; -import org.openecomp.mso.openstack.exceptions.MsoOpenstackException; -import org.openecomp.mso.openstack.exceptions.MsoStackNotFound; -import org.openecomp.mso.properties.MsoJavaProperties; -import org.openecomp.mso.properties.MsoPropertiesException; -import org.openecomp.mso.properties.MsoPropertiesFactory; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.woorea.openstack.base.client.OpenStackBaseException; -import com.woorea.openstack.base.client.OpenStackRequest; -import com.woorea.openstack.heat.Heat; -import com.woorea.openstack.heat.model.Stack; -import com.woorea.openstack.heat.model.Stack.Output; -import com.woorea.openstack.heat.model.UpdateStackParam; - -public class MsoHeatUtilsWithUpdate extends MsoHeatUtils { - - private static final String UPDATE_STACK = "UpdateStack"; - private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - - protected MsoJavaProperties msoProps = null; - - private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); - - public MsoHeatUtilsWithUpdate (String msoPropID, MsoPropertiesFactory msoPropertiesFactory, CloudConfigFactory cloudConfFactory) { - super (msoPropID,msoPropertiesFactory,cloudConfFactory); - - try { - msoProps = msoPropertiesFactory.getMsoJavaProperties (msoPropID); - } catch (MsoPropertiesException e) { - LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. Mso Properties ID not found in cache: " + msoPropID, "", "", MsoLogger.ErrorCode.AvailabilityError, "Exception Mso Properties ID not found in cache: " + msoPropID, e); - } - } - - /* - * Keep these methods around for backward compatibility - */ - - public StackInfo updateStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, Object> stackInputs, - boolean pollForCompletion, - int timeoutMinutes) throws MsoException { - // Keeping this method to allow compatibility with no environment or files variable sent. In this case, - // simply return the new method with the environment variable set to null. - return this.updateStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - null, - null, - null); - } - - public StackInfo updateStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, Object> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment) throws MsoException { - // Keeping this method to allow compatibility with no environment variable sent. In this case, - // simply return the new method with the files variable set to null. - return this.updateStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - environment, - null, - null); - } - - public StackInfo updateStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, Object> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment, - Map <String, Object> files) throws MsoException { - return this.updateStack (cloudSiteId, - tenantId, - stackName, - heatTemplate, - stackInputs, - pollForCompletion, - timeoutMinutes, - environment, - files, - null); - } - - /** - * Update a Stack in the specified cloud location and tenant. The Heat template - * and parameter map are passed in as arguments, along with the cloud access credentials. - * It is expected that parameters have been validated and contain at minimum the required - * parameters for the given template with no extra (undefined) parameters.. - * - * The Stack name supplied by the caller must be unique in the scope of this tenant. - * However, it should also be globally unique, as it will be the identifier for the - * resource going forward in Inventory. This latter is managed by the higher levels - * invoking this function. - * - * The caller may choose to let this function poll Openstack for completion of the - * stack creation, or may handle polling itself via separate calls to query the status. - * In either case, a StackInfo object will be returned containing the current status. - * When polling is enabled, a status of CREATED is expected. When not polling, a - * status of BUILDING is expected. - * - * An error will be thrown if the requested Stack already exists in the specified - * Tenant and Cloud. - * - * @param tenantId The Openstack ID of the tenant in which to create the Stack - * @param cloudSiteId The cloud identifier (may be a region) in which to create the tenant. - * @param stackName The name of the stack to update - * @param heatTemplate The Heat template - * @param stackInputs A map of key/value inputs - * @param pollForCompletion Indicator that polling should be handled in Java vs. in the client - * @param environment An optional yaml-format string to specify environmental parameters - * @param files a Map<String, Object> for listing child template IDs - * @param heatFiles a Map<String, Object> for listing get_file entries (fileName, fileBody) - * @return A StackInfo object - * @throws MsoException Thrown if the Openstack API call returns an exception. - */ - - public StackInfo updateStack (String cloudSiteId, - String tenantId, - String stackName, - String heatTemplate, - Map <String, Object> stackInputs, - boolean pollForCompletion, - int timeoutMinutes, - String environment, - Map <String, Object> files, - Map <String, Object> heatFiles) throws MsoException { - boolean heatEnvtVariable = true; - if (environment == null || "".equalsIgnoreCase (environment.trim ())) { - heatEnvtVariable = false; - } - boolean haveFiles = true; - if (files == null || files.isEmpty ()) { - haveFiles = false; - } - boolean haveHeatFiles = true; - if (heatFiles == null || heatFiles.isEmpty ()) { - haveHeatFiles = false; - } - - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId) - // This could throw MsoTenantNotFound or MsoOpenstackException (both propagated) - Heat heatClient = getHeatClient (cloudSite, tenantId); - - // Perform a query first to get the current status - Stack heatStack = queryHeatStack (heatClient, stackName); - if (heatStack == null || "DELETE_COMPLETE".equals (heatStack.getStackStatus ())) { - // Not found. Return a StackInfo with status NOTFOUND - throw new MsoStackNotFound (stackName, tenantId, cloudSiteId); - } - - // Use canonical name "<stack name>/<stack-id>" to update the stack. - // Otherwise, update by name returns a 302 redirect. - // NOTE: This is specific to the v1 Orchestration API. - String canonicalName = heatStack.getStackName () + "/" + heatStack.getId (); - - LOGGER.debug ("Ready to Update Stack (" + canonicalName + ") with input params: " + stackInputs); - - // Build up the stack update parameters - // Disable auto-rollback, because error reason is lost. Always rollback in the code. - UpdateStackParam stack = new UpdateStackParam (); - stack.setTimeoutMinutes (timeoutMinutes); - stack.setParameters (stackInputs); - stack.setTemplate (heatTemplate); - stack.setDisableRollback (true); - // TJM add envt to stack - if (heatEnvtVariable) { - stack.setEnvironment (environment); - } - - // Handle nested templates & get_files here. if we have both - must combine - // and then add to stack (both are part of "files:" being added to stack) - if (haveFiles && haveHeatFiles) { - // Let's do this here - not in the bean - LOGGER.debug ("Found files AND heatFiles - combine and add!"); - Map <String, Object> combinedFiles = new HashMap<>(); - for (String keyString : files.keySet ()) { - combinedFiles.put (keyString, files.get (keyString)); - } - for (String keyString : heatFiles.keySet ()) { - combinedFiles.put (keyString, heatFiles.get (keyString)); - } - stack.setFiles (combinedFiles); - } else { - // Handle case where we have one or neither - if (haveFiles) { - stack.setFiles (files); - } - if (haveHeatFiles) { - // setFiles method modified to handle adding a map. - stack.setFiles (heatFiles); - } - } - - try { - // Execute the actual Openstack command to update the Heat stack - OpenStackRequest <Void> request = heatClient.getStacks ().update (canonicalName, stack); - executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackBaseException e) { - // Since this came on the 'Update Stack' command, nothing was changed - // in the cloud. Rethrow the error as an MSO exception. - throw heatExceptionToMsoException (e, UPDATE_STACK); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, UPDATE_STACK); - } - - // If client has requested a final response, poll for stack completion - Stack updateStack = null; - if (pollForCompletion) { - // Set a time limit on overall polling. - // Use the resource (template) timeout for Openstack (expressed in minutes) - // and add one poll interval to give Openstack a chance to fail on its own. - int createPollInterval = msoProps.getIntProperty (createPollIntervalProp, createPollIntervalDefault); - int pollTimeout = (timeoutMinutes * 60) + createPollInterval; - - boolean loopAgain = true; - while (loopAgain) { - try { - updateStack = queryHeatStack (heatClient, canonicalName); - LOGGER.debug (updateStack.getStackStatus () + " (" + canonicalName + ")"); - try { - LOGGER.debug("Current stack " + this.getOutputsAsStringBuilder(heatStack).toString()); - } catch (Exception e) { - LOGGER.debug("an error occurred trying to print out the current outputs of the stack", e); - } - - - if ("UPDATE_IN_PROGRESS".equals (updateStack.getStackStatus ())) { - // Stack update is still running. - // Sleep and try again unless timeout has been reached - if (pollTimeout <= 0) { - // Note that this should not occur, since there is a timeout specified - // in the Openstack call. - LOGGER.error (MessageEnum.RA_UPDATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName, updateStack.getStackStatus(), "", "", MsoLogger.ErrorCode.AvailabilityError, "Update stack timeout"); - loopAgain = false; - } else { - try { - Thread.sleep (createPollInterval * 1000L); - } catch (InterruptedException e) { - // If we are interrupted, we should stop ASAP. - loopAgain = false; - // Set again the interrupted flag - Thread.currentThread().interrupt(); - } - } - pollTimeout -= createPollInterval; - LOGGER.debug("pollTimeout remaining: " + pollTimeout); - } else { - loopAgain = false; - } - } catch (MsoException e) { - // Cannot query the stack. Something is wrong. - - // TODO: No way to roll back the stack at this point. What to do? - e.addContext (UPDATE_STACK); - throw e; - } - } - - if (!"UPDATE_COMPLETE".equals (updateStack.getStackStatus ())) { - LOGGER.error (MessageEnum.RA_UPDATE_STACK_ERR, updateStack.getStackStatus(), updateStack.getStackStatusReason(), "", "", MsoLogger.ErrorCode.DataError, "Update Stack error"); - - // TODO: No way to roll back the stack at this point. What to do? - // Throw a 'special case' of MsoOpenstackException to report the Heat status - MsoOpenstackException me = null; - if ("UPDATE_IN_PROGRESS".equals (updateStack.getStackStatus ())) { - me = new MsoOpenstackException (0, "", "Stack Update Timeout"); - } else { - String error = "Stack error (" + updateStack.getStackStatus () - + "): " - + updateStack.getStackStatusReason (); - me = new MsoOpenstackException (0, "", error); - } - me.addContext (UPDATE_STACK); - throw me; - } - - } else { - // Return the current status. - updateStack = queryHeatStack (heatClient, canonicalName); - if (updateStack != null) { - LOGGER.debug ("UpdateStack, status = " + updateStack.getStackStatus ()); - } else { - LOGGER.debug ("UpdateStack, stack not found"); - } - } - return new StackInfo (updateStack); - } - - private StringBuilder getOutputsAsStringBuilder(Stack heatStack) { - // This should only be used as a utility to print out the stack outputs - // to the log - StringBuilder sb = new StringBuilder(""); - if (heatStack == null) { - sb.append("(heatStack is null)"); - return sb; - } - List<Output> outputList = heatStack.getOutputs(); - if (outputList == null || outputList.isEmpty()) { - sb.append("(outputs is empty)"); - return sb; - } - Map<String, Object> outputs = new HashMap<>(); - for (Output outputItem : outputList) { - outputs.put(outputItem.getOutputKey(), outputItem.getOutputValue()); - } - int counter = 0; - sb.append("OUTPUTS:\n"); - for (String key : outputs.keySet()) { - sb.append("outputs[").append(counter++).append("]: ").append(key).append("="); - Object obj = outputs.get(key); - if (obj instanceof String) { - sb.append((String) obj).append(" (a string)"); - } else if (obj instanceof JsonNode) { - sb.append(this.convertNode((JsonNode) obj)).append(" (a JsonNode)"); - } else if (obj instanceof java.util.LinkedHashMap) { - try { - String str = JSON_MAPPER.writeValueAsString(obj); - sb.append(str).append(" (a java.util.LinkedHashMap)"); - } catch (Exception e) { - LOGGER.debug("Exception :", e); - sb.append("(a LinkedHashMap value that would not convert nicely)"); - } - } else if (obj instanceof Integer) { - String str = ""; - try { - str = obj.toString() + " (an Integer)\n"; - } catch (Exception e) { - LOGGER.debug("Exception :", e); - str = "(an Integer unable to call .toString() on)"; - } - sb.append(str); - } else if (obj instanceof ArrayList) { - String str = ""; - try { - str = obj.toString() + " (an ArrayList)"; - } catch (Exception e) { - LOGGER.debug("Exception :", e); - str = "(an ArrayList unable to call .toString() on?)"; - } - sb.append(str); - } else if (obj instanceof Boolean) { - String str = ""; - try { - str = obj.toString() + " (a Boolean)"; - } catch (Exception e) { - LOGGER.debug("Exception :", e); - str = "(an Boolean unable to call .toString() on?)"; - } - sb.append(str); - } - else { - String str = ""; - try { - str = obj.toString() + " (unknown Object type)"; - } catch (Exception e) { - LOGGER.debug("Exception :", e); - str = "(a value unable to call .toString() on?)"; - } - sb.append(str); - } - sb.append("\n"); - } - sb.append("[END]"); - return sb; - } - - private String convertNode(final JsonNode node) { - try { - final Object obj = JSON_MAPPER.treeToValue(node, Object.class); - final String json = JSON_MAPPER.writeValueAsString(obj); - return json; - } catch (Exception e) { - LOGGER.debug("Error converting json to string " + e.getMessage(), e); - } - return "[Error converting json to string]"; - } - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoKeystoneUtils.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoKeystoneUtils.java deleted file mode 100644 index 1f3c43c79e..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoKeystoneUtils.java +++ /dev/null @@ -1,604 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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.io.Serializable; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -import java.util.Optional; - -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudIdentity; -import org.openecomp.mso.cloud.CloudSite; -import org.openecomp.mso.logger.MsoAlarmLogger; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.openstack.beans.MsoTenant; -import org.openecomp.mso.openstack.exceptions.MsoAdapterException; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; -import org.openecomp.mso.openstack.exceptions.MsoException; -import org.openecomp.mso.openstack.exceptions.MsoOpenstackException; -import org.openecomp.mso.openstack.exceptions.MsoTenantAlreadyExists; -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.keystone.Keystone; -import com.woorea.openstack.keystone.model.Access; -import com.woorea.openstack.keystone.model.Metadata; -import com.woorea.openstack.keystone.model.Role; -import com.woorea.openstack.keystone.model.Roles; -import com.woorea.openstack.keystone.model.Tenant; -import com.woorea.openstack.keystone.model.User; -import com.woorea.openstack.keystone.utils.KeystoneUtils; -import com.woorea.openstack.keystone.model.Authentication; - -public class MsoKeystoneUtils extends MsoTenantUtils { - - // Cache the Keystone Clients statically. Since there is just one MSO user, there is no - // benefit to re-authentication on every request (or across different flows). The - // token will be used until it expires. - // - // The cache key is "cloudId" - private static Map <String, KeystoneCacheEntry> adminClientCache = new HashMap<>(); - - private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - String msoPropID; - - public MsoKeystoneUtils(String msoPropID, CloudConfigFactory cloudConfigFactory) { - super(msoPropID, cloudConfigFactory); - this.msoPropID = msoPropID; - LOGGER.debug("MsoKeyStoneUtils:" + msoPropID); - } - - /** - * Create a tenant with the specified name in the given cloud. If the tenant already exists, - * an Exception will be thrown. The MSO User will also be added to the "member" list of - * the new tenant to perform subsequent Nova/Heat commands in the tenant. If the MSO User - * association fails, the entire transaction will be rolled back. - * <p> - * For the AIC Cloud (DCP/LCP): it is not clear that cloudId is needed, as all admin - * requests go to the centralized identity service in DCP. However, if some artifact - * must exist in each local LCP instance as well, then it will be needed to access the - * correct region. - * <p> - * - * @param tenantName The tenant name to create - * @param cloudSiteId The cloud identifier (may be a region) in which to create the tenant. - * @return the tenant ID of the newly created tenant - * @throws MsoTenantAlreadyExists Thrown if the requested tenant already exists - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - */ - public String createTenant (String tenantName, - String cloudSiteId, - Map <String, String> metadata, - boolean backout) throws MsoException { - // Obtain the cloud site information where we will create the tenant - Optional<CloudSite> cloudSiteOpt = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId); - if (!cloudSiteOpt.isPresent()) { - LOGGER.error(MessageEnum.RA_CREATE_TENANT_ERR, "MSOCloudSite not found", "", "", MsoLogger.ErrorCode.DataError, "MSOCloudSite not found"); - throw new MsoCloudSiteNotFound (cloudSiteId); - } - Keystone keystoneAdminClient = getKeystoneAdminClient(cloudSiteOpt.get()); - Tenant tenant = null; - try { - // Check if the tenant already exists - tenant = findTenantByName (keystoneAdminClient, tenantName); - - if (tenant != null) { - // Tenant already exists. Throw an exception - LOGGER.error(MessageEnum.RA_TENANT_ALREADY_EXIST, tenantName, cloudSiteId, "", "", MsoLogger.ErrorCode.DataError, "Tenant already exists"); - throw new MsoTenantAlreadyExists (tenantName, cloudSiteId); - } - - // Does not exist, create a new one - tenant = new Tenant (); - tenant.setName (tenantName); - tenant.setDescription ("SDN Tenant (via MSO)"); - tenant.setEnabled (true); - - OpenStackRequest <Tenant> request = keystoneAdminClient.tenants ().create (tenant); - tenant = executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackBaseException e) { - // Convert Keystone OpenStackResponseException to MsoOpenstackException - throw keystoneErrorToMsoException (e, "CreateTenant"); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, "CreateTenant"); - } - - // Add MSO User to the tenant as a member and - // apply tenant metadata if supported by the cloud site - try { - CloudIdentity cloudIdentity = cloudSiteOpt.get().getIdentityService (); - - User msoUser = findUserByNameOrId (keystoneAdminClient, cloudIdentity.getMsoId ()); - Role memberRole = findRoleByNameOrId (keystoneAdminClient, cloudIdentity.getMemberRole ()); - - OpenStackRequest <Void> request = keystoneAdminClient.tenants ().addUser (tenant.getId (), - msoUser.getId (), - memberRole.getId ()); - executeAndRecordOpenstackRequest (request, msoProps); - - if (cloudIdentity.hasTenantMetadata () && metadata != null && !metadata.isEmpty ()) { - Metadata tenantMetadata = new Metadata (); - tenantMetadata.setMetadata (metadata); - - OpenStackRequest <Metadata> metaRequest = keystoneAdminClient.tenants () - .createOrUpdateMetadata (tenant.getId (), - tenantMetadata); - executeAndRecordOpenstackRequest (metaRequest, msoProps); - } - } catch (Exception e) { - // Failed to attach MSO User to the new tenant. Can't operate without access, - // so roll back the tenant. - if (!backout) - { - LOGGER.warn(MessageEnum.RA_CREATE_TENANT_ERR, "Create Tenant errored, Tenant deletion suppressed", "Openstack", "", MsoLogger.ErrorCode.DataError, "Create Tenant error, Tenant deletion suppressed"); - } - else - { - try { - OpenStackRequest <Void> request = keystoneAdminClient.tenants ().delete (tenant.getId ()); - executeAndRecordOpenstackRequest (request, msoProps); - } catch (Exception e2) { - // Just log this one. We will report the original exception. - LOGGER.error (MessageEnum.RA_CREATE_TENANT_ERR, "Nested exception rolling back tenant", "Openstack", "", MsoLogger.ErrorCode.DataError, "Create Tenant error, Nested exception rolling back tenant", e2); - } - } - - - // Propagate the original exception on user/role/tenant mapping - if (e instanceof OpenStackBaseException) { - // Convert Keystone Exception to MsoOpenstackException - throw keystoneErrorToMsoException ((OpenStackBaseException) e, "CreateTenantUser"); - } else { - MsoAdapterException me = new MsoAdapterException (e.getMessage (), e); - me.addContext ("CreateTenantUser"); - throw me; - } - } - return tenant.getId (); - } - - /** - * Query for a tenant by ID in the given cloud. If the tenant exists, - * return an MsoTenant object. If not, return null. - * <p> - * For the AIC Cloud (DCP/LCP): it is not clear that cloudId is needed, as all admin - * requests go to the centralized identity service in DCP. However, if some artifact - * must exist in each local LCP instance as well, then it will be needed to access the - * correct region. - * <p> - * - * @param tenantId The Openstack ID of the tenant to query - * @param cloudSiteId The cloud identifier (may be a region) in which to query the tenant. - * @return the tenant properties of the queried tenant, or null if not found - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - */ - public MsoTenant queryTenant (String tenantId, String cloudSiteId) throws MsoException { - // Obtain the cloud site information where we will query the tenant - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - - Keystone keystoneAdminClient = getKeystoneAdminClient (cloudSite); - - // Check if the tenant exists and return its Tenant Id - try { - Tenant tenant = findTenantById (keystoneAdminClient, tenantId); - if (tenant == null) { - return null; - } - - Map <String, String> metadata = new HashMap<>(); - if (cloudSite.getIdentityService ().hasTenantMetadata ()) { - OpenStackRequest <Metadata> request = keystoneAdminClient.tenants ().showMetadata (tenant.getId ()); - Metadata tenantMetadata = executeAndRecordOpenstackRequest (request, msoProps); - if (tenantMetadata != null) { - metadata = tenantMetadata.getMetadata (); - } - } - return new MsoTenant (tenant.getId (), tenant.getName (), metadata); - } catch (OpenStackBaseException e) { - // Convert Keystone OpenStackResponseException to MsoOpenstackException - throw keystoneErrorToMsoException (e, "QueryTenant"); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, "QueryTenant"); - } - } - - /** - * Query for a tenant with the specified name in the given cloud. If the tenant exists, - * return an MsoTenant object. If not, return null. This query is useful if the client - * knows it has the tenant name, skipping an initial lookup by ID that would always fail. - * <p> - * For the AIC Cloud (DCP/LCP): it is not clear that cloudId is needed, as all admin - * requests go to the centralized identity service in DCP. However, if some artifact - * must exist in each local LCP instance as well, then it will be needed to access the - * correct region. - * <p> - * - * @param tenantName The name of the tenant to query - * @param cloudSiteId The cloud identifier (may be a region) in which to query the tenant. - * @return the tenant properties of the queried tenant, or null if not found - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - */ - public MsoTenant queryTenantByName (String tenantName, String cloudSiteId) throws MsoException { - // Obtain the cloud site information where we will query the tenant - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - Keystone keystoneAdminClient = getKeystoneAdminClient (cloudSite); - - try { - Tenant tenant = findTenantByName (keystoneAdminClient, tenantName); - if (tenant == null) { - return null; - } - - Map <String, String> metadata = new HashMap<>(); - if (cloudSite.getIdentityService ().hasTenantMetadata ()) { - OpenStackRequest <Metadata> request = keystoneAdminClient.tenants ().showMetadata (tenant.getId ()); - Metadata tenantMetadata = executeAndRecordOpenstackRequest (request, msoProps); - if (tenantMetadata != null) { - metadata = tenantMetadata.getMetadata (); - } - } - return new MsoTenant (tenant.getId (), tenant.getName (), metadata); - } catch (OpenStackBaseException e) { - // Convert Keystone OpenStackResponseException to MsoOpenstackException - throw keystoneErrorToMsoException (e, "QueryTenantName"); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, "QueryTenantName"); - } - } - - /** - * Delete the specified Tenant (by ID) in the given cloud. This method returns true or - * false, depending on whether the tenant existed and was successfully deleted, or if - * the tenant already did not exist. Both cases are treated as success (no Exceptions). - * <p> - * Note for the AIC Cloud (DCP/LCP): all admin requests go to the centralized identity - * service in DCP. So deleting a tenant from one cloudSiteId will remove it from all - * sites managed by that identity service. - * <p> - * - * @param tenantId The Openstack ID of the tenant to delete - * @param cloudSiteId The cloud identifier from which to delete the tenant. - * @return true if the tenant was deleted, false if the tenant did not exist. - * @throws MsoOpenstackException If the Openstack API call returns an exception. - */ - public boolean deleteTenant (String tenantId, String cloudSiteId) throws MsoException { - // Obtain the cloud site information where we will query the tenant - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - Keystone keystoneAdminClient = getKeystoneAdminClient (cloudSite); - - try { - // Check that the tenant exists. Also, need the ID to delete - Tenant tenant = findTenantById (keystoneAdminClient, tenantId); - if (tenant == null) { - LOGGER.error(MessageEnum.RA_TENANT_NOT_FOUND, tenantId, cloudSiteId, "", "", MsoLogger.ErrorCode.DataError, "Tenant not found"); - return false; - } - - OpenStackRequest <Void> request = keystoneAdminClient.tenants ().delete (tenant.getId ()); - executeAndRecordOpenstackRequest (request, msoProps); - LOGGER.debug ("Deleted Tenant " + tenant.getId () + " (" + tenant.getName () + ")"); - - // Clear any cached clients. Not really needed, ID will not be reused. - MsoHeatUtils.expireHeatClient (tenant.getId (), cloudSiteId); - MsoNeutronUtils.expireNeutronClient (tenant.getId (), cloudSiteId); - } catch (OpenStackBaseException e) { - // Convert Keystone OpenStackResponseException to MsoOpenstackException - throw keystoneErrorToMsoException (e, "Delete Tenant"); - } catch (RuntimeException e) { - // Catch-all - throw runtimeExceptionToMsoException (e, "DeleteTenant"); - } - - return true; - } - - // ------------------------------------------------------------------- - // PRIVATE UTILITY FUNCTIONS FOR USE WITHIN THIS CLASS - - /* - * Get a Keystone Admin client for the Openstack Identity service. - * This requires an 'admin'-level userId + password along with an 'admin' tenant - * in the target cloud. These values will be retrieved from properties based - * on the specified cloud ID. - * <p> - * On successful authentication, the Keystone object will be cached for the cloudId - * so that it can be reused without going back to Openstack every time. - * - * @param cloudId - * - * @return an authenticated Keystone object - */ - public Keystone getKeystoneAdminClient (CloudSite cloudSite) throws MsoException { - CloudIdentity cloudIdentity = cloudSite.getIdentityService (); - - String cloudId = cloudIdentity.getId (); - String adminTenantName = cloudIdentity.getAdminTenant (); - String region = cloudSite.getRegionId (); - - // Check first in the cache of previously authorized clients - KeystoneCacheEntry entry = adminClientCache.get (cloudId); - if (entry != null) { - if (!entry.isExpired ()) { - return entry.getKeystoneClient (); - } else { - // Token is expired. Remove it from cache. - adminClientCache.remove (cloudId); - } - } - - Keystone keystone = new Keystone (cloudIdentity.getKeystoneUrl (region, msoPropID)); - - // Must authenticate against the 'admin' tenant to get the services endpoints - Access access = null; - String token = null; - try { - Authentication credentials = cloudIdentity.getAuthentication (); - OpenStackRequest <Access> request = keystone.tokens () - .authenticate (credentials) - .withTenantName (adminTenantName); - access = executeAndRecordOpenstackRequest (request, msoProps); - token = access.getToken ().getId (); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 401) { - // Authentication error. Can't access admin tenant - something is mis-configured - String error = "MSO Authentication Failed for " + cloudIdentity.getId (); - alarmLogger.sendAlarm ("MsoAuthenticationError", MsoAlarmLogger.CRITICAL, error); - throw new MsoAdapterException (error); - } else { - throw keystoneErrorToMsoException (e, "TokenAuth"); - } - } catch (OpenStackConnectException e) { - // Connection to Openstack failed - throw keystoneErrorToMsoException (e, "TokenAuth"); - } - - // Get the Identity service URL. Throws runtime exception if not found per region. - String adminUrl = null; - try { - // TODO: FOR TESTING!!!! - adminUrl = KeystoneUtils.findEndpointURL (access.getServiceCatalog (), "identity", region, "public"); - adminUrl = adminUrl.replaceFirst("5000", "35357"); - } catch (RuntimeException e) { - String error = "Identity service not found: region=" + region + ",cloud=" + cloudIdentity.getId (); - alarmLogger.sendAlarm ("MsoConfigurationError", MsoAlarmLogger.CRITICAL, error); - LOGGER.error(MessageEnum.IDENTITY_SERVICE_NOT_FOUND, region, cloudIdentity.getId(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in findEndpointURL"); - throw new MsoAdapterException (error, e); - } - - // A new Keystone object is required for the new URL. Use the auth token from above. - // Note: this doesn't go back to Openstack, it's just a local object. - keystone = new Keystone (adminUrl); - keystone.token (token); - - // Cache to avoid re-authentication for every call. - KeystoneCacheEntry cacheEntry = new KeystoneCacheEntry (adminUrl, token, access.getToken ().getExpires ()); - adminClientCache.put (cloudId, cacheEntry); - - return keystone; - } - - /* - * Find a tenant (or query its existance) by its Id. - * - * @param adminClient an authenticated Keystone object - * - * @param tenantName the tenant ID to query - * - * @return a Tenant object or null if not found - */ - private Tenant findTenantById (Keystone adminClient, String tenantId) { - if (tenantId == null) { - return null; - } - - try { - OpenStackRequest <Tenant> request = adminClient.tenants ().show (tenantId); - return executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - return null; - } else { - LOGGER.error(MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack Error, GET Tenant by Id (" + tenantId + "): " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in Openstack GET tenant by Id"); - throw e; - } - } - } - - /* - * Find a tenant (or query its existance) by its Name. This method avoids an - * initial lookup by ID when it's known that we have the tenant Name. - * - * @param adminClient an authenticated Keystone object - * - * @param tenantName the tenant name to query - * - * @return a Tenant object or null if not found - */ - public Tenant findTenantByName (Keystone adminClient, String tenantName) { - if (tenantName == null) { - return null; - } - - try { - OpenStackRequest <Tenant> request = adminClient.tenants ().show ("").queryParam ("name", tenantName); - return executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - return null; - } else { - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack Error, GET Tenant By Name (" + tenantName + "): " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in Openstack GET Tenant By Name"); - throw e; - } - } - } - - /* - * Look up an Openstack User by Name or Openstack ID. Check the ID first, and if that - * fails, try the Name. - * - * @param adminClient an authenticated Keystone object - * - * @param userName the user name or ID to query - * - * @return a User object or null if not found - */ - private User findUserByNameOrId (Keystone adminClient, String userNameOrId) { - if (userNameOrId == null) { - return null; - } - - try { - OpenStackRequest <User> request = adminClient.users ().show (userNameOrId); - return executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - // Not found by ID. Search for name - return findUserByName (adminClient, userNameOrId); - } else { - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack Error, GET User (" + userNameOrId + "): " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in Openstack GET User"); - throw e; - } - } - } - - /* - * Look up an Openstack User by Name. This avoids initial Openstack query by ID - * if we know we have the User Name. - * - * @param adminClient an authenticated Keystone object - * - * @param userName the user name to query - * - * @return a User object or null if not found - */ - public User findUserByName (Keystone adminClient, String userName) { - if (userName == null) { - return null; - } - - try { - OpenStackRequest <User> request = adminClient.users ().show ("").queryParam ("name", userName); - return executeAndRecordOpenstackRequest (request, msoProps); - } catch (OpenStackResponseException e) { - if (e.getStatus () == 404) { - return null; - } else { - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "Openstack Error, GET User By Name (" + userName + "): " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in Openstack GET User By Name"); - throw e; - } - } - } - - /* - * Look up an Openstack Role by Name or Id. There is no direct query for Roles, so - * need to retrieve a full list from Openstack and look for a match. By default, - * Openstack should have a "_member_" role for normal VM-level privileges and an - * "admin" role for expanded privileges (e.g. administer tenants, users, and roles). - * <p> - * - * @param adminClient an authenticated Keystone object - * - * @param roleNameOrId the Role name or ID to look up - * - * @return a Role object - */ - private Role findRoleByNameOrId (Keystone adminClient, String roleNameOrId) { - if (roleNameOrId == null) { - return null; - } - - // Search by name or ID. Must search in list - OpenStackRequest <Roles> request = adminClient.roles ().list (); - Roles roles = executeAndRecordOpenstackRequest (request, msoProps); - - for (Role role : roles) { - if (roleNameOrId.equals (role.getName ()) || roleNameOrId.equals (role.getId ())) { - return role; - } - } - - return null; - } - - private static class KeystoneCacheEntry implements Serializable { - - private static final long serialVersionUID = 1L; - - private String keystoneUrl; - private String token; - private Calendar expires; - - public KeystoneCacheEntry (String url, String token, Calendar expires) { - this.keystoneUrl = url; - this.token = token; - this.expires = expires; - } - - public Keystone getKeystoneClient () { - Keystone keystone = new Keystone (keystoneUrl); - keystone.token (token); - return keystone; - } - - public boolean isExpired () { - // adding arbitrary guard timer of 5 minutes - return expires == null || System.currentTimeMillis() > (expires.getTimeInMillis() - 300000); - - } - } - - /** - * Clean up the Admin client cache to remove expired entries. - */ - public static void adminCacheCleanup () { - for (String cacheKey : adminClientCache.keySet ()) { - if (adminClientCache.get (cacheKey).isExpired ()) { - adminClientCache.remove (cacheKey); - LOGGER.debug ("Cleaned Up Cached Admin Client for " + cacheKey); - } - } - } - - /** - * Reset the Admin client cache. - * This may be useful if cached credentials get out of sync. - */ - public static void adminCacheReset () { - adminClientCache = new HashMap<>(); - } - - @Override - public String getKeystoneUrl(String regionId, String msoPropID, CloudIdentity cloudIdentity) { - return cloudIdentity.getIdentityUrl(); - } -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoNeutronUtils.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoNeutronUtils.java deleted file mode 100644 index df769ec0c2..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoNeutronUtils.java +++ /dev/null @@ -1,588 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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.io.Serializable; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.openecomp.mso.cloud.CloudConfig; -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudIdentity; -import org.openecomp.mso.cloud.CloudSite; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.logger.MsoAlarmLogger; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.openstack.beans.NetworkInfo; -import org.openecomp.mso.openstack.exceptions.MsoAdapterException; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; -import org.openecomp.mso.openstack.exceptions.MsoException; -import org.openecomp.mso.openstack.exceptions.MsoIOException; -import org.openecomp.mso.openstack.exceptions.MsoNetworkAlreadyExists; -import org.openecomp.mso.openstack.exceptions.MsoNetworkNotFound; -import org.openecomp.mso.openstack.exceptions.MsoOpenstackException; -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.keystone.Keystone; -import com.woorea.openstack.keystone.model.Access; -import com.woorea.openstack.keystone.utils.KeystoneUtils; -import com.woorea.openstack.quantum.Quantum; -import com.woorea.openstack.quantum.model.Network; -import com.woorea.openstack.quantum.model.Networks; -import com.woorea.openstack.quantum.model.Segment; -import com.woorea.openstack.keystone.model.Authentication; - -public class MsoNeutronUtils extends MsoCommonUtils -{ - // Cache Neutron Clients statically. Since there is just one MSO user, there is no - // benefit to re-authentication on every request (or across different flows). The - // token will be used until it expires. - // - // The cache key is "tenantId:cloudId" - private static Map<String,NeutronCacheEntry> neutronClientCache = new HashMap<>(); - - private CloudConfigFactory cloudConfigFactory; - - private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - private String msoPropID; - - public enum NetworkType { - BASIC, PROVIDER, MULTI_PROVIDER - }; - - public MsoNeutronUtils(String msoPropID, CloudConfigFactory cloudConfigFactory) { - this.cloudConfigFactory = cloudConfigFactory; - this.msoPropID = msoPropID; - } - - protected CloudConfigFactory getCloudConfigFactory() { - return cloudConfigFactory; - } - - /** - * Create a network with the specified parameters in the given cloud/tenant. - * - * If a network already exists with the same name, an exception will be thrown. Note that - * this is an MSO-imposed restriction. Openstack does not require uniqueness on network names. - * <p> - * @param cloudSiteId The cloud identifier (may be a region) in which to create the network. - * @param tenantId The tenant in which to create the network - * @param type The type of network to create (Basic, Provider, Multi-Provider) - * @param networkName The network name to create - * @param provider The provider network name (for Provider or Multi-Provider networks) - * @param vlans A list of VLAN segments for the network (for Provider or Multi-Provider networks) - * @return a NetworkInfo object which describes the newly created network - * @throws MsoNetworkAlreadyExists Thrown if a network with the same name already exists - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - * @throws MsoCloudSiteNotFound Thrown if the cloudSite is invalid or unknown - */ - public NetworkInfo createNetwork (String cloudSiteId, String tenantId, NetworkType type, String networkName, String provider, List<Integer> vlans) - throws MsoException - { - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - - Quantum neutronClient = getNeutronClient (cloudSite, tenantId); - - // Check if a network already exists with this name - // Openstack will allow duplicate name, so require explicit check - Network network = findNetworkByName (neutronClient, networkName); - - if (network != null) { - // Network already exists. Throw an exception - LOGGER.error(MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network already exists"); - throw new MsoNetworkAlreadyExists (networkName, tenantId, cloudSiteId); - } - - // Does not exist, create a new one - network = new Network(); - network.setName(networkName); - network.setAdminStateUp(true); - - if (type == NetworkType.PROVIDER) { - if (provider != null && vlans != null && vlans.size() > 0) { - network.setProviderPhysicalNetwork (provider); - network.setProviderNetworkType("vlan"); - network.setProviderSegmentationId (vlans.get(0)); - } - } else if (type == NetworkType.MULTI_PROVIDER) { - if (provider != null && vlans != null && vlans.size() > 0) { - List<Segment> segments = new ArrayList<>(vlans.size()); - for (int vlan : vlans) { - Segment segment = new Segment(); - segment.setProviderPhysicalNetwork (provider); - segment.setProviderNetworkType("vlan"); - segment.setProviderSegmentationId (vlan); - - segments.add(segment); - } - network.setSegments(segments); - } - } - - try { - OpenStackRequest<Network> request = neutronClient.networks().create(network); - Network newNetwork = executeAndRecordOpenstackRequest(request); - return new NetworkInfo(newNetwork); - } - catch (OpenStackBaseException e) { - // Convert Neutron exception to an MsoOpenstackException - MsoException me = neutronExceptionToMsoException (e, "CreateNetwork"); - throw me; - } - catch (RuntimeException e) { - // Catch-all - MsoException me = runtimeExceptionToMsoException(e, "CreateNetwork"); - throw me; - } - } - - - /** - * Query for a network with the specified name or ID in the given cloud. If the network exists, - * return an NetworkInfo object. If not, return null. - * <p> - * Whenever possible, the network ID should be used as it is much more efficient. Query by - * name requires retrieval of all networks for the tenant and search for matching name. - * <p> - * @param networkNameOrId The network to query - * @param tenantId The Openstack tenant to look in for the network - * @param cloudSiteId The cloud identifier (may be a region) in which to query the network. - * @return a NetworkInfo object describing the queried network, or null if not found - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - * @throws MsoCloudSiteNotFound - */ - public NetworkInfo queryNetwork(String networkNameOrId, String tenantId, String cloudSiteId) throws MsoException - { - LOGGER.debug("In queryNetwork"); - - // Obtain the cloud site information - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - - Quantum neutronClient = getNeutronClient (cloudSite, tenantId); - // Check if the network exists and return its info - try { - Network network = findNetworkByNameOrId (neutronClient, networkNameOrId); - if (network == null) { - LOGGER.debug ("Query Network: " + networkNameOrId + " not found in tenant " + tenantId); - return null; - } - return new NetworkInfo(network); - } - catch (OpenStackBaseException e) { - // Convert Neutron exception to an MsoOpenstackException - MsoException me = neutronExceptionToMsoException (e, "QueryNetwork"); - throw me; - } - catch (RuntimeException e) { - // Catch-all - MsoException me = runtimeExceptionToMsoException(e, "QueryNetwork"); - throw me; - } - } - - /** - * Delete the specified Network (by ID) in the given cloud. - * If the network does not exist, success is returned. - * <p> - * @param networkId Openstack ID of the network to delete - * @param tenantId The Openstack tenant. - * @param cloudSiteId The cloud identifier (may be a region) from which to delete the network. - * @return true if the network was deleted, false if the network did not exist - * @throws MsoOpenstackException If the Openstack API call returns an exception, this local - * exception will be thrown. - * @throws MsoCloudSiteNotFound - */ - public boolean deleteNetwork(String networkId, String tenantId, String cloudSiteId) throws MsoException - { - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - Quantum neutronClient = getNeutronClient (cloudSite, tenantId); - try { - // Check that the network exists. - Network network = findNetworkById (neutronClient, networkId); - if (network == null) { - LOGGER.info(MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", ""); - return false; - } - - OpenStackRequest<Void> request = neutronClient.networks().delete(network.getId()); - executeAndRecordOpenstackRequest(request); - - LOGGER.debug ("Deleted Network " + network.getId() + " (" + network.getName() + ")"); - } - catch (OpenStackBaseException e) { - // Convert Neutron exception to an MsoOpenstackException - MsoException me = neutronExceptionToMsoException (e, "Delete Network"); - throw me; - } - catch (RuntimeException e) { - // Catch-all - MsoException me = runtimeExceptionToMsoException(e, "DeleteNetwork"); - throw me; - } - - return true; - } - - - /** - * Update a network with the specified parameters in the given cloud/tenant. - * - * Specifically, this call is intended to update the VLAN segments on a - * multi-provider network. The provider segments will be replaced with the - * supplied list of VLANs. - * <p> - * Note that updating the 'segments' array is not normally supported by Neutron. - * This method relies on a Platform Orchestration extension (using SDN controller - * to manage the virtual networking). - * - * @param cloudSiteId The cloud site ID (may be a region) in which to update the network. - * @param tenantId Openstack ID of the tenant in which to update the network - * @param networkId The unique Openstack ID of the network to be updated - * @param type The network type (Basic, Provider, Multi-Provider) - * @param provider The provider network name. This should not change. - * @param vlans The list of VLAN segments to replace - * @return a NetworkInfo object which describes the updated network - * @throws MsoNetworkNotFound Thrown if the requested network does not exist - * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception - * @throws MsoCloudSiteNotFound - */ - public NetworkInfo updateNetwork (String cloudSiteId, String tenantId, String networkId, NetworkType type, String provider, List<Integer> vlans) - throws MsoException - { - // Obtain the cloud site information where we will create the stack - CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - Quantum neutronClient = getNeutronClient (cloudSite, tenantId); - // Check that the network exists - Network network = findNetworkById (neutronClient, networkId); - - if (network == null) { - // Network not found. Throw an exception - LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network not found"); - throw new MsoNetworkNotFound (networkId, tenantId, cloudSiteId); - } - - // Overwrite the properties to be updated - if (type == NetworkType.PROVIDER) { - if (provider != null && vlans != null && vlans.size() > 0) { - network.setProviderPhysicalNetwork (provider); - network.setProviderNetworkType("vlan"); - network.setProviderSegmentationId (vlans.get(0)); - } - } else if (type == NetworkType.MULTI_PROVIDER) { - if (provider != null && vlans != null && vlans.size() > 0) { - List<Segment> segments = new ArrayList<>(vlans.size()); - for (int vlan : vlans) { - Segment segment = new Segment(); - segment.setProviderPhysicalNetwork (provider); - segment.setProviderNetworkType("vlan"); - segment.setProviderSegmentationId (vlan); - - segments.add(segment); - } - network.setSegments(segments); - } - } - - try { - OpenStackRequest<Network> request = neutronClient.networks().update(network); - Network newNetwork = executeAndRecordOpenstackRequest(request); - return new NetworkInfo(newNetwork); - } - catch (OpenStackBaseException e) { - // Convert Neutron exception to an MsoOpenstackException - MsoException me = neutronExceptionToMsoException (e, "UpdateNetwork"); - throw me; - } - catch (RuntimeException e) { - // Catch-all - MsoException me = runtimeExceptionToMsoException(e, "UpdateNetwork"); - throw me; - } - } - - - // ------------------------------------------------------------------- - // PRIVATE UTILITY FUNCTIONS FOR USE WITHIN THIS CLASS - - /** - * Get a Neutron (Quantum) client for the Openstack Network service. - * This requires a 'member'-level userId + password, which will be retrieved from - * properties based on the specified cloud Id. The tenant in which to operate - * must also be provided. - * <p> - * On successful authentication, the Quantum object will be cached for the - * tenantID + cloudId so that it can be reused without reauthenticating with - * Openstack every time. - * - * @param cloudSite - a cloud site definition - * @param tenantId - Openstack tenant ID - * @return an authenticated Quantum object - */ - private Quantum getNeutronClient(CloudSite cloudSite, String tenantId) throws MsoException - { - String cloudId = cloudSite.getId(); - - // Check first in the cache of previously authorized clients - String cacheKey = cloudId + ":" + tenantId; - if (neutronClientCache.containsKey(cacheKey)) { - if (! neutronClientCache.get(cacheKey).isExpired()) { - LOGGER.debug ("Using Cached HEAT Client for " + cacheKey); - Quantum neutronClient = neutronClientCache.get(cacheKey).getNeutronClient(); - return neutronClient; - } - else { - // Token is expired. Remove it from cache. - neutronClientCache.remove(cacheKey); - LOGGER.debug ("Expired Cached Neutron Client for " + cacheKey); - } - } - - // Obtain an MSO token for the tenant from the identity service - CloudIdentity cloudIdentity = cloudSite.getIdentityService(); - Keystone keystoneTenantClient = new Keystone (cloudIdentity.getKeystoneUrl(cloudId, msoPropID)); - Access access = null; - try { - Authentication credentials = cloudIdentity.getAuthentication (); - OpenStackRequest<Access> request = keystoneTenantClient.tokens().authenticate(credentials).withTenantId(tenantId); - access = executeAndRecordOpenstackRequest(request); - } - catch (OpenStackResponseException e) { - if (e.getStatus() == 401) { - // Authentication error. - String error = "Authentication Failure: tenant=" + tenantId + ",cloud=" + cloudIdentity.getId(); - alarmLogger .sendAlarm("MsoAuthenticationError", MsoAlarmLogger.CRITICAL, error); - throw new MsoAdapterException(error); - } - else { - MsoException me = keystoneErrorToMsoException(e, "TokenAuth"); - throw me; - } - } - catch (OpenStackConnectException e) { - // Connection to Openstack failed - MsoIOException me = new MsoIOException (e.getMessage(), e); - me.addContext("TokenAuth"); - throw me; - } - catch (RuntimeException e) { - // Catch-all - MsoException me = runtimeExceptionToMsoException(e, "TokenAuth"); - throw me; - } - - String region = cloudSite.getRegionId(); - String neutronUrl = null; - try { - neutronUrl = KeystoneUtils.findEndpointURL(access.getServiceCatalog(), "network", region, "public"); - if (! neutronUrl.endsWith("/")) { - neutronUrl += "/v2.0/"; - } - } catch (RuntimeException e) { - // This comes back for not found (probably an incorrect region ID) - String error = "Network service not found: region=" + region + ",cloud=" + cloudIdentity.getId(); - alarmLogger.sendAlarm("MsoConfigurationError", MsoAlarmLogger.CRITICAL, error); - throw new MsoAdapterException (error, e); - } - - Quantum neutronClient = new Quantum(neutronUrl); - neutronClient.token(access.getToken().getId()); - - neutronClientCache.put(cacheKey, new NeutronCacheEntry(neutronUrl, access.getToken().getId(), access.getToken().getExpires())); - LOGGER.debug ("Caching Neutron Client for " + cacheKey); - - return neutronClient; - } - - /** - * Forcibly expire a Neutron client from the cache. This call is for use by - * the KeystoneClient in case where a tenant is deleted. In that case, - * all cached credentials must be purged so that fresh authentication is - * done on subsequent calls. - */ - public static void expireNeutronClient (String tenantId, String cloudId) { - String cacheKey = cloudId + ":" + tenantId; - if (neutronClientCache.containsKey(cacheKey)) { - neutronClientCache.remove(cacheKey); - LOGGER.debug ("Deleted Cached Neutron Client for " + cacheKey); - } - } - - - /* - * Find a tenant (or query its existence) by its Name or Id. Check first against the - * ID. If that fails, then try by name. - * - * @param adminClient an authenticated Keystone object - * @param tenantName the tenant name or ID to query - * @return a Tenant object or null if not found - */ - public Network findNetworkByNameOrId (Quantum neutronClient, String networkNameOrId) - { - if (networkNameOrId == null) { - return null; - } - - Network network = findNetworkById(neutronClient, networkNameOrId); - - if (network == null) { - network = findNetworkByName(neutronClient, networkNameOrId); - } - - return network; - } - - /* - * Find a network (or query its existence) by its Id. - * - * @param neutronClient an authenticated Quantum object - * @param networkId the network ID to query - * @return a Network object or null if not found - */ - private static Network findNetworkById (Quantum neutronClient, String networkId) - { - if (networkId == null) { - return null; - } - - try { - OpenStackRequest<Network> request = neutronClient.networks().show(networkId); - Network network = executeAndRecordOpenstackRequest(request); - return network; - } - catch (OpenStackResponseException e) { - if (e.getStatus() == 404) { - return null; - } else { - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Error, GET Network By ID (" + networkId + "): " + e, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception in Openstack"); - throw e; - } - } - } - - /* - * Find a network (or query its existence) by its Name. This method avoids an - * initial lookup by ID when it's known that we have the network Name. - * - * Neutron does not support 'name=*' query parameter for Network query (show). - * The only way to query by name is to retrieve all networks and look for the - * match. While inefficient, this capability will be provided as it is needed - * by MSO, but should be avoided in favor of ID whenever possible. - * - * TODO: - * Network names are not required to be unique, though MSO will attempt to enforce - * uniqueness. This call probably needs to return an error (instead of returning - * the first match). - * - * @param neutronClient an authenticated Quantum object - * @param networkName the network name to query - * @return a Network object or null if not found - */ - public Network findNetworkByName (Quantum neutronClient, String networkName) - { - if (networkName == null) { - return null; - } - - try { - OpenStackRequest<Networks> request = neutronClient.networks().list(); - Networks networks = executeAndRecordOpenstackRequest(request); - for (Network network : networks.getList()) { - if (network.getName().equals(networkName)) { - LOGGER.debug ("Found match on network name: " + networkName); - return network; - } - } - LOGGER.debug ("findNetworkByName - no match found for " + networkName); - return null; - } - catch (OpenStackResponseException e) { - if (e.getStatus() == 404) { - return null; - } else { - LOGGER.error (MessageEnum.RA_CONNECTION_EXCEPTION, "OpenStack", "Openstack Error, GET Network By Name (" + networkName + "): " + e, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception in OpenStack"); - throw e; - } - } - } - - - /* - * An entry in the Neutron Client Cache. It saves the Neutron client object - * along with the token expiration. After this interval, this cache - * item will no longer be used. - */ - private static class NeutronCacheEntry implements Serializable - { - private static final long serialVersionUID = 1L; - - private String neutronUrl; - private String token; - private Calendar expires; - - public NeutronCacheEntry (String neutronUrl, String token, Calendar expires) { - this.neutronUrl = neutronUrl; - this.token = token; - this.expires = expires; - } - - public Quantum getNeutronClient () { - Quantum neutronClient = new Quantum(neutronUrl); - neutronClient.token(token); - return neutronClient; - } - - public boolean isExpired() { - return expires == null || System.currentTimeMillis() > expires.getTimeInMillis(); - } - } - - /** - * Clean up the Neutron client cache to remove expired entries. - */ - public static void neutronCacheCleanup () { - for (String cacheKey : neutronClientCache.keySet()) { - if (neutronClientCache.get(cacheKey).isExpired()) { - neutronClientCache.remove(cacheKey); - LOGGER.debug ("Cleaned Up Cached Neutron Client for " + cacheKey); - } - } - } - - /** - * Reset the Neutron client cache. - * This may be useful if cached credentials get out of sync. - */ - public static void neutronCacheReset () { - neutronClientCache = new HashMap<>(); - } -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtils.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtils.java deleted file mode 100644 index 964babd1e0..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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.util.Map; -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudIdentity; -import org.openecomp.mso.logger.MessageEnum; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.openstack.beans.MsoTenant; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; -import org.openecomp.mso.openstack.exceptions.MsoException; -import org.openecomp.mso.properties.MsoJavaProperties; -import org.openecomp.mso.properties.MsoPropertiesException; -import org.openecomp.mso.properties.MsoPropertiesFactory; - -public abstract class MsoTenantUtils extends MsoCommonUtils { - - private CloudConfigFactory cloudConfigFactory; - protected MsoPropertiesFactory msoPropFactory; - protected static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - protected MsoJavaProperties msoProps; - - public MsoTenantUtils (String msoPropID, CloudConfigFactory cloudConfigFactory) { - this.cloudConfigFactory = cloudConfigFactory; - msoPropFactory = new MsoPropertiesFactory(); - - LOGGER.debug("msoTenantUtils:" + msoPropID); - - try { - msoProps = msoPropFactory.getMsoJavaProperties (msoPropID); - } catch (MsoPropertiesException e) { - LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. Mso Properties ID not found in cache: " + msoPropID, "", "", MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e); - } - } - - public CloudConfigFactory getCloudConfigFactory() { - return cloudConfigFactory; - } - - public abstract String createTenant (String tenantName, String cloudSiteId, Map <String, String> metadata, boolean backout) - throws MsoException; - - public abstract MsoTenant queryTenant (String tenantId, String cloudSiteId) - throws MsoException, MsoCloudSiteNotFound; - - public abstract MsoTenant queryTenantByName (String tenantName, String cloudSiteId) - throws MsoException, MsoCloudSiteNotFound; - - public abstract boolean deleteTenant (String tenantId, String cloudSiteId) - throws MsoException; - - public abstract String getKeystoneUrl (String regionId, String msoPropID, CloudIdentity cloudIdentity) - throws MsoException; - -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtilsFactory.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtilsFactory.java deleted file mode 100644 index 49c262268d..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoTenantUtilsFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * 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.reflect.InvocationTargetException; - -import org.openecomp.mso.cloud.CloudConfig; -import org.openecomp.mso.cloud.CloudConfigFactory; -import org.openecomp.mso.cloud.CloudIdentity; -import org.openecomp.mso.cloud.CloudSite; -import org.openecomp.mso.logger.MsoLogger; -import org.openecomp.mso.openstack.exceptions.MsoCloudSiteNotFound; - - -public class MsoTenantUtilsFactory { - - private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - private CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - private String msoPropID; - - public MsoTenantUtilsFactory (String msoPropID) { - this.msoPropID = msoPropID; - } - - public void setCloudConfigFactory(CloudConfigFactory cloudConfigFactory) { - this.cloudConfigFactory = cloudConfigFactory; - } - - public CloudConfigFactory getCloudConfigFactory() { - return cloudConfigFactory; - } - - //based on Cloud IdentityServerType returns ORM or KEYSTONE Utils - public MsoTenantUtils getTenantUtils(String cloudSiteId) throws MsoCloudSiteNotFound { - // Obtain the cloud site information - CloudConfig cloudConfig = getCloudConfigFactory().getCloudConfig(); - CloudSite cloudSite = cloudConfig.getCloudSite(cloudSiteId).orElseThrow( - () -> new MsoCloudSiteNotFound(cloudSiteId)); - return getTenantUtilsByServerType(cloudSite.getIdentityService().getIdentityServerType().toString()); - } - - public MsoTenantUtils getTenantUtilsByServerType(String serverType) { - - MsoTenantUtils tenantU = null; - if (CloudIdentity.IdentityServerType.KEYSTONE.toString().equals(serverType)) { - tenantU = new MsoKeystoneUtils(msoPropID, getCloudConfigFactory()); - } else { - try { - tenantU = CloudIdentity.IdentityServerType.valueOf(serverType).getMsoTenantUtilsClass() - .getConstructor(String.class, CloudConfigFactory.class).newInstance(msoPropID, getCloudConfigFactory()); - } catch (InvocationTargetException | InstantiationException | NoSuchMethodException | IllegalAccessException e) { - throw new RuntimeException("Could not instantiate an MsoTenantUtils class for " + serverType, e); - } - } - return tenantU; - } -} diff --git a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoYamlEditorWithEnvt.java b/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoYamlEditorWithEnvt.java deleted file mode 100644 index 8704911e26..0000000000 --- a/adapters/mso-adapter-utils/src/main/java/org/openecomp/mso/openstack/utils/MsoYamlEditorWithEnvt.java +++ /dev/null @@ -1,163 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; -import org.openecomp.mso.db.catalog.beans.HeatTemplateParam; -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.yaml.snakeyaml.Yaml; - -import org.openecomp.mso.logger.MsoLogger; - -public class MsoYamlEditorWithEnvt { - - private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA); - - private Map <String, Object> yml; - private Yaml yaml = new Yaml (); - private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); - - public MsoYamlEditorWithEnvt() { - super(); - } - public MsoYamlEditorWithEnvt(byte[] b) { - init(b); - } - - @SuppressWarnings("unchecked") - private synchronized void init (byte[] body) { - InputStream input = new ByteArrayInputStream (body); - yml = (Map <String, Object>) yaml.load (input); - } - - @SuppressWarnings("unchecked") - public synchronized Set <MsoHeatEnvironmentParameter> getParameterListFromEnvt() { - // In an environment entry, the parameters section can only contain the name:value - - // not other attributes. - Set <MsoHeatEnvironmentParameter> paramSet = new HashSet<>(); - Map<String, Object> resourceMap = null; - try { - resourceMap = (Map<String,Object>) yml.get("parameters"); - } catch (Exception e) { - LOGGER.debug("Exception:", e); - return paramSet; - } - if (resourceMap == null) { - return paramSet; - } - - for (Entry<String, Object> stringObjectEntry : resourceMap.entrySet()) { - MsoHeatEnvironmentParameter hep = new MsoHeatEnvironmentParameter(); - Entry<String, Object> pair = stringObjectEntry; - String value; - Object obj = pair.getValue(); - if (obj instanceof String) { - value = yaml.dump(obj); - // but this adds an extra '\n' at the end - which won't hurt - but we don't need it - value = value.substring(0, value.length() - 1); - } else if (obj instanceof LinkedHashMap) { - //Handle that it's json - try { - value = JSON_MAPPER.writeValueAsString(obj); - } catch (Exception e) { - LOGGER.debug("Exception:", e); - value = "_BAD_JSON_MAPPING"; - } - } else { - //this handles integers/longs/floats/etc. - value = String.valueOf(obj); - } - hep.setName((String) pair.getKey()); - hep.setValue(value); - paramSet.add(hep); - } - return paramSet; - } - public synchronized Set <MsoHeatEnvironmentResource> getResourceListFromEnvt() { - try { - Set<MsoHeatEnvironmentResource> resourceList = new HashSet<>(); - @SuppressWarnings("unchecked") - Map<String, Object> resourceMap = (Map<String,Object>) yml.get("resource_registry"); - - for (Entry<String, Object> stringObjectEntry : resourceMap.entrySet()) { - MsoHeatEnvironmentResource her = new MsoHeatEnvironmentResource(); - Entry<String, Object> pair = stringObjectEntry; - her.setName((String) pair.getKey()); - her.setValue((String) pair.getValue()); - resourceList.add(her); - } - return resourceList; - } catch (Exception e) { - LOGGER.debug("Exception:", e); - } - return null; - } - public synchronized Set <HeatTemplateParam> getParameterList () { - Set <HeatTemplateParam> paramSet = new HashSet <> (); - @SuppressWarnings("unchecked") - Map <String, Object> resourceMap = (Map <String, Object>) yml.get ("parameters"); - - for (Entry<String, Object> stringObjectEntry : resourceMap.entrySet()) { - HeatTemplateParam param = new HeatTemplateParam(); - Entry<String, Object> pair = stringObjectEntry; - @SuppressWarnings("unchecked") - Map<String, String> resourceEntry = (Map<String, String>) pair.getValue(); - String value = null; - try { - value = resourceEntry.get("default"); - } catch (ClassCastException cce) { - LOGGER.debug("Exception:", cce); - // This exception only - the value is an integer. For what we're doing - // here - we don't care - so set value to something - and it will - // get marked as not being required - which is correct. - //System.out.println("cce exception!"); - value = "300"; - // okay - } - param.setParamName((String) pair.getKey()); - if (value != null) { - param.setRequired(false); - } else { - param.setRequired(true); - } - value = resourceEntry.get("type"); - param.setParamType(value); - - paramSet.add(param); - - } - return paramSet; - - } - - -} |