aboutsummaryrefslogtreecommitdiffstats
path: root/adapters/mso-vnf-adapter/src/main/java/org
diff options
context:
space:
mode:
authorChrisC <cc697w@intl.att.com>2017-01-31 11:40:03 +0100
committerChrisC <cc697w@intl.att.com>2017-01-31 12:59:33 +0100
commit025301d08b061482c1f046d562bf017c8cbcfe8d (patch)
tree68a2a549736c9bf0f7cd4e71c76e40ef7e2606f2 /adapters/mso-vnf-adapter/src/main/java/org
parent2754ad52f833278a5c925bd788a16d1dce16a598 (diff)
Initial OpenECOMP MSO commit
Change-Id: Ia6a7574859480717402cc2f22534d9973a78fa6d Signed-off-by: ChrisC <cc697w@intl.att.com>
Diffstat (limited to 'adapters/mso-vnf-adapter/src/main/java/org')
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/BpelRestClient.java304
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/HealthCheckHandler.java66
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapter.java142
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsync.java103
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsyncImpl.java652
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterImpl.java2391
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VfRollback.java137
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VnfAdapterRest.java628
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VolumeAdapterRest.java576
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfAlreadyExists.java42
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfException.java80
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfExceptionBean.java73
-rw-r--r--adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfNotFound.java43
13 files changed, 5237 insertions, 0 deletions
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/BpelRestClient.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/BpelRestClient.java
new file mode 100644
index 0000000000..e76aa40304
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/BpelRestClient.java
@@ -0,0 +1,304 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.properties.MsoJavaProperties;
+import org.openecomp.mso.properties.MsoPropertiesException;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+/**
+ * This is the class that is used to POST replies from the MSO adapters to the BPEL engine.
+ * It can be configured via property file, or modified using the member methods.
+ * The properties to use are:
+ * org.openecomp.mso.adapters.vnf.bpelauth encrypted authorization string to send to BEPL engine
+ * org.openecomp.mso.adapters.vnf.sockettimeout socket timeout value
+ * org.openecomp.mso.adapters.vnf.connecttimeout connect timeout value
+ * org.openecomp.mso.adapters.vnf.retrycount number of times to retry failed connections
+ * org.openecomp.mso.adapters.vnf.retryinterval interval (in seconds) between retries
+ * org.openecomp.mso.adapters.vnf.retrylist list of response codes that will trigger a retry (the special code
+ * 900 means "connection was not established")
+ */
+public class BpelRestClient {
+ public static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
+ private static final String PROPERTY_DOMAIN = "org.openecomp.mso.adapters.vnf";
+ private static final String BPEL_AUTH_PROPERTY = PROPERTY_DOMAIN+".bpelauth";
+ private static final String SOCKET_TIMEOUT_PROPERTY = PROPERTY_DOMAIN+".sockettimeout";
+ private static final String CONN_TIMEOUT_PROPERTY = PROPERTY_DOMAIN+".connecttimeout";
+ private static final String RETRY_COUNT_PROPERTY = PROPERTY_DOMAIN+".retrycount";
+ private static final String RETRY_INTERVAL_PROPERTY = PROPERTY_DOMAIN+".retryinterval";
+ private static final String RETRY_LIST_PROPERTY = PROPERTY_DOMAIN+".retrylist";
+ private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+
+ /** Default socket timeout (in seconds) */
+ public static final int DEFAULT_SOCKET_TIMEOUT = 5;
+ /** Default connect timeout (in seconds) */
+ public static final int DEFAULT_CONNECT_TIMEOUT = 5;
+ /** By default, retry up to five times */
+ public static final int DEFAULT_RETRY_COUNT = 5;
+ /** Default interval to wait between retries (in seconds), negative means use backoff algorithm */
+ public static final int DEFAULT_RETRY_INTERVAL = -15;
+ /** Default list of response codes to trigger a retry */
+ public static final String DEFAULT_RETRY_LIST = "408,429,500,502,503,504,900"; // 900 is "connection failed"
+ /** Default credentials */
+ public static final String DEFAULT_CREDENTIALS = "";
+
+ // Properties of the BPEL client -- all are configurable
+ private int socketTimeout;
+ private int connectTimeout;
+ private int retryCount;
+ private int retryInterval;
+ private Set<Integer> retryList;
+ private String credentials;
+
+ // last response from BPEL engine
+ private int lastResponseCode;
+ private String lastResponse;
+
+ /**
+ * Create a client to send results to the BPEL engine, using configuration from the
+ * MSO_PROP_VNF_ADAPTER properties.
+ */
+ public BpelRestClient() {
+ socketTimeout = DEFAULT_SOCKET_TIMEOUT;
+ connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+ retryCount = DEFAULT_RETRY_COUNT;
+ retryInterval = DEFAULT_RETRY_INTERVAL;
+ setRetryList(DEFAULT_RETRY_LIST);
+ credentials = DEFAULT_CREDENTIALS;
+ lastResponseCode = 0;
+ lastResponse = "";
+
+ try {
+ MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ MsoJavaProperties jp = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER);
+ socketTimeout = jp.getIntProperty(SOCKET_TIMEOUT_PROPERTY, DEFAULT_SOCKET_TIMEOUT);
+ connectTimeout = jp.getIntProperty(CONN_TIMEOUT_PROPERTY, DEFAULT_CONNECT_TIMEOUT);
+ retryCount = jp.getIntProperty(RETRY_COUNT_PROPERTY, DEFAULT_RETRY_COUNT);
+ retryInterval = jp.getIntProperty(RETRY_INTERVAL_PROPERTY, DEFAULT_RETRY_INTERVAL);
+ setRetryList(jp.getProperty(RETRY_LIST_PROPERTY, DEFAULT_RETRY_LIST));
+ credentials = jp.getEncryptedProperty(BPEL_AUTH_PROPERTY, DEFAULT_CREDENTIALS, ENCRYPTION_KEY);
+ } catch (MsoPropertiesException e) {
+ String error = "Unable to get properties:" + MSO_PROP_VNF_ADAPTER;
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Camunda", "", MsoLogger.ErrorCode.AvailabilityError, "MsoPropertiesException - Unable to get properties", e);
+ }
+ }
+
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(int retryCount) {
+ if (retryCount < 0)
+ retryCount = DEFAULT_RETRY_COUNT;
+ this.retryCount = retryCount;
+ }
+
+ public int getRetryInterval() {
+ return retryInterval;
+ }
+
+ public void setRetryInterval(int retryInterval) {
+ this.retryInterval = retryInterval;
+ }
+
+ public String getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(String credentials) {
+ this.credentials = credentials;
+ }
+
+ public String getRetryList() {
+ if (retryList.size() == 0)
+ return "";
+ String t = retryList.toString();
+ return t.substring(1, t.length()-1);
+ }
+
+ public void setRetryList(String retryList) {
+ Set<Integer> s = new TreeSet<Integer>();
+ for (String t : retryList.split("[, ]")) {
+ try {
+ s.add(Integer.parseInt(t));
+ } catch (NumberFormatException x) {
+ // ignore
+ }
+ }
+ this.retryList = s;
+ }
+
+ public int getLastResponseCode() {
+ return lastResponseCode;
+ }
+
+ public String getLastResponse() {
+ return lastResponse;
+ }
+
+ /**
+ * Post a response to the URL of the BPEL engine. As long as the response code is one of those in
+ * the retryList, the post will be retried up to "retrycount" times with an interval (in seconds)
+ * of "retryInterval". If retryInterval is negative, then each successive retry interval will be
+ * double the previous one.
+ * @param toBpelStr the content (XML or JSON) to post
+ * @param bpelUrl the URL to post to
+ * @param isxml true if the content is XML, otherwise assumed to be JSON
+ * @return true if the post succeeded, false if all retries failed
+ */
+ public boolean bpelPost(final String toBpelStr, final String bpelUrl, final boolean isxml) {
+ debug("Sending response to BPEL: " + toBpelStr);
+ int totalretries = 0;
+ int retryint = retryInterval;
+ while (true) {
+ sendOne(toBpelStr, bpelUrl, isxml);
+ // Note: really should handle response code 415 by switching between content types if needed
+ if (!retryList.contains(lastResponseCode)) {
+ debug("Got response code: " + lastResponseCode + ": returning.");
+ return true;
+ }
+ if (totalretries >= retryCount) {
+ debug("Retried " + totalretries + " times, giving up.");
+ LOGGER.error(MessageEnum.RA_SEND_VNF_NOTIF_ERR, "Could not deliver response to BPEL after "+totalretries+" tries: "+toBpelStr, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, "Could not deliver response to BPEL");
+ return false;
+ }
+ totalretries++;
+ int sleepinterval = retryint;
+ if (retryint < 0) {
+ // if retry interval is negative double the retry on each pass
+ sleepinterval = -retryint;
+ retryint *= 2;
+ }
+ debug("Sleeping for " + sleepinterval + " seconds.");
+ try {
+ Thread.sleep(sleepinterval * 1000L);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ private void debug(String m) {
+ LOGGER.debug(m);
+// System.err.println(m);
+ }
+ private void sendOne(final String toBpelStr, final String bpelUrl, final boolean isxml) {
+ LOGGER.debug("Sending to BPEL server: "+bpelUrl);
+ LOGGER.debug("Content is: "+toBpelStr);
+
+ //POST
+ HttpPost post = new HttpPost(bpelUrl);
+ if (credentials != null && !credentials.isEmpty())
+ post.addHeader("Authorization", "Basic " + DatatypeConverter.printBase64Binary(credentials.getBytes()));
+
+ //ContentType
+ ContentType ctype = isxml ? ContentType.APPLICATION_XML : ContentType.APPLICATION_JSON;
+ post.setEntity(new StringEntity(toBpelStr, ctype));
+
+ //Timeouts
+ RequestConfig requestConfig = RequestConfig
+ .custom()
+ .setSocketTimeout(socketTimeout * 1000)
+ .setConnectTimeout(connectTimeout * 1000)
+ .build();
+ post.setConfig(requestConfig);
+
+ //Client 4.3+
+ //Execute & GetResponse
+ try (CloseableHttpClient client = HttpClients.createDefault();
+ CloseableHttpResponse response = client.execute(post)) {
+ if (response != null) {
+ lastResponseCode = response.getStatusLine().getStatusCode();
+ HttpEntity entity = response.getEntity();
+ lastResponse = (entity != null) ? EntityUtils.toString(entity) : "";
+ } else {
+ lastResponseCode = 900;
+ lastResponse = "";
+ }
+ } catch (Exception e) {
+ String error = "Error sending Bpel notification:" + toBpelStr;
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, error, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Error sending Bpel notification", e);
+ lastResponseCode = 900;
+ lastResponse = "";
+ }
+ LOGGER.debug("Response code from BPEL server: "+lastResponseCode);
+ LOGGER.debug("Response body is: "+lastResponse);
+ }
+
+ public static void main(String[] a) throws MsoPropertiesException {
+ final String bpelengine = "http://mtmac1.research.att.com:8080/catch.jsp";
+ final String propfile = "/tmp/mso.vnf.properties";
+ // "/Users/eby/src/mso.rest/mso/packages/mso-config-centralized/mso-po-adapter-config/mso.vnf.properties"
+ final String xml =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
+ "<updateVolumeGroupResponse><volumeGroupId>1464013300723</volumeGroupId><volumeGroupOutputs>" +
+ "<entry><key>clyde</key><value>10</value></entry>" +
+ "<entry><key>wayne</key><value>99</value></entry>" +
+ "<entry><key>mickey</key><value>7</value></entry>" +
+ "</volumeGroupOutputs></updateVolumeGroupResponse>";
+
+ MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ msoPropertiesFactory.initializeMsoProperties (MSO_PROP_VNF_ADAPTER, propfile);
+
+ BpelRestClient bc = new BpelRestClient();
+ System.out.println(bc.getRetryList());
+ System.out.println(bc.getCredentials()); // poAvos:Domain2.0!
+
+ bc.bpelPost(xml, bpelengine, true);
+ System.out.println("respcode = "+bc.getLastResponseCode());
+ System.out.println("resp = "+bc.getLastResponse());
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/HealthCheckHandler.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/HealthCheckHandler.java
new file mode 100644
index 0000000000..108baf3444
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/HealthCheckHandler.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.HealthCheckUtils;
+import org.openecomp.mso.utils.UUIDChecker;
+
+
+@Path("/")
+public class HealthCheckHandler {
+
+ private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
+ private static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
+
+ @HEAD
+ @GET
+ @Path("/healthcheck")
+ @Produces(MediaType.TEXT_HTML)
+ public Response healthcheck (@QueryParam("requestId") String requestId) {
+ long startTime = System.currentTimeMillis ();
+ MsoLogger.setServiceName ("Healthcheck");
+ UUIDChecker.verifyOldUUID(requestId, msoLogger);
+ HealthCheckUtils healthCheck = new HealthCheckUtils ();
+ if (!healthCheck.siteStatusCheck(msoLogger, startTime)) {
+ return HealthCheckUtils.HEALTH_CHECK_NOK_RESPONSE;
+ }
+
+ if (!healthCheck.configFileCheck(msoLogger, startTime, MSO_PROP_VNF_ADAPTER)) {
+ return HealthCheckUtils.NOT_STARTED_RESPONSE;
+ }
+
+ if (!healthCheck.catalogDBCheck (msoLogger, startTime)) {
+ return HealthCheckUtils.NOT_STARTED_RESPONSE;
+ }
+ msoLogger.debug("healthcheck - Successful");
+ return HealthCheckUtils.HEALTH_CHECK_RESPONSE;
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapter.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapter.java
new file mode 100644
index 0000000000..95d8ee23a0
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapter.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebParam.Mode;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.ws.Holder;
+
+import org.openecomp.mso.openstack.beans.VnfStatus;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+import org.openecomp.mso.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+import org.openecomp.mso.entity.MsoRequest;
+
+import java.util.Map;
+
+@WebService (name="VnfAdapter", targetNamespace="http://com.att.mso/vnf")
+public interface MsoVnfAdapter
+{
+ /**
+ * This is the "Create VNF" Web Service Endpoint definition.
+ */
+ @WebMethod
+ public void createVnf (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="vnfId", mode=Mode.OUT) Holder<String> vnfId,
+ @WebParam(name="outputs", mode=Mode.OUT) Holder<Map<String,String>> outputs,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<VnfRollback> rollback )
+ throws VnfException, VnfAlreadyExists;
+
+ @WebMethod
+ public void updateVnf (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="outputs", mode=Mode.OUT) Holder<Map<String,String>> outputs,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<VnfRollback> rollback )
+ throws VnfException;
+
+ @WebMethod
+ public void queryVnf (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="vnfExists", mode=Mode.OUT) Holder<Boolean> vnfExists,
+ @WebParam(name="vnfId", mode=Mode.OUT) Holder<String> vnfId,
+ @WebParam(name="status", mode=Mode.OUT) Holder<VnfStatus> status,
+ @WebParam(name="outputs", mode=Mode.OUT) Holder<Map<String,String>> outputs )
+ throws VnfException;
+
+ @WebMethod
+ public void deleteVnf (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="request") MsoRequest msoRequest)
+ throws VnfException;
+
+
+ @WebMethod
+ public void rollbackVnf (@WebParam(name="rollback") @XmlElement(required=true) VnfRollback rollback)
+ throws VnfException;
+
+ @WebMethod
+ public void createVfModule (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="baseVfHeatStackId") @XmlElement(required=false) String baseVfHeatStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="vnfId", mode=Mode.OUT) Holder<String> vnfId,
+ @WebParam(name="outputs", mode=Mode.OUT) Holder<Map<String,String>> outputs,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<VnfRollback> rollback )
+ throws VnfException, VnfAlreadyExists;
+
+ @WebMethod
+ public void deleteVfModule (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vfName") @XmlElement(required=true) String vfName,
+ @WebParam(name="request") MsoRequest msoRequest)
+ throws VnfException;
+
+ @WebMethod
+ public void updateVfModule (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="baseVfHeatStackId") @XmlElement(required=false) String baseVfHeatStackId,
+ @WebParam(name="vfModuleStackId") @XmlElement(required=false) String vfModuleStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="outputs", mode=Mode.OUT) Holder<Map<String,String>> outputs,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<VnfRollback> rollback )
+ throws VnfException;
+
+ @WebMethod
+ public void healthCheck ();
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsync.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsync.java
new file mode 100644
index 0000000000..d58e9ee6a8
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsync.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import javax.jws.Oneway;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+import java.util.Map;
+
+/**
+ * This webservice defines the Asynchronous versions of VNF adapter calls.
+ * The notification messages for final responses are documented elsewhere
+ * (by the client service WSDL).
+ *
+ */
+@WebService (name="VnfAdapterAsync", targetNamespace="http://com.att.mso/vnfA")
+public interface MsoVnfAdapterAsync
+{
+ /**
+ * This is the "Create VNF" Web Service Endpoint definition.
+ */
+ @WebMethod
+ @Oneway
+ public void createVnfA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="messageId") @XmlElement(required=true) String messageId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="notificationUrl") @XmlElement(required=true) String notificationUrl );
+
+ @WebMethod
+ @Oneway
+ public void updateVnfA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfType") @XmlElement(required=true) String vnfType,
+ @WebParam(name="vnfVersion") @XmlElement(required=false) String vnfVersion,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="requestType") @XmlElement(required=false) String requestType,
+ @WebParam(name="volumeGroupHeatStackId") @XmlElement(required=false) String volumeGroupHeatStackId,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="messageId") @XmlElement(required=true) String messageId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="notificationUrl") @XmlElement(required=true) String notificationUrl );
+
+ @WebMethod
+ @Oneway
+ public void queryVnfA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="messageId") @XmlElement(required=true) String messageId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="notificationUrl") @XmlElement(required=true) String notificationUrl );
+
+ @WebMethod
+ @Oneway
+ public void deleteVnfA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="vnfName") @XmlElement(required=true) String vnfName,
+ @WebParam(name="messageId") @XmlElement(required=true) String messageId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="notificationUrl") @XmlElement(required=true) String notificationUrl );
+
+ @WebMethod
+ @Oneway
+ public void rollbackVnfA (@WebParam(name="rollback") @XmlElement(required=true) VnfRollback rollback,
+ @WebParam(name="messageId") @XmlElement(required=true) String messageId,
+ @WebParam(name="notificationUrl") @XmlElement(required=true) String notificationUrl );
+
+
+ @WebMethod
+ public void healthCheckA ();
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsyncImpl.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsyncImpl.java
new file mode 100644
index 0000000000..c192eb6063
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterAsyncImpl.java
@@ -0,0 +1,652 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jws.WebService;
+import javax.xml.bind.DatatypeConverter;
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Holder;
+import javax.xml.ws.handler.MessageContext;
+
+import org.openecomp.mso.adapters.vnf.async.client.CreateVnfNotification;
+import org.openecomp.mso.adapters.vnf.async.client.QueryVnfNotification;
+import org.openecomp.mso.adapters.vnf.async.client.UpdateVnfNotification;
+import org.openecomp.mso.adapters.vnf.async.client.VnfAdapterNotify;
+import org.openecomp.mso.adapters.vnf.async.client.VnfAdapterNotify_Service;
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoAlarmLogger;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+import org.openecomp.mso.openstack.beans.VnfStatus;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+
+@WebService(serviceName = "VnfAdapterAsync", endpointInterface = "org.openecomp.mso.adapters.vnf.MsoVnfAdapterAsync", targetNamespace = "http://com.att.mso/vnfA")
+public class MsoVnfAdapterAsyncImpl implements MsoVnfAdapterAsync {
+
+ MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+
+ CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
+
+ public static final String MSO_PROP_VNF_ADAPTER="MSO_PROP_VNF_ADAPTER";
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String BPEL_AUTH_PROP = "org.openecomp.mso.adapters.vnf.bpelauth";
+ private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
+
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheckA () {
+ LOGGER.debug ("Health check call in VNF Adapter");
+ }
+
+ /**
+ * This is the asynchronous "Create VNF" web service implementation.
+ * It will create a new VNF of the requested type in the specified cloud
+ * and tenant. The tenant must exist before this service is called.
+ *
+ * If a VNF with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * All VNF types will be defined in the MSO catalog. The caller must request
+ * one of these pre-defined types or an error will be returned. Within the
+ * catalog, each VNF type references (among other things) a Heat template
+ * which is used to deploy the required VNF artifacts (VMs, networks, etc.)
+ * to the cloud.
+ *
+ * Depending on the Heat template, a variable set of input parameters will
+ * be defined, some of which are required. The caller is responsible to
+ * pass the necessary input data for the VNF or an error will be thrown.
+ *
+ * The method sends an asynchronous response to the notification URL when
+ * processing completes. The createAsyncResponse contains the vnfId (the
+ * canonical name of the stack), a Map of VNF output attributes, and a
+ * VnfRollback object. This last object can be passed as-is to the
+ * rollbackVnf operation to undo everything that was created for the VNF.
+ * This is useful if a VNF is successfully created but the orchestrator
+ * fails on a subsequent operation.
+ *
+ * Note: this method is implemented by calling the synchronous web method
+ * and translating the response to an asynchronous notification.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
+ * @param tenantId Openstack tenant identifier
+ * @param vnfType VNF type key, should match a VNF definition in catalog DB
+ * @param vnfName Name to be assigned to the new VNF
+ * @param inputs Map of key=value inputs for VNF stack creation
+ * @param failIfExists Flag whether already existing VNF should be considered
+ * a success or failure
+ * @param msoRequest Request tracking information for logs
+ * @param notificationURL the target URL for asynchronous response
+ */
+ @Override
+ public void createVnfA (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ String serviceName = "CreateVnfA";
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.info (MessageEnum.RA_ASYNC_CREATE_VNF, vnfName, vnfType, cloudSiteId, tenantId, "", "createVnfA");
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ // Use the synchronous method to perform the actual Create
+ MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory, cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <String> vnfId = new Holder <String> ();
+ Holder <Map <String, String>> outputs = new Holder <Map <String, String>> ();
+ Holder <VnfRollback> vnfRollback = new Holder <VnfRollback> ();
+
+ try {
+ vnfAdapter.createVnf (cloudSiteId,
+ tenantId,
+ vnfType,
+ vnfVersion,
+ vnfName,
+ requestType,
+ volumeGroupHeatStackId,
+ inputs,
+ failIfExists,
+ backout,
+ msoRequest,
+ vnfId,
+ outputs,
+ vnfRollback);
+ MsoLogger.setServiceName (serviceName);
+ } catch (VnfException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vnfName, cloudSiteId, tenantId, "", "createVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException in createVnfA", e);
+ org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory.fromValue (e.getFaultInfo ()
+ .getCategory ()
+ .name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "createVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.createVnfNotification (messageId, false, exCat, eMsg, null, null, null);
+ } catch (Exception e1) {
+ error = "Error sending createVnf notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "createVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending createVnf notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_CREATE_VNF_COMPLETE, "", "createVnfA", "", "createVnfA");
+ return;
+ }
+ LOGGER.debug ("Async Create VNF: " + vnfName + " VnfId:" + vnfId.value);
+ // Build and send Asynchronous response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.createVnfNotification (messageId,
+ true,
+ null,
+ null,
+ vnfId.value,
+ copyCreateOutputs (outputs),
+ copyVrb (vnfRollback));
+ } catch (Exception e) {
+ error = "Error sending createVnf notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "createVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending createVnf notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_CREATE_VNF_COMPLETE, "", "createVnfA");
+ return;
+ }
+
+ @Override
+ public void updateVnfA (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ Map <String, String> inputs,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ String serviceName = "UpdateVnfA";
+ MsoLogger.setServiceName (serviceName);
+ MsoLogger.setLogContext (msoRequest);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ LOGGER.info (MessageEnum.RA_ASYNC_UPDATE_VNF, vnfName, vnfType, cloudSiteId, tenantId, "", "UpdateVnfA");
+
+ // Use the synchronous method to perform the actual Create
+ MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <String> vnfId = new Holder <String> ();
+ Holder <Map <String, String>> outputs = new Holder <Map <String, String>> ();
+ Holder <VnfRollback> vnfRollback = new Holder <VnfRollback> ();
+
+ try {
+ vnfAdapter.updateVnf (cloudSiteId, tenantId, vnfType,vnfVersion, vnfName, requestType, volumeGroupHeatStackId, inputs, msoRequest, outputs, vnfRollback);
+ MsoLogger.setServiceName (serviceName);
+ } catch (VnfException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, vnfName, cloudSiteId, tenantId, "", "UpdateVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending updateVnf notification", e);
+ org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory.fromValue (e.getFaultInfo ()
+ .getCategory ()
+ .name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "UpdateVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.updateVnfNotification (messageId, false, exCat, eMsg, null, null);
+ } catch (Exception e1) {
+ error = "Error sending updateVnf notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "UpdateVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending updateVnf notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_UPDATE_VNF_COMPLETE, "", "UpdateVnfA");
+ return;
+ }
+ LOGGER.debug ("Async Update VNF: " + vnfName + " VnfId:" + vnfId.value);
+ // Build and send Asynchronous response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.updateVnfNotification (messageId,
+ true,
+ null,
+ null,
+ copyUpdateOutputs (outputs),
+ copyVrb (vnfRollback));
+ } catch (Exception e) {
+ error = "Error sending updateVnf notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "UpdateVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending updateVnf notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_UPDATE_VNF_COMPLETE, "", "UpdateVnfA");
+ return;
+ }
+
+ /**
+ * This is the "Query VNF" web service implementation.
+ * It will look up a VNF by name or ID in the specified cloud and tenant.
+ *
+ * The method returns an indicator that the VNF exists, its Openstack internal
+ * ID, its status, and the set of outputs (from when the stack was created).
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to query
+ * @param tenantId Openstack tenant identifier
+ * @param vnfName VNF Name or Openstack ID
+ * @param msoRequest Request tracking information for logs
+ * @param notificationURL the target URL for asynchronous response
+ */
+ @Override
+ public void queryVnfA (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ String serviceName = "QueryVnfA";
+ MsoLogger.setServiceName (serviceName);
+ MsoLogger.setLogContext (msoRequest);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ LOGGER.info (MessageEnum.RA_ASYNC_QUERY_VNF, vnfName, cloudSiteId, tenantId);
+
+ // Use the synchronous method to perform the actual query
+ MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> vnfExists = new Holder <Boolean> ();
+ Holder <String> vnfId = new Holder <String> ();
+ Holder <VnfStatus> status = new Holder <VnfStatus> ();
+ Holder <Map <String, String>> outputs = new Holder <Map <String, String>> ();
+
+ try {
+ vnfAdapter.queryVnf (cloudSiteId, tenantId, vnfName, msoRequest, vnfExists, vnfId, status, outputs);
+ MsoLogger.setServiceName (serviceName);
+ } catch (VnfException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "", "queryVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending queryVnfA notification", e);
+ org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory.fromValue (e.getFaultInfo ()
+ .getCategory ()
+ .name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "queryVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.queryVnfNotification (messageId, false, exCat, eMsg, null, null, null, null);
+ } catch (Exception e1) {
+ error = "Error sending queryVnf notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "queryVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending queryVnf notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_QUERY_VNF_COMPLETE, "", "queryVnfA");
+ return;
+ }
+
+ if (!vnfExists.value) {
+ LOGGER.debug ("Async Query, VNF not found");
+ } else {
+ LOGGER.debug ("Async Query, VNF=" + vnfId.value + ", status=" + status.value);
+ }
+ // Build and send Asynchronous response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ org.openecomp.mso.adapters.vnf.async.client.VnfStatus vnfS = org.openecomp.mso.adapters.vnf.async.client.VnfStatus.fromValue (status.value.name ());
+ notifyPort.queryVnfNotification (messageId,
+ true,
+ null,
+ null,
+ vnfExists.value,
+ vnfId.value,
+ vnfS,
+ copyQueryOutputs (outputs));
+ } catch (Exception e) {
+ error = "Error sending queryVnf notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "queryVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending queryVnf notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+
+ LOGGER.info (MessageEnum.RA_ASYNC_QUERY_VNF_COMPLETE, "", "queryVnfA");
+ return;
+ }
+
+ /**
+ * This is the Asynchronous "Delete VNF" web service implementation.
+ * It will delete a VNF by name or ID in the specified cloud and tenant.
+ *
+ * The method has no outputs.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to delete
+ * @param tenantId Openstack tenant identifier
+ * @param vnfName VNF Name or Openstack ID
+ * @param msoRequest Request tracking information for logs
+ * @param notificationURL the target URL for asynchronous response
+ */
+ @Override
+ public void deleteVnfA (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ String serviceName = "DeleteVnfA";
+ MsoLogger.setServiceName (serviceName);
+ MsoLogger.setLogContext (msoRequest);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ LOGGER.info (MessageEnum.RA_ASYNC_DELETE_VNF, vnfName, cloudSiteId, tenantId);
+
+ // Use the synchronous method to perform the actual delete
+ MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ try {
+ vnfAdapter.deleteVnf (cloudSiteId, tenantId, vnfName, msoRequest);
+ MsoLogger.setServiceName (serviceName);
+ } catch (VnfException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "", "deleteVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending deleteVnfA notification", e);
+ org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory.fromValue (e.getFaultInfo ()
+ .getCategory ()
+ .name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "deleteVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.deleteVnfNotification (messageId, false, exCat, eMsg);
+ } catch (Exception e1) {
+ error = "Error sending deleteVnf notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "deleteVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending deleteVnfA notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_DELETE_VNF_COMPLETE, "", "deleteVnfA");
+ return;
+ }
+
+ LOGGER.debug ("Async Delete VNF: " + vnfName);
+ // Build and send Asynchronous response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.deleteVnfNotification (messageId, true, null, null);
+
+ } catch (Exception e) {
+ error = "Error sending deleteVnf notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "deleteVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending deleteVnfA notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+
+ LOGGER.info (MessageEnum.RA_ASYNC_DELETE_VNF_COMPLETE, "", "deleteVnfA");
+ return;
+ }
+
+ /**
+ * This web service endpoint will rollback a previous Create VNF operation.
+ * A rollback object is returned to the client in a successful creation
+ * response. The client can pass that object as-is back to the rollbackVnf
+ * operation to undo the creation.
+ */
+ @Override
+ public void rollbackVnfA (VnfRollback rollback, String messageId, String notificationUrl) {
+ String serviceName = "RollbackVnfA";
+ MsoLogger.setServiceName (serviceName);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ String error;
+ // rollback may be null (e.g. if stack already existed when Create was called)
+ if (rollback == null) {
+ error = "Empty Rollback: No action to perform";
+ LOGGER.info (MessageEnum.RA_ROLLBACK_NULL, "", "rollbackVnfA");
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ return;
+ }
+
+ MsoLogger.setLogContext (rollback.getMsoRequest ());
+ LOGGER.info (MessageEnum.RA_ASYNC_ROLLBACK_VNF, "", "rollbackVnfA");
+
+ // Use the synchronous method to perform the actual rollback
+ MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ try {
+ vnfAdapter.rollbackVnf (rollback);
+ MsoLogger.setServiceName (serviceName);
+ } catch (VnfException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "rollbackVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending rollbackVnfA notification", e);
+ org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.openecomp.mso.adapters.vnf.async.client.MsoExceptionCategory.fromValue (e.getFaultInfo ()
+ .getCategory ()
+ .name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "rollbackVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.rollbackVnfNotification (messageId, false, exCat, eMsg);
+ } catch (Exception e1) {
+ error = "Error sending rollbackVnf notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "rollbackVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending rollbackVnfA notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ LOGGER.info (MessageEnum.RA_ASYNC_ROLLBACK_VNF_COMPLETE, "", "rollbackVnfA");
+ return;
+ }
+
+ LOGGER.debug ("Async Rollback VNF:" + rollback.getVnfId ());
+ // Build and send Asynchronous response
+ try {
+ VnfAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.rollbackVnfNotification (messageId, true, null, null);
+ } catch (Exception e) {
+ error = "Error sending rollbackVnf notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, "", "rollbackVnfA", MsoLogger.ErrorCode.BusinessProcesssError, "Exception sending rollbackVnfA notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+
+ LOGGER.info (MessageEnum.RA_ASYNC_ROLLBACK_VNF_COMPLETE, "", "rollbackVnfA");
+ return;
+ }
+
+ private org.openecomp.mso.adapters.vnf.async.client.VnfRollback copyVrb (Holder <VnfRollback> hVrb) {
+ org.openecomp.mso.adapters.vnf.async.client.VnfRollback cvrb = new org.openecomp.mso.adapters.vnf.async.client.VnfRollback ();
+
+ if (hVrb != null && hVrb.value != null) {
+ org.openecomp.mso.adapters.vnf.async.client.MsoRequest cmr = new org.openecomp.mso.adapters.vnf.async.client.MsoRequest ();
+
+ cvrb.setCloudSiteId (hVrb.value.getCloudSiteId ());
+ if (hVrb.value.getMsoRequest() != null) {
+ cmr.setRequestId (hVrb.value.getMsoRequest ().getRequestId ());
+ cmr.setServiceInstanceId (hVrb.value.getMsoRequest ().getServiceInstanceId ());
+ } else {
+ cmr.setRequestId (null);
+ cmr.setServiceInstanceId (null);
+ }
+ cvrb.setMsoRequest (cmr);
+ cvrb.setVnfId (hVrb.value.getVnfId ());
+ cvrb.setTenantId (hVrb.value.getTenantId ());
+ cvrb.setTenantCreated (hVrb.value.getTenantCreated ());
+ cvrb.setVnfCreated (hVrb.value.getVnfCreated ());
+ }
+ return cvrb;
+ }
+
+ private CreateVnfNotification.Outputs copyCreateOutputs (Holder <Map <String, String>> hMap) {
+
+ CreateVnfNotification.Outputs outputs = new CreateVnfNotification.Outputs ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <String, String> ();
+ sMap = hMap.value;
+ CreateVnfNotification.Outputs.Entry entry = new CreateVnfNotification.Outputs.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ outputs.getEntry ().add (entry);
+ }
+ }
+ return outputs;
+ }
+
+ private UpdateVnfNotification.Outputs copyUpdateOutputs (Holder <Map <String, String>> hMap) {
+
+ UpdateVnfNotification.Outputs outputs = new UpdateVnfNotification.Outputs ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <String, String> ();
+ sMap = hMap.value;
+ UpdateVnfNotification.Outputs.Entry entry = new UpdateVnfNotification.Outputs.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ outputs.getEntry ().add (entry);
+ }
+ }
+ return outputs;
+ }
+
+ private QueryVnfNotification.Outputs copyQueryOutputs (Holder <Map <String, String>> hMap) {
+
+ QueryVnfNotification.Outputs outputs = new QueryVnfNotification.Outputs ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <String, String> ();
+ sMap = hMap.value;
+
+ QueryVnfNotification.Outputs.Entry entry = new QueryVnfNotification.Outputs.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ outputs.getEntry ().add (entry);
+ }
+ }
+ return outputs;
+ }
+
+ private VnfAdapterNotify getNotifyEP (String notificationUrl) {
+
+ URL warWsdlLoc = null;
+ try {
+ warWsdlLoc = Thread.currentThread ().getContextClassLoader ().getResource ("VnfAdapterNotify.wsdl");
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.RA_WSDL_NOT_FOUND, "VnfAdapterNotify.wsdl", "", "getNotifyEP", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - WSDL not found", e);
+ }
+ if (warWsdlLoc == null) {
+ LOGGER.error (MessageEnum.RA_WSDL_NOT_FOUND, "VnfAdapterNotify.wsdl", "", "getNotifyEP", MsoLogger.ErrorCode.BusinessProcesssError, "WSDL not found");
+ } else {
+ try {
+ LOGGER.debug ("VnfAdpaterNotify.wsdl location:" + warWsdlLoc.toURI ().toString ());
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.RA_WSDL_URL_CONVENTION_EXC, "VnfAdapterNotify.wsdl", "", "getNotifyEP", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - WSDL URL convention", e);
+ }
+ }
+
+ VnfAdapterNotify_Service notifySvc = new VnfAdapterNotify_Service (warWsdlLoc,
+ new QName ("http://com.att.mso/vnfNotify",
+ "vnfAdapterNotify"));
+
+ VnfAdapterNotify notifyPort = notifySvc.getMsoVnfAdapterAsyncImplPort ();
+
+ BindingProvider bp = (BindingProvider) notifyPort;
+
+ URL epUrl = null;
+ try {
+ epUrl = new URL (notificationUrl);
+ } catch (MalformedURLException e1) {
+ LOGGER.error (MessageEnum.RA_INIT_NOTIF_EXC, "", "getNotifyEP", MsoLogger.ErrorCode.BusinessProcesssError, "MalformedURLException", e1);
+ }
+
+ LOGGER.debug ("Notification Endpoint URL: " + epUrl.toExternalForm ());
+
+ bp.getRequestContext ().put (BindingProvider.ENDPOINT_ADDRESS_PROPERTY, epUrl.toExternalForm ());
+
+ // authentication
+ try {
+ Map <String, Object> req_ctx = bp.getRequestContext ();
+ Map <String, List <String>> headers = new HashMap <String, List <String>> ();
+
+ String userCredentials = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER).getEncryptedProperty (BPEL_AUTH_PROP,
+ "",
+ ENCRYPTION_KEY);
+
+ String basicAuth = "Basic " + DatatypeConverter.printBase64Binary (userCredentials.getBytes ());
+ req_ctx.put (MessageContext.HTTP_REQUEST_HEADERS, headers);
+ headers.put ("Authorization", Collections.singletonList (basicAuth));
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.RA_SET_CALLBACK_AUTH_EXC, "", "getNotifyEP", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Unable to set authorization in callback request", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, "Unable to set authorization in callback request");
+ }
+
+ return notifyPort;
+ }
+
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterImpl.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterImpl.java
new file mode 100644
index 0000000000..757f875128
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/MsoVnfAdapterImpl.java
@@ -0,0 +1,2391 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.openecomp.mso.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+import org.openecomp.mso.adapters.vnf.exceptions.VnfNotFound;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.cloud.CloudConfig;
+import org.openecomp.mso.cloud.CloudSite;
+import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
+import org.openecomp.mso.db.catalog.CatalogDatabase;
+import org.openecomp.mso.db.catalog.beans.HeatEnvironment;
+import org.openecomp.mso.db.catalog.beans.HeatFiles;
+import org.openecomp.mso.db.catalog.beans.HeatTemplate;
+import org.openecomp.mso.db.catalog.beans.HeatTemplateParam;
+import org.openecomp.mso.db.catalog.beans.VnfResource;
+import org.openecomp.mso.db.catalog.beans.VfModule;
+import org.openecomp.mso.db.catalog.beans.VnfComponent;
+import org.openecomp.mso.entity.MsoRequest;
+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.beans.VnfStatus;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+import org.openecomp.mso.openstack.exceptions.MsoException;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.openstack.utils.MsoHeatUtils;
+import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
+import org.openecomp.mso.openstack.utils.MsoHeatEnvironmentEntry;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.ObjectMapper;
+
+@WebService(serviceName = "VnfAdapter", endpointInterface = "org.openecomp.mso.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://com.att.mso/vnf")
+public class MsoVnfAdapterImpl implements MsoVnfAdapter {
+
+ CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
+ protected CloudConfig cloudConfig = null;
+
+ MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
+
+ private static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
+ private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
+ private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter.";
+ private static final String LOG_REPLY_NAME = "MSO-VnfAdapter:MSO-BPMN.";
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String CHECK_REQD_PARAMS = "org.openecomp.mso.adapters.vnf.checkRequiredParameters";
+ private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.openecomp.mso.adapters.vnf.addGetFilesOnVolumeReq";
+
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheck () {
+ LOGGER.debug ("Health check call in VNF Adapter");
+ }
+
+ /**
+ * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
+ * @see MsoVnfAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
+ */
+ public MsoVnfAdapterImpl() {
+
+ }
+
+ /**
+ * This constructor MUST be used if this class is called with the new operator.
+ * @param msoPropFactory
+ */
+ public MsoVnfAdapterImpl(MsoPropertiesFactory msoPropFactory, CloudConfigFactory cloudConfigFact) {
+ this.msoPropertiesFactory = msoPropFactory;
+ this.cloudConfigFactory = cloudConfigFact;
+ }
+
+ /**
+ * This is the "Create VNF" web service implementation.
+ * It will create a new VNF of the requested type in the specified cloud
+ * and tenant. The tenant must exist before this service is called.
+ *
+ * If a VNF with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * All VNF types will be defined in the MSO catalog. The caller must request
+ * one of these pre-defined types or an error will be returned. Within the
+ * catalog, each VNF type references (among other things) a Heat template
+ * which is used to deploy the required VNF artifacts (VMs, networks, etc.)
+ * to the cloud.
+ *
+ * Depending on the Heat template, a variable set of input parameters will
+ * be defined, some of which are required. The caller is responsible to
+ * pass the necessary input data for the VNF or an error will be thrown.
+ *
+ * The method returns the vnfId (the canonical name), a Map of VNF output
+ * attributes, and a VnfRollback object. This last object can be passed
+ * as-is to the rollbackVnf operation to undo everything that was created
+ * for the VNF. This is useful if a VNF is successfully created but the
+ * orchestrator fails on a subsequent operation.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
+ * @param tenantId Openstack tenant identifier
+ * @param vnfType VNF type key, should match a VNF definition in catalog DB
+ * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
+ * @param vnfName Name to be assigned to the new VNF
+ * @param inputs Map of key=value inputs for VNF stack creation
+ * @param failIfExists Flag whether already existing VNF should be considered
+ * a success or failure
+ * @param msoRequest Request tracking information for logs
+ * @param vnfId Holder for output VNF Openstack ID
+ * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
+ * @param rollback Holder for returning VnfRollback object
+ */
+ @Override
+ public void createVnf (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ // Create a hook here to catch shortcut createVf requests:
+ if (requestType != null) {
+ if (requestType.startsWith("VFMOD")) {
+ LOGGER.debug("Calling createVfModule from createVnf -- requestType=" + requestType);
+ String newRequestType = requestType.substring(5);
+ String vfVolGroupHeatStackId = "";
+ String vfBaseHeatStackId = "";
+ try {
+ if (volumeGroupHeatStackId != null) {
+ vfVolGroupHeatStackId = volumeGroupHeatStackId.substring(0, volumeGroupHeatStackId.lastIndexOf("|"));
+ vfBaseHeatStackId = volumeGroupHeatStackId.substring(volumeGroupHeatStackId.lastIndexOf("|")+1);
+ }
+ } catch (Exception e) {
+ // might be ok - both are just blank
+ LOGGER.debug("ERROR trying to parse the volumeGroupHeatStackId " + volumeGroupHeatStackId);
+ }
+ this.createVfModule(cloudSiteId,
+ tenantId,
+ vnfType,
+ vnfVersion,
+ vnfName,
+ newRequestType,
+ vfVolGroupHeatStackId,
+ vfBaseHeatStackId,
+ inputs,
+ failIfExists,
+ backout,
+ msoRequest,
+ vnfId,
+ outputs,
+ rollback);
+ return;
+ }
+ }
+ // createVf will know if the requestType starts with "X" that it's the "old" way
+ StringBuilder newRequestTypeSb = new StringBuilder("X");
+ String vfVolGroupHeatStackId = "";
+ String vfBaseHeatStackId = "";
+ if (requestType != null) {
+ newRequestTypeSb.append(requestType);
+ }
+ this.createVfModule(cloudSiteId,
+ tenantId,
+ vnfType,
+ vnfVersion,
+ vnfName,
+ newRequestTypeSb.toString(),
+ vfVolGroupHeatStackId,
+ vfBaseHeatStackId,
+ inputs,
+ failIfExists,
+ backout,
+ msoRequest,
+ vnfId,
+ outputs,
+ rollback);
+ return;
+ // End createVf shortcut
+ }
+
+ @Override
+ public void updateVnf (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ Map <String, String> inputs,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
+ MsoLogger.setServiceName ("UpdateVnf");
+ String requestTypeString = "";
+ if (requestType != null && !requestType.equals("")) {
+ requestTypeString = requestType;
+ }
+ String nestedStackId = null;
+ if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
+ nestedStackId = volumeGroupHeatStackId;
+ }
+
+ LOGGER.debug ("Updating VNF: " + vnfName + " of type " + vnfType + "in " + cloudSiteId + "/" + tenantId);
+ LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Build a default rollback object (no actions performed)
+ VnfRollback vnfRollback = new VnfRollback ();
+ vnfRollback.setCloudSiteId (cloudSiteId);
+ vnfRollback.setTenantId (tenantId);
+ vnfRollback.setMsoRequest (msoRequest);
+ vnfRollback.setRequestType(requestTypeString);
+
+ // First, look up to see if the VNF already exists.
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+ MsoHeatUtilsWithUpdate heatU = new MsoHeatUtilsWithUpdate (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ StackInfo heatStack = null;
+ long queryStackStarttime1 = System.currentTimeMillis ();
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, vnfName);
+ LOGGER.recordMetricEvent (queryStackStarttime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("UpdateVNF");
+ String error = "Update VNF: Query " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (queryStackStarttime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in updateVnf", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
+ // Not Found
+ String error = "Update VNF: Stack " + vnfName + " does not exist in " + cloudSiteId + "/" + tenantId;
+ LOGGER.error (MessageEnum.RA_VNF_NOT_EXIST, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Stack " + vnfName + " does not exist");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfNotFound (cloudSiteId, tenantId, vnfName);
+ } else {
+ LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
+ // Populate the outputs from the existing stack.
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vnfRollback; // Default rollback - no updates performed
+ }
+
+ // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
+ StackInfo nestedHeatStack = null;
+ long queryStackStarttime2 = System.currentTimeMillis ();
+ if (nestedStackId != null) {
+ try {
+ LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
+ nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
+ LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("UpdateVNF");
+ String error = "Update VNF: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.AvailabilityError, "Exception trying to query nested stack", me);
+ LOGGER.debug("ERROR trying to query nested stack= " + error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
+ String error = "Update VNF: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.AvailabilityError, "Attached heatStack ID DOES NOT EXIST");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ LOGGER.debug(error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found nested heat stack - copying values to inputs");
+ this.sendMapToDebug(inputs);
+ heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
+ this.sendMapToDebug(inputs);
+ }
+ }
+
+ // Ready to deploy the new VNF
+
+ try(CatalogDatabase db = new CatalogDatabase ()) {
+ // Retrieve the VNF definition
+ VnfResource vnf;
+ if (vnfVersion != null && !vnfVersion.isEmpty ()) {
+ vnf = db.getVnfResource (vnfType, vnfVersion);
+ } else {
+ vnf = db.getVnfResource (vnfType);
+ }
+ if (vnf == null) {
+ String error = "Update VNF: Unknown VNF Type: " + vnfType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Unknown VNF Type");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug ("Got VNF definition from Catalog: " + vnf.toString ());
+
+ // Currently, all VNFs are orchestrated via HEAT
+ if (!"HEAT".equals (vnf.getOrchestrationMode ())) {
+ String error = "Update VNF: Configuration error: VNF=" + vnfType;
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, " VNF=" + vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Configuration error");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ }
+
+ //1604 - Need to handle an updateVolume request.
+ VnfComponent vnfComponent = null;
+ if (requestTypeString != null && !requestTypeString.equals("")) {
+ LOGGER.debug("About to query for vnfComponent id = " + vnf.getId() + ", type = " + requestTypeString.toUpperCase());
+ vnfComponent = db.getVnfComponent(vnf.getId(), requestTypeString.toUpperCase());
+ if (vnfComponent == null) {
+ String error = "Update VNF: Cannot find VNF Component entry for: " + vnfType + ", type = " + requestTypeString.toUpperCase();
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Cannot find VNF Component entry");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug("FOUND VnfComponent: " + vnfComponent.toString());
+ }
+
+ HeatTemplate heatTemplate = db.getHeatTemplate (vnf.getTemplateId ());
+ if (heatTemplate == null) {
+ String error = "Update VNF: undefined Heat Template. VNF=" + vnfType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", String.valueOf(vnf.getTemplateId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Template");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ }
+
+ // If this is a component request - get the template associated for volumes
+ // May change this - for now get both templates - but volume will be 2nd, which makes sense
+ // for the rest of the code. Same with envt later
+ if (vnfComponent != null) {
+ LOGGER.debug("Querying db to find component template " + vnfComponent.getHeatTemplateId());
+ heatTemplate = db.getHeatTemplate(vnfComponent
+ .getHeatTemplateId());
+ if (heatTemplate == null) {
+ String error = "Update VNF: undefined Heat Template for Volume Component. VNF="
+ + vnfType;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "Heat Template ID",
+ String.valueOf(vnfComponent.getHeatTemplateId()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Template for Volume Component");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException(error, MsoExceptionCategory.INTERNAL);
+ }
+ }
+
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
+
+ // Add check for any Environment variable
+ HeatEnvironment heatEnvironment = null;
+ String heatEnvironmentString = null;
+
+ if (vnf.getEnvironmentId () != null) {
+ LOGGER.debug ("about to call getHeatEnvironment with :" + vnf.getEnvironmentId () + ":");
+ heatEnvironment = db.getHeatEnvironment (vnf.getEnvironmentId ());
+ if (heatEnvironment == null) {
+
+ String error = "Create VNF: undefined Heat Environment. VNF=" + vnfType
+ + ", Environment ID="
+ + vnf.getEnvironmentId ();
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(vnf.getEnvironmentId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Create VNF: undefined Heat Environment");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ } else {
+ LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
+ heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
+ LOGGER.debug ("After parsing: " + heatEnvironmentString);
+ }
+ } else {
+ LOGGER.debug ("no environment parameter for this VNF " + vnfType);
+ }
+
+ //1604 - override the VNF environment with the one for the component
+ if(vnfComponent != null) {
+ if (vnfComponent.getHeatEnvironmentId () != null) {
+ LOGGER.debug ("about to call getHeatEnvironment with :" + vnfComponent.getHeatEnvironmentId () + ":");
+ heatEnvironment = db.getHeatEnvironment (vnfComponent.getHeatEnvironmentId ());
+ if (heatEnvironment == null) {
+ String error = "Update VNF: undefined Heat Environment. VNF=" + vnfType
+ + ", Environment ID="
+ + vnfComponent.getHeatEnvironmentId ();
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(vnfComponent.getHeatEnvironmentId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Environment");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ } else {
+ LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
+ heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
+ LOGGER.debug ("after parsing: " + heatEnvironmentString);
+ }
+ } else {
+ LOGGER.debug ("no environment parameter for this VNF VOLUME component " + vnfType);
+ }
+ }
+ // End 1604
+
+
+ LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
+ + heatTemplate.getId ());
+ Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
+ Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
+ if (nestedTemplates != null) {
+ // for debugging print them out
+ LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
+ for (String providerResourceFile : nestedTemplates.keySet ()) {
+ String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
+ String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
+ nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
+ LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
+ }
+ } else {
+ LOGGER.debug ("No nested templates found - nothing to do here");
+ nestedTemplatesChecked = null;
+ }
+
+ // Also add the files: for any get_files associated with this vnf_resource_id
+ // *if* there are any
+ LOGGER.debug ("In MsoVnfAdapterImpl.updateVnf, about to call db.getHeatFiles avec vnfResourceId="
+ + vnf.getId ());
+ Map <String, HeatFiles> heatFiles = db.getHeatFiles (vnf.getId ());
+ Map <String, Object> heatFilesObjects = new HashMap <String, Object> ();
+ if (heatFiles != null) {
+ // add these to stack - to be done in createStack
+ // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
+ // this will match the nested templates format
+ LOGGER.debug ("Contents of heatFiles - to be added to files: on stack:");
+
+ for (String heatFileName : heatFiles.keySet ()) {
+ String heatFileBody = heatFiles.get (heatFileName).getFileBody ();
+ // Remove the file:/// enforcement for get_file:
+ //String heatFileNameChecked = this.enforceFilePrefix (heatFileName);
+ String heatFileNameChecked = heatFileName;
+ LOGGER.debug (heatFileNameChecked + " -> " + heatFileBody);
+ heatFilesObjects.put (heatFileNameChecked, heatFileBody);
+ }
+ } else {
+ LOGGER.debug ("No heat files found -nothing to do here");
+ heatFilesObjects = null;
+ }
+
+ // Check that required parameters have been supplied
+ String missingParams = null;
+ List <String> paramList = new ArrayList <String> ();
+
+ // New for 1510 - consult the PARAM_ALIAS field to see if we've been
+ // supplied an alias. Only check if we don't find it initially.
+ // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
+ // And also new - add parameter to turn off checking all together if we find we're blocking orders we
+ // shouldn't
+ boolean haveEnvironmentParameters = false;
+ boolean checkRequiredParameters = true;
+ try {
+ String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
+ .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
+ if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
+ checkRequiredParameters = false;
+ LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
+ + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
+ }
+ } catch (Exception e) {
+ // No problem - default is true
+ LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
+ }
+ // 1604 - Add enhanced environment & parameter checking
+ // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
+ // Part 2: only submit to openstack the parameters in the envt that are in the heat template
+ // Note this also removes any comments
+ MsoHeatEnvironmentEntry mhee = null;
+ if (heatEnvironmentString != null && heatEnvironmentString.toLowerCase ().contains ("parameters:")) {
+ LOGGER.debug("Enhanced environment checking enabled - 1604");
+ haveEnvironmentParameters = true;
+ StringBuilder sb = new StringBuilder(heatEnvironmentString);
+ //LOGGER.debug("About to create MHEE with " + sb);
+ mhee = new MsoHeatEnvironmentEntry(sb);
+ StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
+ for (HeatTemplateParam parm : heatTemplate.getParameters()) {
+ sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
+ }
+ if (!mhee.isValid()) {
+ sb2.append("Environment says it's not valid! " + mhee.getErrorString());
+ } else {
+ sb2.append("\nEnvironment:");
+ sb2.append(mhee.toFullString());
+ }
+ LOGGER.debug(sb2.toString());
+ } else {
+ LOGGER.debug("NO ENVIRONMENT for this entry");
+ }
+
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ LOGGER.debug ("Parameter:'" + parm.getParamName ()
+ + "', isRequired="
+ + parm.isRequired ()
+ + ", alias="
+ + parm.getParamAlias ());
+ if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
+ if (inputs.containsKey (parm.getParamAlias ())) {
+ // They've submitted using an alias name. Remove that from inputs, and add back using real name.
+ String realParamName = parm.getParamName ();
+ String alias = parm.getParamAlias ();
+ String value = inputs.get (alias);
+ LOGGER.debug ("*Found an Alias: paramName=" + realParamName
+ + ",alias="
+ + alias
+ + ",value="
+ + value);
+ inputs.remove (alias);
+ inputs.put (realParamName, value);
+ LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
+ }
+ // enhanced - check if it's in the Environment (note: that method
+ else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
+
+ LOGGER.debug ("Required parameter " + parm.getParamName ()
+ + " appears to be in environment - do not count as missing");
+ }
+ else {
+ LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
+ if (missingParams == null) {
+ missingParams = parm.getParamName ();
+ } else {
+ missingParams += "," + parm.getParamName ();
+ }
+ }
+ }
+ paramList.add (parm.getParamName ());
+ }
+ if (missingParams != null) {
+ // Problem - missing one or more required parameters
+ if (checkRequiredParameters) {
+ String error = "Update VNF: Missing Required inputs: " + missingParams;
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Missing Required inputs");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
+ }
+ } else {
+ LOGGER.debug ("No missing parameters found - ok to proceed");
+ }
+
+ // Here - modify heatEnvironmentString
+ StringBuilder parsedEnvironmentString = null;
+ String newEnvironmentString = null;
+ if (mhee != null) {
+ LOGGER.debug("Environment before:\n" + heatEnvironmentString);
+ parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
+ LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
+ newEnvironmentString = parsedEnvironmentString.toString();
+ }
+
+ // Remove any extraneous parameters (don't throw an error)
+ if (inputs != null) {
+ List <String> extraParams = new ArrayList <String> ();
+ extraParams.addAll (inputs.keySet ());
+ // This is not a valid parameter for this template
+ extraParams.removeAll (paramList);
+ if (!extraParams.isEmpty ()) {
+ LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "VNF Extra params");
+ inputs.keySet ().removeAll (extraParams);
+ }
+ }
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ // Have the tenant. Now deploy the stack itself
+ // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
+ // because we already checked for those.
+ long updateStackStarttime = System.currentTimeMillis ();
+ try {
+ heatStack = heatU.updateStack (cloudSiteId,
+ tenantId,
+ vnfName,
+ template,
+ copyStringInputs (inputs),
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ newEnvironmentString,
+ //heatEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects);
+ LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", vnfName);
+ } catch (MsoException me) {
+ me.addContext ("UpdateVNF");
+ String error = "Update VNF " + vnfType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", vnfName);
+ LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, vnfType, cloudSiteId, tenantId, "OpenStack", "updateStack", MsoLogger.ErrorCode.DataError, "Exception - updateStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ }
+
+ // Reach this point if updateStack is successful.
+ // Populate remaining rollback info and response parameters.
+ vnfRollback.setVnfId (heatStack.getCanonicalName ());
+ vnfRollback.setVnfCreated (true);
+
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vnfRollback;
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully update VNF");
+ return;
+ }
+
+ /**
+ * This is the "Query VNF" web service implementation.
+ * It will look up a VNF by name or ID in the specified cloud and tenant.
+ *
+ * The method returns an indicator that the VNF exists, its Openstack internal
+ * ID, its status, and the set of outputs (from when the stack was created).
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to query
+ * @param tenantId Openstack tenant identifier
+ * @param vnfName VNF Name or Openstack ID
+ * @param msoRequest Request tracking information for logs
+ * @param vnfExists Flag reporting the result of the query
+ * @param vnfId Holder for output VNF Openstack ID
+ * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
+ */
+ @Override
+ public void queryVnf (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest,
+ Holder <Boolean> vnfExists,
+ Holder <String> vnfId,
+ Holder <VnfStatus> status,
+ Holder <Map <String, String>> outputs) throws VnfException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("QueryVnf");
+ LOGGER.debug ("Querying VNF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ StackInfo heatStack = null;
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, vnfName);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
+ } catch (MsoException me) {
+ me.addContext ("QueryVNF");
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ String error = "Query VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryVNF", MsoLogger.ErrorCode.DataError, "Exception - queryStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ // Populate the outputs based on the returned Stack information
+ //
+ if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
+ // Not Found
+ vnfExists.value = Boolean.FALSE;
+ status.value = VnfStatus.NOTFOUND;
+ vnfId.value = null;
+ outputs.value = new HashMap <String, String> (); // Return as an empty map
+
+ LOGGER.debug ("VNF " + vnfName + " not found");
+ } else {
+ vnfExists.value = Boolean.TRUE;
+ status.value = stackStatusToVnfStatus (heatStack.getStatus ());
+ vnfId.value = heatStack.getCanonicalName ();
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+
+ LOGGER.debug ("VNF " + vnfName + " found, ID = " + vnfId.value);
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query VNF");
+ return;
+ }
+
+ /**
+ * This is the "Delete VNF" web service implementation.
+ * It will delete a VNF by name or ID in the specified cloud and tenant.
+ *
+ * The method has no outputs.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to delete
+ * @param tenantId Openstack tenant identifier
+ * @param vnfName VNF Name or Openstack ID
+ * @param msoRequest Request tracking information for logs
+ */
+ @Override
+ public void deleteVnf (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest) throws VnfException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteVnf");
+ LOGGER.debug ("Deleting VNF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
+ // The possible outcomes of deleteStack are a StackInfo object with status
+ // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
+ // could be thrown.
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", vnfName);
+ } catch (MsoException me) {
+ me.addContext ("DeleteVNF");
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ String error = "Delete VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", vnfName);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "DeleteVNF", MsoLogger.ErrorCode.DataError, "Exception - DeleteVNF", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ // On success, nothing is returned.
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete VNF");
+ return;
+ }
+
+ /**
+ * This web service endpoint will rollback a previous Create VNF operation.
+ * A rollback object is returned to the client in a successful creation
+ * response. The client can pass that object as-is back to the rollbackVnf
+ * operation to undo the creation.
+ */
+ @Override
+ public void rollbackVnf (VnfRollback rollback) throws VnfException {
+ long startTime = System.currentTimeMillis ();
+ MsoLogger.setServiceName ("RollbackVnf");
+ // rollback may be null (e.g. if stack already existed when Create was called)
+ if (rollback == null) {
+ LOGGER.info (MessageEnum.RA_ROLLBACK_NULL, "OpenStack", "rollbackVnf");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "Rollback request content is null");
+ return;
+ }
+
+ // Get the elements of the VnfRollback object for easier access
+ String cloudSiteId = rollback.getCloudSiteId ();
+ String tenantId = rollback.getTenantId ();
+ String vnfId = rollback.getVnfId ();
+
+ MsoLogger.setLogContext (rollback.getMsoRequest());
+
+ LOGGER.debug ("Rolling Back VNF " + vnfId + " in " + cloudSiteId + "/" + tenantId);
+
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
+ // The possible outcomes of deleteStack are a StackInfo object with status
+ // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
+ // could be thrown.
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ heat.deleteStack (tenantId, cloudSiteId, vnfId, true);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
+ } catch (MsoException me) {
+ // Failed to rollback the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("RollbackVNF");
+ String error = "Rollback VNF: " + vnfId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfId, cloudSiteId, tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError, "Exception - DeleteStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully roll back VNF");
+ return;
+ }
+
+ private VnfStatus stackStatusToVnfStatus (HeatStatus stackStatus) {
+ switch (stackStatus) {
+ case CREATED:
+ return VnfStatus.ACTIVE;
+ case UPDATED:
+ return VnfStatus.ACTIVE;
+ case FAILED:
+ return VnfStatus.FAILED;
+ default:
+ return VnfStatus.UNKNOWN;
+ }
+ }
+
+ private Map <String, String> copyStringOutputs (Map <String, Object> stackOutputs) {
+ Map <String, String> stringOutputs = new HashMap <String, String> ();
+ for (String key : stackOutputs.keySet ()) {
+ if (stackOutputs.get (key) instanceof String) {
+ stringOutputs.put (key, (String) stackOutputs.get (key));
+ }
+ }
+ return stringOutputs;
+ }
+
+ private Map <String, Object> copyStringInputs (Map <String, String> stringInputs) {
+ return new HashMap <String, Object> (stringInputs);
+ }
+
+ /*
+ * a helper method to make sure that any resource_registry entry of the format
+ * "xx::xx" : yyy.yaml (or yyy.template)
+ * has the file name prepended with "file:///"
+ * Return a String of the environment body that's passed in.
+ * Have to be careful not to mess up the original formatting.
+ */
+ private String parseEnvironment (String environment) {
+ StringBuilder sb = new StringBuilder ();
+ try (Scanner scanner = new Scanner (environment)) {
+ scanner.useDelimiter ("\n");
+ String line = null;
+ Pattern resource = Pattern.compile ("\\s*\"\\w+::\\S+\"\\s*:");
+ LOGGER.debug ("regex pattern for finding a resource_registry: \\s*\"\\w+::\\S+\"\\s*:");
+ while (scanner.hasNextLine ()) {
+ line = scanner.nextLine ();
+ if (line.toLowerCase ().contains ("resource_registry")) {
+ sb.append (line + "\n");
+ boolean done = false;
+ // basically keep scanning until EOF or parameters: section
+ while (scanner.hasNextLine () && !done) {
+ line = scanner.nextLine ();
+ if ("parameters:".equalsIgnoreCase (line.trim ())) {
+ sb.append (line + "\n");
+ done = true;
+ break;
+ }
+ Matcher m = resource.matcher (line);
+ if (m.find ()) {
+ sb.append (m.group ());
+ String secondPart = line.substring (m.end ()).trim ();
+ String output = secondPart;
+ if (secondPart.endsWith (".yaml")
+ || secondPart.endsWith (".template") && !secondPart.startsWith ("file:///")) {
+ output = "file:///" + secondPart;
+ LOGGER.debug ("changed " + secondPart + " to " + output);
+ } // don't do anything if it's not .yaml or .template
+ sb.append (" " + output + "\n");
+ } else {
+ sb.append (line + "\n");
+ }
+ }
+ } else {
+ sb.append (line + "\n");
+ continue;
+ }
+ }
+ scanner.close ();
+ } catch (Exception e) {
+ LOGGER.debug ("Error trying to scan " + environment, e);
+ return environment;
+ }
+ return sb.toString ();
+ }
+
+ /*
+ * helper class to add file:/// to the Provider_Resource_File entry in HEAT_NESTED_TEMPLATE
+ * and the File_Name entry in HEAT_FILES if the file:/// part is missing.
+ */
+ private String enforceFilePrefix (String string) {
+ if (string.trim ().startsWith ("file:///")) {
+ // just leave it
+ return string;
+ }
+ if (string.trim ().endsWith (".yaml") || string.trim ().endsWith (".template")) {
+ // only .yaml or .template are valid anyway - otherwise don't bother
+ return "file:///" + string.trim ();
+ } else {
+ LOGGER.debug (string + " is NOT a .yaml or .template file");
+ }
+ return string;
+ }
+
+ private void sendMapToDebug(Map<String, String> inputs) {
+ int i = 0;
+ StringBuilder sb = new StringBuilder("inputs:");
+ if (inputs == null) {
+ sb.append("\tNULL");
+ }
+ else if (inputs.size() < 1) {
+ sb.append("\tEMPTY");
+ } else {
+ for (String str : inputs.keySet()) {
+ sb.append("\titem " + i++ + ": " + str + "=" + inputs.get(str));
+ }
+ }
+ LOGGER.debug(sb.toString());
+ return;
+ }
+
+ public void createVfModule(String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ String baseVfHeatStackId,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ String vfModuleName = vnfName;
+ String vfModuleType = vnfType;
+ String vfVersion = vnfVersion;
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateVfModule");
+ String requestTypeString = "";
+ if (requestType != null && !requestType.equals("")) {
+ requestTypeString = requestType;
+ }
+ String nestedStackId = null;
+ if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
+ if (!volumeGroupHeatStackId.equalsIgnoreCase("null")) {
+ nestedStackId = volumeGroupHeatStackId;
+ }
+ }
+ String nestedBaseStackId = null;
+ if (baseVfHeatStackId != null && !baseVfHeatStackId.equals("")) {
+ if (!baseVfHeatStackId.equalsIgnoreCase("null")) {
+ nestedBaseStackId = baseVfHeatStackId;
+ }
+ }
+
+ if (inputs == null) {
+ // Create an empty set of inputs
+ inputs = new HashMap<String,String>();
+ LOGGER.debug("inputs == null - setting to empty");
+ } else {
+ this.sendMapToDebug(inputs);
+ }
+ //This method will also handle doing things the "old" way - i.e., just orchestrate a VNF
+ boolean oldWay = false;
+ if (requestTypeString.startsWith("X")) {
+ oldWay = true;
+ LOGGER.debug("orchestrating a VNF - *NOT* a module!");
+ requestTypeString = requestTypeString.substring(1);
+ }
+
+ // 1607 - let's parse out the request type we're being sent
+ boolean isBaseRequest = false;
+ boolean isVolumeRequest = false;
+ if (requestTypeString.startsWith("VOLUME")) {
+ isVolumeRequest = true;
+ }
+
+ LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Build a default rollback object (no actions performed)
+ VnfRollback vfRollback = new VnfRollback();
+ vfRollback.setCloudSiteId(cloudSiteId);
+ vfRollback.setTenantId(tenantId);
+ vfRollback.setMsoRequest(msoRequest);
+ vfRollback.setRequestType(requestTypeString);
+ vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
+ vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
+ vfRollback.setIsBase(isBaseRequest);
+
+ // First, look up to see if the VF already exists.
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ StackInfo heatStack = null;
+ long subStartTime1 = System.currentTimeMillis ();
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
+ } catch (MsoException me) {
+ String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - queryStack", me);
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ // New with 1607 - more precise handling/messaging if the stack already exists
+ if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
+ // INIT, CREATED, NOTFOUND, FAILED, BUILDING, DELETING, UNKNOWN, UPDATING, UPDATED
+ HeatStatus status = heatStack.getStatus();
+ if (status == HeatStatus.INIT || status == HeatStatus.BUILDING || status == HeatStatus.DELETING || status == HeatStatus.UPDATING) {
+ // fail - it's in progress - return meaningful error
+ String error = "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; please wait for it to complete, or fix manually.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
+ }
+ if (status == HeatStatus.FAILED) {
+ // fail - it exists and is in a FAILED state
+ String error = "Create VF: Stack " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists and is in FAILED state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
+ }
+ if (status == HeatStatus.UNKNOWN || status == HeatStatus.UPDATED) {
+ // fail - it exists and is in a FAILED state
+ String error = "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists and is in UPDATED or UNKNOWN state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
+ }
+ if (status == HeatStatus.CREATED) {
+ // fail - it exists
+ if (failIfExists != null && failIfExists) {
+ String error = "Create VF: Stack " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
+ } else {
+ LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
+ // Populate the outputs from the existing stack.
+ vnfId.value = heatStack.getCanonicalName ();
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vfRollback; // Default rollback - no updates performed
+ }
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module");
+ return;
+
+ }
+
+ // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf
+ StackInfo nestedHeatStack = null;
+ long subStartTime2 = System.currentTimeMillis ();
+ if (nestedStackId != null) {
+ try {
+ LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
+ nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule");
+ String error = "Create VFModule: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.BusinessProcesssError, "MsoException trying to query nested stack", me);
+ LOGGER.debug("ERROR trying to query nested stack= " + error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
+ String error = "Create VFModule: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "queryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached heatStack ID DOES NOT EXIST");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ LOGGER.debug(error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found nested volume heat stack - copying values to inputs");
+ this.sendMapToDebug(inputs);
+ heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
+ this.sendMapToDebug(inputs);
+ }
+ }
+
+ // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests
+ StackInfo nestedBaseHeatStack = null;
+ long subStartTime3 = System.currentTimeMillis ();
+ if (nestedBaseStackId != null) {
+ try {
+ LOGGER.debug("Querying for nestedBaseStackId = " + nestedBaseStackId);
+ nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
+ LOGGER.recordMetricEvent (subStartTime3, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule");
+ String error = "Create VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (subStartTime3, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "MsoException trying to query nested base stack", me);
+ LOGGER.debug("ERROR trying to query nested base stack= " + error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
+ String error = "Create VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached base heatStack ID DOES NOT EXIST");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ LOGGER.debug(error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found nested base heat stack - copying values to inputs");
+ this.sendMapToDebug(inputs);
+ heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
+ this.sendMapToDebug(inputs);
+ }
+ }
+
+ // Ready to deploy the new VNF
+
+ try (CatalogDatabase db = new CatalogDatabase()) {
+ // Retrieve the VF
+ VfModule vf = null;
+ VnfResource vnfResource = null;
+ LOGGER.debug("version: " + vfVersion);
+ if (!oldWay) {
+ // Need to handle old and new schema methods - for a time. Try the new way first.
+ if (vfVersion != null && !vfVersion.isEmpty()) {
+ vf = db.getVfModuleType(vfModuleType, vfVersion);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " and version=" + vfVersion + " in the TYPE column - will try in MODEL_NAME");
+ vf = db.getVfModuleModelName(vfModuleType, vfVersion);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " and version=" + vfVersion + " in the MODEL_NAME field either - ERROR");
+ }
+ }
+ } else {
+ vf = db.getVfModuleType(vfModuleType);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " in the TYPE column - will try in MODEL_NAME");
+ vf = db.getVfModuleModelName(vfModuleType);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " in the MODEL_NAME field either - ERROR");
+ }
+ }
+ }
+ if (vf == null) {
+ String error = "Create VF Module: Unable to determine specific VF Module Type: "
+ + vfModuleType;
+ if (vfVersion != null && !vfVersion.isEmpty()) {
+ error += " with version = " + vfVersion;
+ }
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module Type", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VF Module: Unable to determine specific VF Module Type");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug("Got VF module definition from Catalog: "
+ + vf.toString());
+
+ if (vf.isBase()) {
+ isBaseRequest = true;
+ LOGGER.debug("This is a BASE VF request!");
+ } else {
+ LOGGER.debug("This is *not* a BASE VF request!");
+ if (!isVolumeRequest && nestedBaseStackId == null) {
+ LOGGER.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
+ }
+ }
+ } else {
+ if (vfVersion != null && !vfVersion.isEmpty()) {
+ vnfResource = db.getVnfResource(vnfType, vnfVersion);
+ } else {
+ vnfResource = db.getVnfResource(vnfType);
+ }
+ if (vnfResource == null) {
+ String error = "Create VNF: Unknown VNF Type: " + vnfType;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type",
+ vnfType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VNF: Unknown VNF Type");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug("Got VNF module definition from Catalog: "
+ + vnfResource.toString());
+ }
+ // By here - we have either a vf or vnfResource
+
+ //1607 - Add version check
+ // First - see if it's in the VnfResource record
+ // if we have a vf Module - then we have to query to get the VnfResource record.
+ if (!oldWay) {
+ if (vf.getVnfResourceId() != null) {
+ int vnfResourceId = vf.getVnfResourceId();
+ vnfResource = db.getVnfResourceById(vnfResourceId);
+ if (vnfResource == null) {
+ LOGGER.debug("Unable to find vnfResource at " + vnfResourceId + " will not error for now...");
+ }
+ }
+ }
+ String minVersionVnf = null;
+ String maxVersionVnf = null;
+ if (vnfResource != null) {
+ try {
+ minVersionVnf = vnfResource.getAicVersionMin();
+ maxVersionVnf = vnfResource.getAicVersionMax();
+ } catch (Exception e) {
+ LOGGER.debug("Unable to pull min/max version for this VNF Resource entry");
+ minVersionVnf = null;
+ maxVersionVnf = null;
+ }
+ if (minVersionVnf != null && minVersionVnf.equals("")) {
+ minVersionVnf = null;
+ }
+ if (maxVersionVnf != null && maxVersionVnf.equals("")) {
+ maxVersionVnf = null;
+ }
+ }
+ if (minVersionVnf != null && maxVersionVnf != null) {
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+ CloudSite cloudSite = null;
+ String aicVersion = "";
+ if (this.cloudConfig == null) {
+ this.cloudConfig = this.cloudConfigFactory.getCloudConfig();
+ }
+ // double check
+ if (this.cloudConfig != null) {
+ cloudSite = this.cloudConfig.getCloudSite(cloudSiteId);
+ if (cloudSite != null) {
+ aicV.setVersion(cloudSite.getAic_version());
+ if ((aicV.isMoreRecentThan(minVersionVnf) || aicV.isTheSameVersion(minVersionVnf)) // aic >= min
+ && (aicV.isTheSameVersion(maxVersionVnf) || !(aicV.isMoreRecentThan(maxVersionVnf)))) { //aic <= max
+ LOGGER.debug("VNF Resource " + vnfResource.getVnfType() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " supported on Cloud: " + cloudSite.getId() + " with AIC_Version:" + cloudSite.getAic_version());
+ } else {
+ // ERROR
+ String error = "VNF Resource type: " + vnfResource.getVnfType() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: " + cloudSite.getId() + " with AIC_Version:" + cloudSite.getAic_version();
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
+ LOGGER.debug(error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ } // let this error out downstream to avoid introducing uncertainty at this stage
+ } else {
+ LOGGER.debug("cloudConfig is NULL - cannot check cloud site version");
+ }
+
+ } else {
+ LOGGER.debug("AIC Version not set in VNF_Resource - this is expected thru 1607 - do not error here - not checked.");
+ }
+ // End Version check 1607
+
+ // with VF_MODULE - we have both the non-vol and vol template/envs in that object
+ // with VNF_RESOURCE - we use the old methods.
+ Integer heatTemplateId = null;
+ Integer heatEnvtId = null;
+
+ if (!oldWay) {
+ if (isVolumeRequest) {
+ heatTemplateId = vf.getVolTemplateId();
+ heatEnvtId = vf.getVolEnvironmentId();
+ } else {
+ heatTemplateId = vf.getTemplateId();
+ heatEnvtId = vf.getEnvironmentId();
+ }
+ } else {
+ if (isVolumeRequest) {
+ VnfComponent vnfComponent = null;
+ vnfComponent = db.getVnfComponent(vnfResource.getId(), "VOLUME");
+ if (vnfComponent == null) {
+ String error = "Create VNF: Cannot find VNF Component entry for: " + vnfType + ", type = VOLUME";
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "getVnfComponent", MsoLogger.ErrorCode.DataError, "Create VNF: Cannot find VNF Component entry");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ heatTemplateId = vnfComponent.getHeatTemplateId();
+ heatEnvtId = vnfComponent.getHeatEnvironmentId();
+ }
+ } else {
+ heatTemplateId = vnfResource.getTemplateId();
+ heatEnvtId = vnfResource.getEnvironmentId();
+ }
+ }
+ // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
+ HeatTemplate heatTemplate = null;
+ if (heatTemplateId == null) {
+ String error = "Create: No Heat Template ID defined in catalog database for " + vnfType + ", reqType=" + requestTypeString;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vnfType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create: No Heat Template ID defined in catalog database");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException(error, MsoExceptionCategory.INTERNAL);
+ } else {
+ heatTemplate = db.getHeatTemplate(heatTemplateId);
+ }
+ if (heatTemplate == null) {
+ String error = "Create VF/VNF: no entry found for heat template ID = " + heatTemplateId;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "Heat Template ID",
+ String.valueOf(heatTemplateId), "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create VF/VNF: no entry found for heat template ID = " + heatTemplateId);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException(error, MsoExceptionCategory.INTERNAL);
+ }
+ LOGGER.debug("Got HEAT Template from DB");
+
+ HeatEnvironment heatEnvironment = null;
+ String heatEnvironmentString = null;
+
+ if (heatEnvtId != null && heatEnvtId != 0) {
+ LOGGER.debug ("about to call getHeatEnvironment with :" + heatEnvtId + ":");
+ heatEnvironment = db.getHeatEnvironment (heatEnvtId);
+ if (heatEnvironment == null) {
+ String error = "Create VFModule: undefined Heat Environment. VFModule=" + vfModuleType
+ + ", Environment ID="
+ + heatEnvtId;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(heatEnvtId), "OpenStack", "getHeatEnvironment", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: undefined Heat Environment");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ } else {
+ LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
+ heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
+ LOGGER.debug ("after parsing: " + heatEnvironmentString);
+ }
+ } else {
+ LOGGER.debug ("no environment parameter found for this Type " + vfModuleType);
+ }
+
+ // 1510 - Add the files: for nested templates *if* there are any
+ LOGGER.debug ("In MsoVnfAdapterImpl, createVfModule about to call db.getNestedTemplates avec templateId="
+ + heatTemplate.getId ());
+ Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
+ Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
+ if (nestedTemplates != null) {
+ // for debugging print them out
+ LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
+ for (String providerResourceFile : nestedTemplates.keySet ()) {
+ String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
+ String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
+ LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
+ nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
+ }
+ } else {
+ LOGGER.debug ("No nested templates found - nothing to do here");
+ nestedTemplatesChecked = null; // just to make sure
+ }
+
+ // 1510 - Also add the files: for any get_files associated with this vnf_resource_id
+ // *if* there are any
+ Map<String, HeatFiles> heatFiles = null;
+ Map<String, Object> heatFilesObjects = new HashMap<String, Object>();
+
+ // Add ability to turn on adding get_files with volume requests (by property).
+ boolean addGetFilesOnVolumeReq = false;
+ try {
+ String propertyString = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_VNF_ADAPTER).getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, null);
+ if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
+ addGetFilesOnVolumeReq = true;
+ LOGGER.debug("AddGetFilesOnVolumeReq - setting to true! " + propertyString);
+ }
+ } catch (Exception e) {
+ LOGGER.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ + " - default to false", e);
+ }
+
+ if (!isVolumeRequest || addGetFilesOnVolumeReq) {
+ if (oldWay) {
+ LOGGER.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFiles avec vnfResourceId="
+ + vnfResource.getId());
+ heatFiles = db.getHeatFiles(vnfResource.getId());
+ } else {
+ // 1607 - now use VF_MODULE_TO_HEAT_FILES table
+ LOGGER.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
+ + vf.getId());
+ heatFiles = db
+ .getHeatFilesForVfModule(vf.getId());
+ }
+ if (heatFiles != null) {
+ // add these to stack - to be done in createStack
+ // here, we will map them to Map<String, Object> from
+ // Map<String, HeatFiles>
+ // this will match the nested templates format
+ LOGGER.debug("Contents of heatFiles - to be added to files: on stack:");
+
+ for (String heatFileName : heatFiles.keySet()) {
+ if (heatFileName.startsWith("_ERROR|")) {
+ // This means there was an invalid entry in VF_MODULE_TO_HEAT_FILES table - the heat file it pointed to could not be found.
+ String heatFileId = heatFileName.substring(heatFileName.lastIndexOf("|")+1);
+ String error = "Create: No HEAT_FILES entry in catalog database for " + vfModuleType + " at HEAT_FILES index=" + heatFileId;
+ LOGGER.debug(error);
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "HEAT_FILES entry not found at " + heatFileId, vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "HEAT_FILES entry not found");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ }
+ String heatFileBody = heatFiles.get(heatFileName)
+ .getFileBody();
+ String heatFileNameChecked = heatFileName;
+ LOGGER.debug(heatFileNameChecked + " -> "
+ + heatFileBody);
+ heatFilesObjects.put(heatFileNameChecked, heatFileBody);
+ }
+ } else {
+ LOGGER.debug("No heat files found -nothing to do here");
+ heatFilesObjects = null;
+ }
+ } else {
+ LOGGER.debug("Volume request - DO NOT CHECK for HEAT_FILES");
+ }
+
+ // Check that required parameters have been supplied
+ String missingParams = null;
+ List <String> paramList = new ArrayList <String> ();
+
+ // New for 1510 - consult the PARAM_ALIAS field to see if we've been
+ // supplied an alias. Only check if we don't find it initially.
+ // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
+ // And also new - add parameter to turn off checking all together if we find we're blocking orders we
+ // shouldn't
+ boolean haveEnvironmentParameters = false;
+ boolean checkRequiredParameters = true;
+ try {
+ String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
+ .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
+ if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
+ checkRequiredParameters = false;
+ LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
+ + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
+ }
+ } catch (Exception e) {
+ // No problem - default is true
+ LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
+ }
+ // 1604 - Add enhanced environment & parameter checking
+ // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
+ // Part 2: only submit to openstack the parameters in the envt that are in the heat template
+ // Note this also removes any comments
+ MsoHeatEnvironmentEntry mhee = null;
+ if (heatEnvironmentString != null && heatEnvironmentString.contains ("parameters:")) {
+ //LOGGER.debug ("Have an Environment argument with a parameters: section - will bypass checking for valid params - but will still check for aliases");
+ LOGGER.debug("Enhanced environment checking enabled - 1604");
+ haveEnvironmentParameters = true;
+ StringBuilder sb = new StringBuilder(heatEnvironmentString);
+ //LOGGER.debug("About to create MHEE with " + sb);
+ mhee = new MsoHeatEnvironmentEntry(sb);
+ StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
+ for (HeatTemplateParam parm : heatTemplate.getParameters()) {
+ sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
+ }
+ if (!mhee.isValid()) {
+ sb2.append("Environment says it's not valid! " + mhee.getErrorString());
+ } else {
+ sb2.append("\nEnvironment:");
+ sb2.append(mhee.toFullString());
+ }
+ LOGGER.debug(sb2.toString());
+ } else {
+ LOGGER.debug("NO ENVIRONMENT for this entry");
+ }
+ // This is kind of a mess. inputs is a Map<String, String> --
+ // if one of the parameters is json - we need to pass String, JsonNode -
+ // so we will store off the parameters that are json in its own HashMap
+ // if there are any json params - then we convert inputs to a Map<String, Object>
+ // and pass that to createStack
+ HashMap<String, JsonNode> jsonParams = new HashMap<String, JsonNode>();
+ boolean hasJson = false;
+
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ LOGGER.debug ("Parameter:'" + parm.getParamName ()
+ + "', isRequired="
+ + parm.isRequired ()
+ + ", alias="
+ + parm.getParamAlias ());
+ // New 1607 - support json type
+ String parameterType = parm.getParamType();
+ if (parameterType == null || parameterType.trim().equals("")) {
+ parameterType = "String";
+ }
+ JsonNode jsonNode = null;
+ if (parameterType.equalsIgnoreCase("json") && inputs != null) {
+ if (inputs.containsKey(parm.getParamName()) ) {
+ hasJson = true;
+ String jsonString = null;
+ try {
+ jsonString = inputs.get(parm.getParamName());
+ jsonNode = new ObjectMapper().readTree(jsonString);
+ } catch (JsonParseException jpe) {
+ //TODO - what to do here?
+ //for now - send the error to debug, but just leave it as a String
+ String errorMessage = jpe.getMessage();
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
+ hasJson = false;
+ jsonNode = null;
+ }
+ if (jsonNode != null) {
+ jsonParams.put(parm.getParamName(), jsonNode);
+ }
+ } else if (inputs.containsKey(parm.getParamAlias())) {
+ hasJson = true;
+ String jsonString = null;
+ try {
+ jsonString = inputs.get(parm.getParamAlias());
+ jsonNode = new ObjectMapper().readTree(jsonString);
+ } catch (JsonParseException jpe) {
+ //TODO - what to do here?
+ //for now - send the error to debug, but just leave it as a String
+ String errorMessage = jpe.getMessage();
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
+ hasJson = false;
+ jsonNode = null;
+ }
+ if (jsonNode != null) {
+ // Notice here - we add it to the jsonParams hashMap with the actual name -
+ // then manipulate the inputs so when we check for aliases below - it will not
+ // get flagged.
+ jsonParams.put(parm.getParamName(), jsonNode);
+ inputs.remove(parm.getParamAlias());
+ inputs.put(parm.getParamName(), jsonString);
+ }
+ } //TODO add a check for the parameter in the env file
+ }
+ if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
+ // Check if they have an alias
+ LOGGER.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...");
+ if (inputs.containsKey (parm.getParamAlias ())) {
+ // They've submitted using an alias name. Remove that from inputs, and add back using real name.
+ String realParamName = parm.getParamName ();
+ String alias = parm.getParamAlias ();
+ String value = inputs.get (alias);
+ LOGGER.debug ("*Found an Alias: paramName=" + realParamName
+ + ",alias="
+ + alias
+ + ",value="
+ + value);
+ inputs.remove (alias);
+ inputs.put (realParamName, value);
+ LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
+ }
+ // enhanced - check if it's in the Environment (note: that method
+ else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
+
+ LOGGER.debug ("Required parameter " + parm.getParamName ()
+ + " appears to be in environment - do not count as missing");
+ } else {
+ LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
+ if (missingParams == null) {
+ missingParams = parm.getParamName ();
+ } else {
+ missingParams += "," + parm.getParamName ();
+ }
+ }
+ }
+ paramList.add (parm.getParamName ());
+ }
+ if (missingParams != null) {
+ if (checkRequiredParameters) {
+ // Problem - missing one or more required parameters
+ String error = "Create VFModule: Missing Required inputs: " + missingParams;
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VFModule: Missing Required inputs");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
+ }
+ } else {
+ LOGGER.debug ("No missing parameters found - ok to proceed");
+ }
+
+ // Here - modify heatEnvironmentString
+ StringBuilder parsedEnvironmentString = null;
+ String newEnvironmentString = null;
+ if (mhee != null) {
+ LOGGER.debug("Environment before:\n" + heatEnvironmentString);
+ parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
+ LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
+ newEnvironmentString = parsedEnvironmentString.toString();
+ }
+
+ // Remove any extraneous parameters (don't throw an error)
+ if (inputs != null) {
+ List <String> extraParams = new ArrayList <String> ();
+ extraParams.addAll (inputs.keySet ());
+ extraParams.removeAll (paramList);
+ if (!extraParams.isEmpty ()) {
+ LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "", MsoLogger.ErrorCode.DataError, "Extra params");
+ inputs.keySet ().removeAll (extraParams);
+ }
+ }
+ // 1607 - when we get here - we have clean inputs. Check if we have
+ Map<String, Object> inputsTwo = null;
+ if (hasJson && jsonParams.size() > 0) {
+ inputsTwo = new HashMap<String, Object>();
+ for (String keyParamName : inputs.keySet()) {
+ if (jsonParams.containsKey(keyParamName)) {
+ inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
+ } else {
+ inputsTwo.put(keyParamName, inputs.get(keyParamName));
+ }
+ }
+ }
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ // Have the tenant. Now deploy the stack itself
+ // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
+ // because we already checked for those.
+ long createStackStarttime = System.currentTimeMillis ();
+ try {
+ // heatStack = heat.createStack(cloudSiteId, tenantId, vnfName, template, inputs, true,
+ // heatTemplate.getTimeoutMinutes());
+ if (backout == null) {
+ backout = true;
+ }
+ if (heat != null) {
+ LOGGER.debug("heat is not null!!");
+ }
+
+ if (!hasJson) {
+ heatStack = heat.createStack (cloudSiteId,
+ tenantId,
+ vfModuleName,
+ template,
+ inputs,
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ newEnvironmentString,
+ //heatEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects,
+ backout.booleanValue());
+ LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "CreateStack", vfModuleName);
+ } else {
+ heatStack = heat.createStack (cloudSiteId,
+ tenantId,
+ vfModuleName,
+ template,
+ inputsTwo,
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ newEnvironmentString,
+ //heatEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects,
+ backout.booleanValue());
+
+ }
+ LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "CreateStack", vfModuleName);
+ } catch (MsoException me) {
+ me.addContext ("CreateVFModule");
+ String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "CreateStack", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "MsoException - createStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ } catch (NullPointerException npe) {
+ String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
+ LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "CreateStack", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "NullPointerException - createStack", npe);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ LOGGER.debug("NULL POINTER EXCEPTION at heat.createStack");
+ //npe.addContext ("CreateVNF");
+ throw new VnfException ("NullPointerException during heat.createStack");
+ } catch (Exception e) {
+ LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating stack with OpenStack", "OpenStack", "CreateStack", vfModuleName);
+ LOGGER.debug("unhandled exception at heat.createStack");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating stack with OpenStack");
+ throw new VnfException("Exception during heat.createStack! " + e.getMessage());
+ }
+ } catch (Exception e) {
+ LOGGER.debug("unhandled exception in create VF");
+ throw new VnfException("Exception during create VF " + e.getMessage());
+
+ }
+
+ // Reach this point if createStack is successful.
+ // Populate remaining rollback info and response parameters.
+ vfRollback.setVnfId (heatStack.getCanonicalName ());
+ vfRollback.setVnfCreated (true);
+
+ vnfId.value = heatStack.getCanonicalName ();
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vfRollback;
+
+ LOGGER.debug ("VF Module " + vfModuleName + " successfully created");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module");
+ return;
+
+
+ }
+
+ public void deleteVfModule (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest) throws VnfException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteVf");
+ LOGGER.debug ("Deleting VF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
+ // The possible outcomes of deleteStack are a StackInfo object with status
+ // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
+ // could be thrown.
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", vnfName);
+ } catch (MsoException me) {
+ me.addContext ("DeleteVNF");
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", vnfName);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError, "Exception - deleteStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ // On success, nothing is returned.
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete VF");
+ return;
+ }
+
+ @Override
+ public void updateVfModule (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ String baseVfHeatStackId,
+ String vfModuleStackId,
+ Map <String, String> inputs,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ String vfModuleName = vnfName;
+ String vfModuleType = vnfType;
+ String vfVersion = vnfVersion;
+ String methodName = "updateVfModule";
+ MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
+ String serviceName = VNF_ADAPTER_SERVICE_NAME + methodName;
+ MsoLogger.setServiceName (serviceName);
+
+ String requestTypeString = "";
+ if (requestType != null && !requestType.equals("")) {
+ requestTypeString = requestType;
+ }
+ String nestedStackId = null;
+ if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
+ if (!volumeGroupHeatStackId.equalsIgnoreCase("null")) {
+ nestedStackId = volumeGroupHeatStackId;
+ }
+ }
+ String nestedBaseStackId = null;
+ if (baseVfHeatStackId != null && !baseVfHeatStackId.equals("")) {
+ if (!baseVfHeatStackId.equalsIgnoreCase("null")) {
+ nestedBaseStackId = baseVfHeatStackId;
+ }
+ }
+
+ if (inputs == null) {
+ // Create an empty set of inputs
+ inputs = new HashMap<String,String>();
+ LOGGER.debug("inputs == null - setting to empty");
+ } else {
+ this.sendMapToDebug(inputs);
+ }
+ boolean isBaseRequest = false;
+ boolean isVolumeRequest = false;
+ if (requestTypeString.startsWith("VOLUME")) {
+ isVolumeRequest = true;
+ }
+ if (vfModuleName == null || vfModuleName.trim().equals("")) {
+ if (vfModuleStackId != null) {
+ vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
+ }
+ }
+
+ LOGGER.debug ("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudSiteId + "/" + tenantId);
+ LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Build a default rollback object (no actions performed)
+ VnfRollback vfRollback = new VnfRollback ();
+ vfRollback.setCloudSiteId (cloudSiteId);
+ vfRollback.setTenantId (tenantId);
+ vfRollback.setMsoRequest (msoRequest);
+ vfRollback.setRequestType(requestTypeString);
+ vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
+ vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
+ vfRollback.setIsBase(isBaseRequest);
+ vfRollback.setVfModuleStackId(vfModuleStackId);
+
+ // First, look up to see if the VNF already exists.
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+ MsoHeatUtilsWithUpdate heatU = new MsoHeatUtilsWithUpdate (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ StackInfo heatStack = null;
+ long queryStackStarttime = System.currentTimeMillis ();
+ LOGGER.debug("UpdateVfModule - querying for " + vfModuleName);
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
+ LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("UpdateVFModule");
+ String error = "Update VFModule: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ //TODO - do we need to check for the other status possibilities?
+ if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
+ // Not Found
+ String error = "Update VF: Stack " + vfModuleName + " does not exist in " + cloudSiteId + "/" + tenantId;
+ LOGGER.error (MessageEnum.RA_VNF_NOT_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfNotFound (cloudSiteId, tenantId, vfModuleName);
+ } else {
+ LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
+ // Populate the outputs from the existing stack.
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vfRollback; // Default rollback - no updates performed
+ }
+
+ // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
+ StackInfo nestedHeatStack = null;
+ long queryStackStarttime2 = System.currentTimeMillis ();
+ if (nestedStackId != null) {
+ try {
+ LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
+ nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
+ LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("UpdateVFModule");
+ String error = "Update VF: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
+ LOGGER.debug("ERROR trying to query nested stack= " + error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
+ MsoLogger.setServiceName (serviceName);
+ String error = "Update VFModule: Attached volume heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.debug(error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found nested heat stack - copying values to inputs");
+ this.sendMapToDebug(inputs);
+ heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
+ this.sendMapToDebug(inputs);
+ }
+ }
+ // handle a nestedBaseStackId if sent - this is the stack ID of the base.
+ StackInfo nestedBaseHeatStack = null;
+ if (nestedBaseStackId != null) {
+ long queryStackStarttime3 = System.currentTimeMillis ();
+ try {
+ LOGGER.debug("Querying for nestedBaseStackId = " + nestedBaseStackId);
+ nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
+ LOGGER.recordMetricEvent (queryStackStarttime3, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("UpdateVfModule");
+ String error = "Update VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.recordMetricEvent (queryStackStarttime3, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
+ LOGGER.debug("ERROR trying to query nested base stack= " + error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
+ MsoLogger.setServiceName (serviceName);
+ String error = "Update VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ LOGGER.debug(error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found nested base heat stack - copying values to inputs");
+ this.sendMapToDebug(inputs);
+ heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
+ this.sendMapToDebug(inputs);
+ }
+ }
+
+ // Ready to deploy the new VNF
+
+ try (CatalogDatabase db = new CatalogDatabase ()) {
+ // Retrieve the VF definition
+ //VnfResource vnf;
+ VfModule vf = null;
+ if (vfVersion != null && !vfVersion.isEmpty ()) {
+ vf = db.getVfModuleType(vfModuleType, vfVersion);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " and version = " + vfVersion + " in the TYPE column - will try in MODEL_NAME");
+ vf = db.getVfModuleModelName(vfModuleType, vfVersion);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " and version = " + vfVersion + " in the MODEL_NAME field either - ERROR");
+ }
+ }
+ } else {
+ vf = db.getVfModuleType(vfModuleType);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " in the TYPE column - will try in MODEL_NAME");
+ vf = db.getVfModuleModelName(vfModuleType);
+ if (vf == null) {
+ LOGGER.debug("Unable to find " + vfModuleType + " in the MODEL_NAME field either - ERROR");
+ }
+ }
+ }
+ if (vf == null) {
+ String error = "Update VFModule: Unknown VF Module Type: " + vfModuleType;
+ if (vfVersion != null && !vfVersion.isEmpty()) {
+ error += " with version = " + vfVersion;
+ }
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VF Module Type", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug ("Got VF module definition from Catalog: " + vf.toString ());
+
+ HeatTemplate heatTemplate = null;
+ Integer heatTemplateId = null;
+ Integer heatEnvtId = null;
+ if (!isVolumeRequest) {
+ heatTemplateId = vf.getTemplateId();
+ heatEnvtId = vf.getEnvironmentId();
+ } else {
+ heatTemplateId = vf.getVolTemplateId();
+ heatEnvtId = vf.getVolEnvironmentId();
+ }
+ if (heatTemplateId == null) {
+ String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException(error, MsoExceptionCategory.INTERNAL);
+ } else {
+ heatTemplate = db.getHeatTemplate(heatTemplateId);
+ }
+
+ if (heatTemplate == null) {
+ String error = "Update VNF: undefined Heat Template. VF="
+ + vfModuleType + ", heat template id = " + heatTemplateId;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "Heat Template ID",
+ String.valueOf(heatTemplateId), "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException(error, MsoExceptionCategory.INTERNAL);
+ }
+
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
+
+ // Add check for any Environment variable
+ HeatEnvironment heatEnvironment = null;
+ String heatEnvironmentString = null;
+
+ if (heatEnvtId != null) {
+ LOGGER.debug ("about to call getHeatEnvironment with :" + heatEnvtId + ":");
+ heatEnvironment = db.getHeatEnvironment (heatEnvtId);
+ if (heatEnvironment == null) {
+
+ String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType
+ + ", Environment ID="
+ + heatEnvtId;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(heatEnvtId), "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ } else {
+ LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
+ heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
+ LOGGER.debug ("After parsing: " + heatEnvironmentString);
+ }
+ } else {
+ LOGGER.debug ("no environment parameter for this VFModuleType " + vfModuleType);
+ }
+
+
+ LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
+ + heatTemplate.getId ());
+ Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
+ Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
+ if (nestedTemplates != null) {
+ // for debugging print them out
+ LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
+ for (String providerResourceFile : nestedTemplates.keySet ()) {
+ String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
+ String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
+ nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
+ LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
+ }
+ } else {
+ LOGGER.debug ("No nested templates found - nothing to do here");
+ nestedTemplatesChecked = null;
+ }
+
+ // Also add the files: for any get_files associated with this VfModule
+ // *if* there are any
+ LOGGER.debug ("In MsoVnfAdapterImpl.updateVfModule, about to call db.getHeatFiles avec vfModuleId="
+ + vf.getId ());
+
+ Map <String, HeatFiles> heatFiles = null;
+// Map <String, HeatFiles> heatFiles = db.getHeatFiles (vnf.getId ());
+ Map <String, Object> heatFilesObjects = new HashMap <String, Object> ();
+
+ // Add ability to turn on adding get_files with volume requests (by property).
+ boolean addGetFilesOnVolumeReq = false;
+ try {
+ String propertyString = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_VNF_ADAPTER).getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, null);
+ if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
+ addGetFilesOnVolumeReq = true;
+ LOGGER.debug("AddGetFilesOnVolumeReq - setting to true! " + propertyString);
+ }
+ } catch (Exception e) {
+ LOGGER.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ + " - default to false", e);
+ }
+ if (!isVolumeRequest || addGetFilesOnVolumeReq) {
+ heatFiles = db.getHeatFilesForVfModule(vf.getId());
+ if (heatFiles != null) {
+ // add these to stack - to be done in createStack
+ // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
+ // this will match the nested templates format
+ LOGGER.debug ("Contents of heatFiles - to be added to files: on stack:");
+
+ for (String heatFileName : heatFiles.keySet ()) {
+ if (heatFileName.startsWith("_ERROR|")) {
+ // This means there was an invalid entry in VF_MODULE_TO_HEAT_FILES table - the heat file it pointed to could not be found.
+ String heatFileId = heatFileName.substring(heatFileName.lastIndexOf("|")+1);
+ String error = "Create: No HEAT_FILES entry in catalog database for " + vfModuleType + " at HEAT_FILES index=" + heatFileId;
+ LOGGER.debug(error);
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "HEAT_FILES entry not found at " + heatFileId, vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+ throw new VnfException (error, MsoExceptionCategory.INTERNAL);
+ }
+ String heatFileBody = heatFiles.get (heatFileName).getFileBody ();
+ LOGGER.debug (heatFileName + " -> " + heatFileBody);
+ heatFilesObjects.put (heatFileName, heatFileBody);
+ }
+ } else {
+ LOGGER.debug ("No heat files found -nothing to do here");
+ heatFilesObjects = null;
+ }
+ }
+
+ // Check that required parameters have been supplied
+ String missingParams = null;
+ List <String> paramList = new ArrayList <String> ();
+
+ // New for 1510 - consult the PARAM_ALIAS field to see if we've been
+ // supplied an alias. Only check if we don't find it initially.
+ // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
+ // And also new - add parameter to turn off checking all together if we find we're blocking orders we
+ // shouldn't
+ boolean haveEnvironmentParameters = false;
+ boolean checkRequiredParameters = true;
+ try {
+ String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
+ .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
+ if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
+ checkRequiredParameters = false;
+ LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
+ + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
+ }
+ } catch (Exception e) {
+ // No problem - default is true
+ LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
+ }
+ // 1604 - Add enhanced environment & parameter checking
+ // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
+ // Part 2: only submit to openstack the parameters in the envt that are in the heat template
+ // Note this also removes any comments
+ MsoHeatEnvironmentEntry mhee = null;
+ if (heatEnvironmentString != null && heatEnvironmentString.toLowerCase ().contains ("parameters:")) {
+ LOGGER.debug("Enhanced environment checking enabled - 1604");
+ haveEnvironmentParameters = true;
+ StringBuilder sb = new StringBuilder(heatEnvironmentString);
+ //LOGGER.debug("About to create MHEE with " + sb);
+ mhee = new MsoHeatEnvironmentEntry(sb);
+ StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
+ for (HeatTemplateParam parm : heatTemplate.getParameters()) {
+ sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
+ }
+ if (!mhee.isValid()) {
+ sb2.append("Environment says it's not valid! " + mhee.getErrorString());
+ } else {
+ sb2.append("\nEnvironment:");
+ sb2.append(mhee.toFullString());
+ }
+ LOGGER.debug(sb2.toString());
+ } else {
+ LOGGER.debug("NO ENVIRONMENT for this entry");
+ }
+
+ // New for 1607 - support params of json type
+ HashMap<String, JsonNode> jsonParams = new HashMap<String, JsonNode>();
+ boolean hasJson = false;
+
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ LOGGER.debug ("Parameter:'" + parm.getParamName ()
+ + "', isRequired="
+ + parm.isRequired ()
+ + ", alias="
+ + parm.getParamAlias ());
+ // handle json
+ String parameterType = parm.getParamType();
+ if (parameterType == null || parameterType.trim().equals("")) {
+ parameterType = "String";
+ }
+ JsonNode jsonNode = null;
+ if (parameterType.equalsIgnoreCase("json") && inputs != null) {
+ if (inputs.containsKey(parm.getParamName()) ) {
+ hasJson = true;
+ String jsonString = null;
+ try {
+ jsonString = inputs.get(parm.getParamName());
+ jsonNode = new ObjectMapper().readTree(jsonString);
+ } catch (JsonParseException jpe) {
+ //TODO - what to do here?
+ //for now - send the error to debug, but just leave it as a String
+ String errorMessage = jpe.getMessage();
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
+ hasJson = false;
+ jsonNode = null;
+ }
+ if (jsonNode != null) {
+ jsonParams.put(parm.getParamName(), jsonNode);
+ }
+ } else if (inputs.containsKey(parm.getParamAlias())) {
+ hasJson = true;
+ String jsonString = null;
+ try {
+ jsonString = inputs.get(parm.getParamAlias());
+ jsonNode = new ObjectMapper().readTree(jsonString);
+ } catch (JsonParseException jpe) {
+ //TODO - what to do here?
+ //for now - send the error to debug, but just leave it as a String
+ String errorMessage = jpe.getMessage();
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
+ hasJson = false;
+ jsonNode = null;
+ }
+ if (jsonNode != null) {
+ // Notice here - we add it to the jsonParams hashMap with the actual name -
+ // then manipulate the inputs so when we check for aliases below - it will not
+ // get flagged.
+ jsonParams.put(parm.getParamName(), jsonNode);
+ inputs.remove(parm.getParamAlias());
+ inputs.put(parm.getParamName(), jsonString);
+ }
+ } //TODO add a check for the parameter in the env file
+ }
+
+ if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
+ if (inputs.containsKey (parm.getParamAlias ())) {
+ // They've submitted using an alias name. Remove that from inputs, and add back using real name.
+ String realParamName = parm.getParamName ();
+ String alias = parm.getParamAlias ();
+ String value = inputs.get (alias);
+ LOGGER.debug ("*Found an Alias: paramName=" + realParamName
+ + ",alias="
+ + alias
+ + ",value="
+ + value);
+ inputs.remove (alias);
+ inputs.put (realParamName, value);
+ LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
+ }
+ // enhanced - check if it's in the Environment (note: that method
+ else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
+
+ LOGGER.debug ("Required parameter " + parm.getParamName ()
+ + " appears to be in environment - do not count as missing");
+ }
+ else {
+ LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
+ if (missingParams == null) {
+ missingParams = parm.getParamName ();
+ } else {
+ missingParams += "," + parm.getParamName ();
+ }
+ }
+ }
+ paramList.add (parm.getParamName ());
+ }
+ if (missingParams != null) {
+ // Problem - missing one or more required parameters
+ if (checkRequiredParameters) {
+ String error = "Update VNF: Missing Required inputs: " + missingParams;
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new VnfException (error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
+ }
+ } else {
+ LOGGER.debug ("No missing parameters found - ok to proceed");
+ }
+
+ // Here - modify heatEnvironmentString
+ StringBuilder parsedEnvironmentString = null;
+ String newEnvironmentString = null;
+ if (mhee != null) {
+ LOGGER.debug("Environment before:\n" + heatEnvironmentString);
+ parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
+ LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
+ newEnvironmentString = parsedEnvironmentString.toString();
+ }
+
+ // Remove any extraneous parameters (don't throw an error)
+ if (inputs != null) {
+ List <String> extraParams = new ArrayList <String> ();
+ extraParams.addAll (inputs.keySet ());
+ // This is not a valid parameter for this template
+ extraParams.removeAll (paramList);
+ if (!extraParams.isEmpty ()) {
+ LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "", MsoLogger.ErrorCode.DataError, "Extra params");
+ inputs.keySet ().removeAll (extraParams);
+ }
+ }
+ // 1607 - when we get here - we have clean inputs. Create inputsTwo in case we have json
+ Map<String, Object> inputsTwo = null;
+ if (hasJson && jsonParams.size() > 0) {
+ inputsTwo = new HashMap<String, Object>();
+ for (String keyParamName : inputs.keySet()) {
+ if (jsonParams.containsKey(keyParamName)) {
+ inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
+ } else {
+ inputsTwo.put(keyParamName, inputs.get(keyParamName));
+ }
+ }
+ }
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ // Have the tenant. Now deploy the stack itself
+ // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
+ // because we already checked for those.
+ long updateStackStarttime = System.currentTimeMillis ();
+ try {
+ if (!hasJson) {
+ heatStack = heatU.updateStack (cloudSiteId,
+ tenantId,
+ vfModuleName,
+ template,
+ copyStringInputs (inputs),
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ newEnvironmentString,
+ //heatEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects);
+ LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "UpdateStack", null);
+ } else {
+ heatStack = heatU.updateStack (cloudSiteId,
+ tenantId,
+ vfModuleName,
+ template,
+ inputsTwo,
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ newEnvironmentString,
+ //heatEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects);
+ LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "UpdateStack", null);
+
+ }
+ } catch (MsoException me) {
+ me.addContext ("UpdateVFModule");
+ String error = "Update VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
+ LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ }
+
+ // Reach this point if updateStack is successful.
+ // Populate remaining rollback info and response parameters.
+ vfRollback.setVnfId (heatStack.getCanonicalName ());
+ vfRollback.setVnfCreated (true);
+
+ outputs.value = copyStringOutputs (heatStack.getOutputs ());
+ rollback.value = vfRollback;
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully update VF Module");
+ return;
+ }
+
+ private String getVfModuleNameFromModuleStackId(String vfModuleStackId) {
+ // expected format of vfModuleStackId is "MSOTEST51-vSAMP3_base_module-0/1fc1f86c-7b35-447f-99a6-c23ec176ae24"
+ // before the "/" is the vfModuleName and after the "/" is the heat stack id in Openstack
+ if (vfModuleStackId == null)
+ return null;
+ int index = vfModuleStackId.lastIndexOf('/');
+ if (index <= 0)
+ return null;
+ String vfModuleName = null;
+ try {
+ vfModuleName = vfModuleStackId.substring(0, index);
+ } catch (Exception e) {
+ vfModuleName = null;
+ }
+ return vfModuleName;
+ }
+
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VfRollback.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VfRollback.java
new file mode 100644
index 0000000000..90ab01bd8c
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VfRollback.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+
+import org.openecomp.mso.entity.MsoRequest;
+
+public class VfRollback {
+ private String vnfId;
+ private String tenantId;
+ private String cloudSiteId;
+ private boolean tenantCreated = false;
+ private boolean vnfCreated = false;
+ private MsoRequest msoRequest;
+ private String volumeGroupName;
+ private String volumeGroupId;
+ private String requestType;
+ private String volumeGroupHeatStackId;
+ private String baseGroupHeatStackId;
+ private boolean isBase = false;
+ private String vfModuleStackId;
+
+
+ public String getVnfId() {
+ return vnfId;
+ }
+ public void setVnfId(String vnfId) {
+ this.vnfId = vnfId;
+ }
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+ public String getCloudSiteId() {
+ return cloudSiteId;
+ }
+ public void setCloudSiteId(String cloudId) {
+ this.cloudSiteId = cloudId;
+ }
+ public boolean getTenantCreated() {
+ return tenantCreated;
+ }
+ public void setTenantCreated(boolean tenantCreated) {
+ this.tenantCreated = tenantCreated;
+ }
+ public boolean getVnfCreated() {
+ return vnfCreated;
+ }
+ public void setVnfCreated(boolean vnfCreated) {
+ this.vnfCreated = vnfCreated;
+ }
+ public MsoRequest getMsoRequest() {
+ return msoRequest;
+ }
+ public void setMsoRequest (MsoRequest msoRequest) {
+ this.msoRequest = msoRequest;
+ }
+ public String getVolumeGroupName() {
+ return this.volumeGroupName;
+ }
+ public void setVolumeGroupName(String volumeGroupName) {
+ this.volumeGroupName = volumeGroupName;
+ }
+ public String getVolumeGroupId() {
+ return this.volumeGroupId;
+ }
+ public void setVolumeGroupId(String volumeGroupId) {
+ this.volumeGroupId = volumeGroupId;
+ }
+ public String getRequestType() {
+ return this.requestType;
+ }
+ public void setRequestType(String requestType) {
+ this.requestType = requestType;
+ }
+ /*
+ private String volumeGroupHeatStackId;
+ private String baseGroupHeatStackId;
+ private boolean isBase = false;
+ */
+ public String getVolumeGroupHeatStackId() {
+ return this.volumeGroupHeatStackId;
+ }
+ public void setVolumeGroupHeatStackId(String volumeGroupHeatStackId) {
+ this.volumeGroupHeatStackId = volumeGroupHeatStackId;
+ }
+
+ public String getBaseGroupHeatStackId() {
+ return this.baseGroupHeatStackId;
+ }
+ public void setBaseGroupHeatStackId(String baseGroupHeatStackId) {
+ this.baseGroupHeatStackId = baseGroupHeatStackId;
+ }
+
+ public boolean isBase() {
+ return this.isBase;
+ }
+ public void setIsBase(boolean isBase) {
+ this.isBase = isBase;
+ }
+ public String getVfModuleStackId() {
+ return this.vfModuleStackId;
+ }
+ public void setVfModuleStackId(String vfModuleStackId) {
+ this.vfModuleStackId = vfModuleStackId;
+ }
+
+ @Override
+ public String toString() {
+ return "VfRollback: cloud=" + cloudSiteId + ", tenant=" + tenantId +
+ ", vnf=" + vnfId + ", tenantCreated=" + tenantCreated +
+ ", vnfCreated=" + vnfCreated + ", requestType = " + requestType +
+ ", volumeGroupHeatStackId = " + this.volumeGroupHeatStackId;
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VnfAdapterRest.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VnfAdapterRest.java
new file mode 100644
index 0000000000..6906f816a7
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VnfAdapterRest.java
@@ -0,0 +1,628 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.xml.ws.Holder;
+
+import org.apache.http.HttpStatus;
+
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.VnfStatus;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+import org.openecomp.mso.adapters.vnfrest.*;
+
+/**
+ * This class services calls to the REST interface for VF Modules (http://host:port/vnfs/rest/v1/vnfs)
+ * Both XML and JSON can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default.
+ * For testing, call with cloudSiteId = ___TESTING___
+ * To test exceptions, also set tenantId = ___TESTING___
+ */
+@Path("/v1/vnfs")
+public class VnfAdapterRest {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+ private final CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
+ private final MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ private final MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory, cloudConfigFactory);
+ //TODO Logging, SkipAAI, CREATED flags, Integrate with BPEL, Auth,
+
+ @HEAD
+ @GET
+ @Path("/healthcheck")
+ @Produces(MediaType.TEXT_HTML)
+ public Response healthcheck () {
+ String CHECK_HTML = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Health Check</title></head><body>Application ready</body></html>";
+ return Response.ok().entity(CHECK_HTML).build();
+ }
+
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v1/vnfs/<aaivnfid>/vf-modules/<aaimodid>
+ * REQUEST:
+ * {"deleteVfModuleRequest":
+ {"cloudSiteId": "DAN",
+ "tenantId": "214b428a1f554c02935e66330f6a5409",
+ "vnfId": "somevnfid",
+ "vfModuleId": "somemodid",
+ "vfModuleStackId": "4e567676-e266-4594-a3a6-131c8a2baf73",
+ "messageId": "ra.1",
+ "notificationUrl": "http://localhost:8089/vnfmock",
+ "skipAAI": true,
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }}
+ }
+ */
+ @DELETE
+ @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response deleteVfModule (
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ final DeleteVfModuleRequest req)
+ {
+ LOGGER.debug("Delete VfModule enter: " + req.toJsonString());
+ if (aaiVnfId == null || !aaiVnfId.equals(req.getVnfId())) {
+ LOGGER.debug("Req rejected - aaiVnfId not provided or doesn't match URL");
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("vnfid in URL does not match content")
+ .build();
+ }
+ if (aaiVfModuleId == null || !aaiVfModuleId.equals(req.getVfModuleId())) {
+ LOGGER.debug("Req rejected - aaiVfModuleId not provided or doesn't match URL");
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("vfModuleId in URL does not match content")
+ .build();
+ }
+ DeleteVfModuleTask task = new DeleteVfModuleTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling delete, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, "", "deleteVfModule", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in deleteVfModule", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("deleteVNFVolumes exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class DeleteVfModuleTask implements Runnable {
+ private final DeleteVfModuleRequest req;
+ private DeleteVfModuleResponse response = null;
+ private VfModuleExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public DeleteVfModuleTask(DeleteVfModuleRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<DeleteVfModuleResponse>(response) {}
+ : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ String cloudsite = req.getCloudSiteId();
+ if (cloudsite != null && !cloudsite.equals(TESTING_KEYWORD)) {
+ //vnfAdapter.deleteVnf (req.getCloudSiteId(), req.getTenantId(), req.getVfModuleStackId(), req.getMsoRequest());
+ vnfAdapter.deleteVfModule (req.getCloudSiteId(), req.getTenantId(), req.getVfModuleStackId(), req.getMsoRequest());
+ }
+ response = new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException - Delete VNF Module", e);
+ eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("Delete vfModule exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v1/vnfs/<aaiVnfId>/vf-modules/<aaiVfModuleId>?cloudSiteId=DAN&tenantId=vfModule?&skipAAI=TRUE&msoRequest.requestId=ra1&msoRequest.serviceInstanceId=si1&vfModuleName=T2N2S1
+ * RESP:
+ * {"queryVfModuleResponse": {
+ "vfModuleId": "AvfmodId",
+ "vfModuleOutputs": {"entry": {
+ "key": "server_private_ip_1",
+ "value": "10.100.1.25"
+ }},
+ "vfModuleStackId": "RaaVnf1/abfa8a6d-feb1-40af-aea3-109403b1cf6b",
+ "vnfId": "AvnfID",
+ "vnfStatus": "ACTIVE"
+ }}
+ */
+ @GET
+ @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response queryVfModule(
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @QueryParam("tenantId") String tenantId,
+ @QueryParam("vfModuleName") String vfModuleName, //RAA? Id in doc
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @QueryParam("msoRequest.requestId") String requestId,
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId)
+ {
+ //This request responds synchronously only
+ LOGGER.debug ("Query vfModule enter:" + vfModuleName);
+ MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
+
+ try {
+ int respStatus = HttpStatus.SC_OK;
+ QueryVfModuleResponse qryResp = new QueryVfModuleResponse(aaiVnfId, aaiVfModuleId, null, null, null);
+ Holder<Boolean> vnfExists = new Holder<Boolean>();
+ Holder<String> vfModuleId = new Holder<String>();
+ Holder<VnfStatus> status = new Holder<VnfStatus>();
+ Holder<Map<String, String>> outputs = new Holder <Map <String, String>> ();
+ vnfAdapter.queryVnf (cloudSiteId, tenantId, vfModuleName, msoRequest, vnfExists, vfModuleId, status, outputs);
+ if (!vnfExists.value) {
+ LOGGER.debug ("vfModule not found");
+ respStatus = HttpStatus.SC_NOT_FOUND;
+ } else {
+ LOGGER.debug ("vfModule found" + vfModuleId.value + ", status=" + status.value);
+ qryResp.setVfModuleId(vfModuleId.value);
+ qryResp.setVnfStatus(status.value);
+ qryResp.setVfModuleOutputs(outputs.value);
+ }
+ LOGGER.debug ("Query vfModule exit");
+ return Response
+ .status(respStatus)
+ .entity(new GenericEntity<QueryVfModuleResponse>(qryResp) {})
+ .build();
+ } catch (VnfException e) {
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, "", "queryVfModule", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException - queryVfModule", e);
+ VfModuleExceptionResponse excResp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.FALSE, null);
+ return Response
+ .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
+ .entity(new GenericEntity<VfModuleExceptionResponse>(excResp) {})
+ .build();
+ }
+ }
+
+ /*URL: http://localhost:8080/vnfs/rest/v1/vnfs/<aaivnfid>/vf-modules
+ *REQUEST:
+ * {"createVfModuleRequest":
+ {"cloudSiteId": "DAN",
+ "tenantId": "214b428a1f554c02935e66330f6a5409",
+ "vnfId": "somevnfid",
+ "vfModuleId": "somemodid",
+ "vfModuleName": "RaaVnf1",
+ "vnfType": "ApacheVnf",
+ "vfModuleParams": {"entry": [
+ {"key": "network_id",
+ "value": "59ed7b41-2983-413f-ba93-e7d437433916"},
+ {"key": "subnet_id",
+ "value": "086c9298-5c57-49b7-bb2b-6fd5730c5d92"},
+ {"key": "server_name_0",
+ "value": "RaaVnf1"}
+ ]},
+ "failIfExists": true,
+ "messageId": "ra.1",
+ "notificationUrl": "http://localhost:8089/vnfmock",
+ "skipAAI": true,
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }}
+ }
+ */
+ @POST
+ @Path("{aaiVnfId}/vf-modules")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response createVfModule(
+ @PathParam("aaiVnfId") String aaiVnfId,
+ final CreateVfModuleRequest req)
+ {
+ LOGGER.debug("Create VfModule enter inside VnfAdapterRest: " + req.toJsonString());
+ if (aaiVnfId == null || !aaiVnfId.equals(req.getVnfId())) {
+ LOGGER.debug("Req rejected - aaiVnfId not provided or doesn't match URL");
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("vnfid in URL does not match content")
+ .build();
+ }
+ CreateVfModuleTask task = new CreateVfModuleTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, "", "createVfModule", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - createVfModule", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("createVfModule exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class CreateVfModuleTask implements Runnable {
+ private final CreateVfModuleRequest req;
+ private CreateVfModuleResponse response = null;
+ private VfModuleExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public CreateVfModuleTask(CreateVfModuleRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<CreateVfModuleResponse>(response) {}
+ : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+
+ @Override
+ public void run() {
+ LOGGER.debug ("CreateVfModuleTask start");
+ try {
+ // Synchronous Web Service Outputs
+ Holder <String> vfModuleStackId = new Holder <String> ();
+ Holder <Map <String, String>> outputs = new Holder <Map <String, String>> ();
+ Holder <VnfRollback> vnfRollback = new Holder <VnfRollback> ();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("completeVnfVfModuleType=" + completeVnfVfModuleType);
+ String cloudsite = req.getCloudSiteId();
+ if (cloudsite != null && cloudsite.equals(TESTING_KEYWORD)) {
+ String tenant = req.getTenantId();
+ if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
+ throw new VnfException("testing.");
+ }
+ vnfRollback.value = new VnfRollback(req.getVnfId(), tenant, cloudsite,
+ true, false, new MsoRequest("reqid", "svcid"),
+ req.getVolumeGroupId(), req.getVolumeGroupId(), req.getRequestType());
+ vfModuleStackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
+ outputs.value = VolumeAdapterRest.testMap();
+ } else {
+// vnfAdapter.createVnf (createReq.getCloudSiteId(),
+// createReq.getTenantId(),
+// createReq.getVnfType(),
+// createReq.getVnfVersion(),
+// createReq.getVfModuleName(),
+// createReq.getRequestType(),
+// createReq.getVolumeGroupStackId(),
+// createReq.getVfModuleParams(),
+// createReq.getFailIfExists(),
+// createReq.getBackout(),
+// createReq.getMsoRequest(),
+// vfModuleStackId,
+// outputs,
+// vnfRollback);
+ vnfAdapter.createVfModule(req.getCloudSiteId(),
+ req.getTenantId(),
+ //req.getVnfType(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVfModuleName(),
+ req.getRequestType(),
+ req.getVolumeGroupStackId(),
+ req.getBaseVfModuleStackId(),
+ req.getVfModuleParams(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getMsoRequest(),
+ vfModuleStackId,
+ outputs,
+ vnfRollback);
+ }
+ VfModuleRollback modRollback = new VfModuleRollback(vnfRollback.value, req.getVfModuleId(), vfModuleStackId.value, req.getMessageId());
+ response = new CreateVfModuleResponse(req.getVnfId(), req.getVfModuleId(),
+ vfModuleStackId.value, Boolean.TRUE, outputs.value, modRollback, req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("CreateVfModuleTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @PUT
+ @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response updateVfModule(
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ final UpdateVfModuleRequest req)
+ {
+ LOGGER.debug("Update VfModule enter: " + req.toJsonString());
+ UpdateVfModulesTask task = new UpdateVfModulesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, "", "updateVfModule", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - updateVfModule", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("updateVfModules exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class UpdateVfModulesTask implements Runnable {
+ private final UpdateVfModuleRequest req;
+ private UpdateVfModuleResponse response = null;
+ private VfModuleExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public UpdateVfModulesTask(UpdateVfModuleRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<UpdateVfModuleResponse>(response) {}
+ : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ try {
+ //MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory, cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <String> vfModuleStackId = new Holder <String> ();
+ Holder <Map <String, String>> outputs = new Holder <Map <String, String>> ();
+ Holder <VnfRollback> vnfRollback = new Holder <VnfRollback> ();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in updateVf - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ /*
+ vnfAdapter.updateVnf (updateReq.getCloudSiteId(),
+ updateReq.getTenantId(),
+ updateReq.getVnfType(),
+ updateReq.getVnfVersion(),
+ updateReq.getVfModuleName(),
+ updateReq.getRequestType(),
+ updateReq.getVolumeGroupStackId(),
+ updateReq.getVfModuleParams(),
+ updateReq.getMsoRequest(),
+ outputs,
+ vnfRollback);
+ */
+ vnfAdapter.updateVfModule (req.getCloudSiteId(),
+ req.getTenantId(),
+ //req.getVnfType(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVfModuleName(),
+ req.getRequestType(),
+ req.getVolumeGroupStackId(),
+ req.getBaseVfModuleId(),
+ req.getVfModuleStackId(),
+ req.getVfModuleParams(),
+ req.getMsoRequest(),
+ outputs,
+ vnfRollback);
+
+ response = new UpdateVfModuleResponse(req.getVnfId(), req.getVfModuleId(),
+ vfModuleStackId.value, outputs.value, req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient ();
+ bpelClient.bpelPost (getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("Update VfModule exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v1/vnfs/<aaivnfid>/vf-modules/<aaimodid>/rollback
+ * REQUEST:
+ * {"deleteVfModuleRequest":
+ {"cloudSiteId": "DAN",
+ "tenantId": "214b428a1f554c02935e66330f6a5409",
+ "vnfId": "somevnfid",
+ "vfModuleId": "somemodid",
+ "vfModuleStackId": "4e567676-e266-4594-a3a6-131c8a2baf73",
+ "messageId": "ra.1",
+ "notificationUrl": "http://localhost:8089/vnfmock",
+ "skipAAI": true,
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }}
+ }
+ */
+ @DELETE
+ @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}/rollback")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response rollbackVfModule (
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ //@QueryParam("rollback") String rollback,
+ final RollbackVfModuleRequest req)
+ {
+ LOGGER.debug("Rollback VfModule enter: " + req.toJsonString());
+ RollbackVfModulesTask task = new RollbackVfModulesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "rollbackVfModule", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - rollbackVfModule", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("rollbackVfModule exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class RollbackVfModulesTask implements Runnable {
+ private final RollbackVfModuleRequest req;
+ private RollbackVfModuleResponse response = null;
+ private VfModuleExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public RollbackVfModulesTask(RollbackVfModuleRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<RollbackVfModuleResponse>(response) {}
+ : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ try {
+ VfModuleRollback vmr = req.getVfModuleRollback();
+ VnfRollback vrb = new VnfRollback(
+ vmr.getVfModuleStackId(), vmr.getTenantId(), vmr.getCloudSiteId(), true, true,
+ vmr.getMsoRequest(), null, null, null);
+ vnfAdapter.rollbackVnf (vrb);
+ response = new RollbackVfModuleResponse(Boolean.TRUE, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - rollbackVfModule", e);
+ eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, false, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient ();
+ bpelClient.bpelPost (getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("RollbackVfModulesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VolumeAdapterRest.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VolumeAdapterRest.java
new file mode 100644
index 0000000000..8fa1552bb0
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/VolumeAdapterRest.java
@@ -0,0 +1,576 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.ws.Holder;
+
+import org.apache.http.HttpStatus;
+
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupRequest;
+import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupResponse;
+import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupRequest;
+import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupResponse;
+import org.openecomp.mso.adapters.vnfrest.QueryVolumeGroupResponse;
+import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupRequest;
+import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupResponse;
+import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupRequest;
+import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupResponse;
+import org.openecomp.mso.adapters.vnfrest.VolumeGroupExceptionResponse;
+import org.openecomp.mso.adapters.vnfrest.VolumeGroupRollback;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.VnfRollback;
+import org.openecomp.mso.openstack.beans.VnfStatus;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+/**
+ * This class services calls to the REST interface for VNF Volumes (http://host:port/vnfs/rest/v1/volume-groups)
+ * Both XML and JSON can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default.
+ * For testing, call with cloudSiteId = ___TESTING___
+ * To test exceptions, also set tenantId = ___TESTING___
+ */
+@Path("/v1/volume-groups")
+public class VolumeAdapterRest {
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+ private final CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
+ private final MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ private final MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl(msoPropertiesFactory, cloudConfigFactory);
+
+ @POST
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response createVNFVolumes(final CreateVolumeGroupRequest req) {
+ LOGGER.debug("createVNFVolumes enter: " + req.toJsonString());
+ CreateVNFVolumesTask task = new CreateVNFVolumesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, "", "createVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - createVNFVolumes", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("createVNFVolumes exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class CreateVNFVolumesTask implements Runnable {
+ private final CreateVolumeGroupRequest req;
+ private CreateVolumeGroupResponse response = null;
+ private VolumeGroupExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public CreateVNFVolumesTask(CreateVolumeGroupRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<CreateVolumeGroupResponse>(response) {}
+ : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ LOGGER.debug ("CreateVFModule VolumesTask start");
+ try {
+ // Synchronous Web Service Outputs
+ Holder<String> stackId = new Holder<String>();
+ Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
+ Holder<VnfRollback> vnfRollback = new Holder<VnfRollback>();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in createVfModuleVolumes - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ String cloudsite = req.getCloudSiteId();
+ if (cloudsite != null && cloudsite.equals(TESTING_KEYWORD)) {
+ String tenant = req.getTenantId();
+ if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
+ throw new VnfException("testing.");
+ }
+ stackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
+ outputs.value = testMap();
+ } else {
+// vnfAdapter.createVnf(
+// req.getCloudSiteId(),
+// req.getTenantId(),
+// req.getVnfType(),
+// req.getVnfVersion(),
+// req.getVolumeGroupName(),
+// "VOLUME", // request type is VOLUME
+// null, // not sure about this
+// req.getVolumeGroupParams(),
+// req.getFailIfExists(),
+// req.getSuppressBackout(),
+// req.getMsoRequest(),
+// stackId,
+// outputs,
+// vnfRollback);
+ vnfAdapter.createVfModule(
+ req.getCloudSiteId(), //cloudSiteId,
+ req.getTenantId(), //tenantId,
+ //req.getVnfType(), //vnfType,
+ completeVnfVfModuleType,
+ req.getVnfVersion(), //vnfVersion,
+ req.getVolumeGroupName(), //vnfName,
+ "VOLUME", //requestType,
+ null, //volumeGroupHeatStackId,
+ null, //baseVfHeatStackId,
+ req.getVolumeGroupParams(), //inputs,
+ req.getFailIfExists(), //failIfExists,
+ req.getSuppressBackout(), //backout,
+ req.getMsoRequest(), // msoRequest,
+ stackId,
+ outputs,
+ vnfRollback);
+ }
+ VolumeGroupRollback rb = new VolumeGroupRollback(
+ req.getVolumeGroupId(),
+ stackId.value,
+ true, // TODO boolean volumeGroupCreated, when would it be false?
+ req.getTenantId(),
+ req.getCloudSiteId(),
+ req.getMsoRequest(),
+ req.getMessageId());
+ response = new CreateVolumeGroupResponse(
+ req.getVolumeGroupId(),
+ stackId.value,
+ true, // TODO boolean volumeGroupCreated, when would it be false?
+ outputs.value,
+ rb,
+ req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VolumeGroupExceptionResponse(
+ e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("CreateVFModule VolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @DELETE
+ @Path("{aaiVolumeGroupId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response deleteVNFVolumes(
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ final DeleteVolumeGroupRequest req
+ )
+ {
+ LOGGER.debug("deleteVNFVolumes enter: " + req.toJsonString());
+ if (aaiVolumeGroupId == null || !aaiVolumeGroupId.equals(req.getVolumeGroupId())) {
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("VolumeGroupId in URL does not match content")
+ .build();
+ }
+ DeleteVNFVolumesTask task = new DeleteVNFVolumesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, "", "deleteVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - deleteVNFVolumes", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("deleteVNFVolumes exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class DeleteVNFVolumesTask implements Runnable {
+ private final DeleteVolumeGroupRequest req;
+ private DeleteVolumeGroupResponse response = null;
+ private VolumeGroupExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public DeleteVNFVolumesTask(DeleteVolumeGroupRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<DeleteVolumeGroupResponse>(response) {}
+ : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ LOGGER.debug("DeleteVNFVolumesTask start");
+ try {
+ if (!req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ vnfAdapter.deleteVnf(req.getCloudSiteId(), req.getTenantId(), req.getVolumeGroupStackId(), req.getMsoRequest());
+ }
+ response = new DeleteVolumeGroupResponse(true, req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("DeleteVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @DELETE
+ @Path("{aaiVolumeGroupId}/rollback")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response rollbackVNFVolumes(
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ final RollbackVolumeGroupRequest req
+ )
+ {
+ LOGGER.debug("rollbackVNFVolumes enter: " + req.toJsonString());
+ if (aaiVolumeGroupId == null || req.getVolumeGroupRollback() == null || !aaiVolumeGroupId.equals(req.getVolumeGroupRollback().getVolumeGroupId())) {
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("VolumeGroupId in URL does not match content")
+ .build();
+ }
+ RollbackVNFVolumesTask task = new RollbackVNFVolumesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "rollbackVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - rollbackVNFVolumes", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug("rollbackVNFVolumes exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class RollbackVNFVolumesTask implements Runnable {
+ private final RollbackVolumeGroupRequest req;
+ private RollbackVolumeGroupResponse response = null;
+ private VolumeGroupExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public RollbackVNFVolumesTask(RollbackVolumeGroupRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<RollbackVolumeGroupResponse>(response) {}
+ : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ LOGGER.debug("DeleteVNFVolumesTask start");
+ try {
+ VolumeGroupRollback vgr = req.getVolumeGroupRollback();
+ VnfRollback vrb = new VnfRollback(
+ vgr.getVolumeGroupStackId(), vgr.getTenantId(), vgr.getCloudSiteId(), true, true,
+ vgr.getMsoRequest(), null, null, null);
+ vnfAdapter.rollbackVnf(vrb);
+ response = new RollbackVolumeGroupResponse(true, req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("DeleteVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @PUT
+ @Path("{aaiVolumeGroupId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response updateVNFVolumes(
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ final UpdateVolumeGroupRequest req
+ )
+ {
+ LOGGER.debug("updateVNFVolumes enter: " + req.toJsonString());
+ if (aaiVolumeGroupId == null || !aaiVolumeGroupId.equals(req.getVolumeGroupId())) {
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("VolumeGroupId in URL does not match content")
+ .build();
+ }
+ UpdateVNFVolumesTask task = new UpdateVNFVolumesTask(req);
+ if (req.isSynchronous()) {
+ // This is a synchronous request
+ task.run();
+ return Response
+ .status(task.getStatusCode())
+ .entity(task.getGenericEntityResponse())
+ .build();
+ } else {
+ // This is an asynchronous request
+ try {
+ Thread t1 = new Thread(task);
+ t1.start();
+ } catch (Exception e) {
+ // problem handling create, send generic failure as sync resp to caller
+ LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, "", "updateVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - updateVNFVolumes", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("updateVNFVolumes exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class UpdateVNFVolumesTask implements Runnable {
+ private final UpdateVolumeGroupRequest req;
+ private UpdateVolumeGroupResponse response = null;
+ private VolumeGroupExceptionResponse eresp = null;
+ private boolean sendxml;
+
+ public UpdateVNFVolumesTask(UpdateVolumeGroupRequest req) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ }
+ public int getStatusCode() {
+ return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
+ }
+ public Object getGenericEntityResponse() {
+ return (response != null)
+ ? new GenericEntity<UpdateVolumeGroupResponse>(response) {}
+ : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
+ }
+ private String getResponse() {
+ if (response != null) {
+ return sendxml ? response.toXmlString() : response.toJsonString();
+ } else {
+ return sendxml ? eresp.toXmlString() : eresp.toJsonString();
+ }
+ }
+ @Override
+ public void run() {
+ LOGGER.debug("UpdateVNFVolumesTask start");
+ try {
+ @SuppressWarnings("unused")
+ Holder<String> stackId = new Holder<String> ();
+ Holder<Map<String, String>> outputs = new Holder<Map <String, String>> ();
+ Holder<VnfRollback> vnfRollback = new Holder<VnfRollback> ();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in updateVfModuleVolume - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ outputs.value = testMap();
+ } else {
+ //vnfAdapter.updateVnf(
+ // req.getCloudSiteId(),
+ // req.getTenantId(),
+ // req.getVnfType(),
+ // req.getVnfVersion(),
+ // req.getVfModuleType(),
+ // "VOLUME", // request type is VOLUME
+ // req.getVolumeGroupStackId(),
+ // req.getVolumeGroupParams(),
+ // req.getMsoRequest(),
+ // outputs,
+ // vnfRollback);
+ vnfAdapter.updateVfModule (req.getCloudSiteId(),
+ req.getTenantId(),
+ //req.getVnfType(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVolumeGroupStackId(),
+ "VOLUME",
+ null,
+ null,
+ req.getVolumeGroupStackId(),
+ req.getVolumeGroupParams(),
+ req.getMsoRequest(),
+ outputs,
+ vnfRollback);
+ }
+ response = new UpdateVolumeGroupResponse(
+ req.getVolumeGroupId(), req.getVolumeGroupStackId(),
+ outputs.value, req.getMessageId());
+ } catch (VnfException e) {
+ eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("UpdateVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @GET
+ @Path("{aaiVolumeGroupId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response queryVNFVolumes(
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @QueryParam("tenantId") String tenantId,
+ @QueryParam("volumeGroupStackId") String volumeGroupStackId,
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @QueryParam("msoRequest.requestId") String requestId,
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId
+ )
+ {
+ //This request responds synchronously only
+ LOGGER.debug ("queryVNFVolumes enter:" + aaiVolumeGroupId + " " + volumeGroupStackId);
+ MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
+
+ try {
+ int respStatus = HttpStatus.SC_OK;
+ QueryVolumeGroupResponse qryResp = new QueryVolumeGroupResponse(aaiVolumeGroupId, volumeGroupStackId, null, null);
+ Holder<Boolean> vnfExists = new Holder<Boolean>();
+ Holder<String> vfModuleId = new Holder<String>();
+ Holder<VnfStatus> status = new Holder<VnfStatus>();
+ Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
+ if (cloudSiteId != null && cloudSiteId.equals(TESTING_KEYWORD)) {
+ if (tenantId != null && tenantId.equals(TESTING_KEYWORD)) {
+ throw new VnfException("testing.");
+ }
+ vnfExists.value = true;
+ vfModuleId.value = TESTING_KEYWORD;
+ status.value = VnfStatus.ACTIVE;
+ outputs.value = testMap();
+ } else {
+ vnfAdapter.queryVnf(cloudSiteId, tenantId, volumeGroupStackId, msoRequest, vnfExists, vfModuleId, status, outputs);
+ }
+ if (!vnfExists.value) {
+ LOGGER.debug ("VNFVolumes not found");
+ qryResp.setVolumeGroupStatus(status.value);
+ respStatus = HttpStatus.SC_NOT_FOUND;
+ } else {
+ LOGGER.debug ("VNFVolumes found " + vfModuleId.value + ", status=" + status.value);
+ qryResp.setVolumeGroupStatus(status.value);
+ qryResp.setVolumeGroupOutputs(outputs.value);
+ }
+ LOGGER.debug("Query queryVNFVolumes exit");
+ return Response
+ .status(respStatus)
+ .entity(new GenericEntity<QueryVolumeGroupResponse>(qryResp) {})
+ .build();
+ } catch (VnfException e) {
+ LOGGER.error(MessageEnum.RA_QUERY_VNF_ERR, aaiVolumeGroupId, "", "queryVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException - queryVNFVolumes", e);
+ VolumeGroupExceptionResponse excResp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.FALSE, null);
+ LOGGER.debug("Query queryVNFVolumes exit");
+ return Response
+ .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
+ .entity(new GenericEntity<VolumeGroupExceptionResponse>(excResp) {})
+ .build();
+ }
+ }
+ public static Map<String, String> testMap() {
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("mickey", "7");
+ m.put("clyde", "10");
+ m.put("wayne", "99");
+ return m;
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfAlreadyExists.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfAlreadyExists.java
new file mode 100644
index 0000000000..7cec0cd99e
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfAlreadyExists.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+/**
+ * This class reports an exception when trying to create a VNF when another
+ * VNF of the same name already exists in the target cloud/tenant. Note that
+ * the createVnf method suppresses this exception by default.
+ *
+ *
+ */
+@WebFault (name="VnfAlreadyExists", faultBean="org.openecomp.mso.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://com.att.mso/vnf")
+public class VnfAlreadyExists extends VnfException {
+
+ private static final long serialVersionUID = 1L;
+
+ public VnfAlreadyExists (String name, String cloudId, String tenantId, String vnfId) {
+ super("VNF " + name + " already exists in cloud/tenant " + cloudId + "/" + tenantId + " with ID " + vnfId);
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfException.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfException.java
new file mode 100644
index 0000000000..ceef76b468
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfException.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.openecomp.mso.openstack.exceptions.MsoException;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * This class simply extends Exception (without addition additional functionality)
+ * to provide an identifier for VNF related exceptions on create, delete, query.
+ *
+ *
+ */
+@WebFault (name="VnfException", faultBean="org.openecomp.mso.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://com.att.mso/vnf")
+public class VnfException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private VnfExceptionBean faultInfo;
+
+ public VnfException (String msg) {
+ super(msg);
+ faultInfo = new VnfExceptionBean (msg);
+ }
+
+ public VnfException (Throwable e) {
+ super(e);
+ faultInfo = new VnfExceptionBean (e.getMessage());
+ }
+
+ public VnfException (String msg, Throwable e) {
+ super (msg, e);
+ faultInfo = new VnfExceptionBean (msg);
+ }
+
+ public VnfException (String msg, MsoExceptionCategory category) {
+ super(msg);
+ faultInfo = new VnfExceptionBean (msg, category);
+ }
+
+ public VnfException (String msg, MsoExceptionCategory category, Throwable e) {
+ super (msg, e);
+ faultInfo = new VnfExceptionBean (msg, category);
+ }
+
+ public VnfException (MsoException e) {
+ super (e);
+ faultInfo = new VnfExceptionBean (e.getContextMessage(), e.getCategory());
+ }
+
+ public VnfExceptionBean getFaultInfo() {
+ return faultInfo;
+ }
+
+ public void setFaultInfo(VnfExceptionBean faultInfo) {
+ this.faultInfo = faultInfo;
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfExceptionBean.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfExceptionBean.java
new file mode 100644
index 0000000000..15918eabb8
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfExceptionBean.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf.exceptions;
+
+
+import java.io.Serializable;
+
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * Jax-WS Fault Bean for Vnf Exception
+ */
+public class VnfExceptionBean implements Serializable {
+
+ private static final long serialVersionUID = -5699310749783790095L;
+
+ private String message;
+ private MsoExceptionCategory category;
+ private Boolean rolledBack;
+
+ public VnfExceptionBean () {}
+
+ public VnfExceptionBean (String message) {
+ this.message = message;
+ }
+
+ public VnfExceptionBean (String message, MsoExceptionCategory category) {
+ this.message = message;
+ this.category = category;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public MsoExceptionCategory getCategory () {
+ return category;
+ }
+
+ public void setCategory (MsoExceptionCategory category) {
+ this.category = category;
+ }
+
+ public Boolean isRolledBack() {
+ return rolledBack;
+ }
+
+ public void setRolledBack(Boolean rolledBack) {
+ this.rolledBack = rolledBack;
+ }
+}
diff --git a/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfNotFound.java b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfNotFound.java
new file mode 100644
index 0000000000..3c27d03daa
--- /dev/null
+++ b/adapters/mso-vnf-adapter/src/main/java/org/openecomp/mso/adapters/vnf/exceptions/VnfNotFound.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.vnf.exceptions;
+
+
+import javax.xml.ws.WebFault;
+
+import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
+
+/**
+ * This class reports an exception when trying to update a Network that does
+ * not exist in the target cloud/tenant. Note that deleteNetwork suppresses
+ * this exception (deletion of non-existent network is considered a success).
+ *
+ *
+ */
+@WebFault (name="VnfNotFound", faultBean="org.openecomp.mso.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://com.att.mso/vnf")
+public class VnfNotFound extends VnfException {
+
+ private static final long serialVersionUID = 1L;
+
+ public VnfNotFound (String cloudId, String tenantId, String vnfName) {
+ super("VNF " + vnfName + " not found in cloud/tenant " + cloudId + "/" + tenantId);
+ }
+}