summaryrefslogtreecommitdiffstats
path: root/adapters/mso-openstack-adapters/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/mso-openstack-adapters/src/main/java')
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/BpelRestClient.java298
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRef.java75
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRefSeq.java66
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnet.java214
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoute.java67
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoutes.java58
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetIp.java59
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetPool.java68
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapter.java222
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsync.java106
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsyncImpl.java698
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterImpl.java2125
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/NetworkAdapterRest.java671
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotification.java437
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotificationResponse.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotification.java181
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotificationResponse.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoExceptionCategory.java61
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoRequest.java106
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify.java191
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify_Service.java110
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkRollback.java370
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkStatus.java65
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/ObjectFactory.java298
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotification.java497
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotificationResponse.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotification.java154
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotificationResponse.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotification.java383
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotificationResponse.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/package-info.java21
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkException.java80
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkExceptionBean.java73
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java190
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/MsoOpenstackAdaptersApplication.java73
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/WebSecurityConfigImpl.java51
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapter.java77
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapterImpl.java295
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/TenantAdapterRest.java345
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantAlreadyExists.java45
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantException.java75
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantExceptionBean.java64
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/GenericValetResponse.java71
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/ValetClient.java326
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/HeatRequest.java125
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmRequest.java65
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmResponse.java30
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateRequest.java134
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateResponse.java70
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteRequest.java84
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteResponse.java66
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackRequest.java81
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackResponse.java29
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetStatus.java81
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateRequest.java134
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateResponse.java71
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vdu/mapper/VfModuleCustomizationToVduMapper.java127
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/BpelRestClient.java296
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/CSAR.java192
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapter.java147
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsync.java105
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsyncImpl.java666
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java2347
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfCloudifyAdapterImpl.java1218
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java1229
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VfRollback.java137
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRest.java691
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java94
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestV2.java704
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRest.java646
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRestV2.java648
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/CreateVnfNotification.java410
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/DeleteVnfNotification.java154
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoExceptionCategory.java61
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoRequest.java106
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/ObjectFactory.java208
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/QueryVnfNotification.java437
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/RollbackVnfNotification.java154
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/UpdateVnfNotification.java383
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify.java177
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify_Service.java110
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfRollback.java198
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfStatus.java61
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/package-info.java21
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfAlreadyExists.java42
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfException.java80
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfExceptionBean.java74
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfNotFound.java41
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduBlueprint.java90
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduInfo.java130
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduPlugin.java248
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduStatus.java37
92 files changed, 23060 insertions, 0 deletions
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/BpelRestClient.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/BpelRestClient.java
new file mode 100644
index 0000000000..cf11ab94c1
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/BpelRestClient.java
@@ -0,0 +1,298 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import java.security.GeneralSecurityException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.annotation.PostConstruct;
+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.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.utils.CryptoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+/**
+ * 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.onap.so.adapters.vnf.bpelauth encrypted authorization string to send to BEPL engine
+ * org.onap.so.adapters.vnf.sockettimeout socket timeout value
+ * org.onap.so.adapters.vnf.connecttimeout connect timeout value
+ * org.onap.so.adapters.vnf.retrycount number of times to retry failed connections
+ * org.onap.so.adapters.vnf.retryinterval interval (in seconds) between retries
+ * org.onap.so.adapters.vnf.retrylist list of response codes that will trigger a retry (the special code
+ * 900 means "connection was not established")
+ */
+@Component("NetworkBpel")
+@Scope("prototype")
+public class BpelRestClient {
+ public static final String MSO_PROP_NETWORK_ADAPTER = "MSO_PROP_NETWORK_ADAPTER";
+ private static final String PROPERTY_DOMAIN = "org.onap.so.adapters.network";
+ 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, BpelRestClient.class);
+
+ @Autowired
+ private Environment env;
+ /** 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_NETWORK_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 = "";
+
+ }
+
+ @PostConstruct
+ protected void init() {
+
+ socketTimeout = env.getProperty(SOCKET_TIMEOUT_PROPERTY, Integer.class, DEFAULT_SOCKET_TIMEOUT);
+ connectTimeout = env.getProperty(CONN_TIMEOUT_PROPERTY, Integer.class, DEFAULT_CONNECT_TIMEOUT);
+ retryCount = env.getProperty(RETRY_COUNT_PROPERTY, Integer.class, DEFAULT_RETRY_COUNT);
+ retryInterval = env.getProperty(RETRY_INTERVAL_PROPERTY, Integer.class, DEFAULT_RETRY_INTERVAL);
+ setRetryList(env.getProperty(RETRY_LIST_PROPERTY, DEFAULT_RETRY_LIST));
+ credentials = getEncryptedProperty(BPEL_AUTH_PROPERTY, DEFAULT_CREDENTIALS, ENCRYPTION_KEY);
+ }
+
+ 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) {
+ int retCnt = 0;
+ if (retryCount < 0)
+ retCnt = DEFAULT_RETRY_COUNT;
+ this.retryCount = retCnt;
+ }
+
+ 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.isEmpty())
+ return "";
+ String t = retryList.toString();
+ return t.substring(1, t.length()-1);
+ }
+
+ public void setRetryList(String retryList) {
+ Set<Integer> s = new TreeSet<>();
+ for (String t : retryList.split("[, ]")) {
+ try {
+ s.add(Integer.parseInt(t));
+ } catch (NumberFormatException x) {
+ LOGGER.debug("Exception while parsing", x);
+ }
+ }
+ 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.DataError, "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) {
+ LOGGER.debug("Exception while Thread sleep", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ private void debug(String m) {
+ LOGGER.debug(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.AvailabilityError, "Exception sending Bpel notification", e);
+ lastResponseCode = 900;
+ lastResponse = "";
+ }
+ LOGGER.debug("Response code from BPEL server: "+lastResponseCode);
+ LOGGER.debug("Response body is: "+lastResponse);
+ }
+
+ private String getEncryptedProperty(String key, String defaultValue, String encryptionKey) {
+ if (env.getProperty(key) != null) {
+ try {
+ return CryptoUtils.decrypt(env.getProperty(key), encryptionKey);
+ } catch (GeneralSecurityException e) {
+ LOGGER.debug("Exception while decrypting property: " + env.getProperty(key), e);
+ }
+ }
+ return defaultValue;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRef.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRef.java
new file mode 100644
index 0000000000..46fb651afe
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRef.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ContrailPolicyRef {
+ private static final MsoLogger logger = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, ContrailPolicyRef.class);
+
+ @JsonProperty("network_policy_refs_data_sequence")
+ private ContrailPolicyRefSeq seq;
+
+ public JsonNode toJsonNode()
+ {
+ JsonNode node = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ node = mapper.convertValue(this, JsonNode.class);
+ }
+ catch (Exception e)
+ {
+ logger.error (MessageEnum.RA_MARSHING_ERROR, "Error creating JsonString for Contrail Policy Ref", "", "", MsoLogger.ErrorCode.SchemaError, "Exception creating JsonString for Contrail Policy Ref", e);
+ }
+
+ return node;
+ }
+
+ public String toJsonString()
+ {
+ String jsonString = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ jsonString = mapper.writeValueAsString(this);
+ }
+ catch (Exception e)
+ {
+ logger.error (MessageEnum.RA_MARSHING_ERROR, "Error creating JsonString for Contrail Policy Ref", "", "", MsoLogger.ErrorCode.SchemaError, "Exception creating JsonString for Contrail Policy Ref", e);
+ }
+
+ return jsonString;
+ }
+
+ public void populate(String major, String minor)
+ {
+ seq = new ContrailPolicyRefSeq(major, minor);
+ return;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRefSeq.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRefSeq.java
new file mode 100644
index 0000000000..17d4a743dc
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailPolicyRefSeq.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ContrailPolicyRefSeq {
+
+ @JsonProperty("network_policy_refs_data_sequence_major")
+ private String major;
+
+ @JsonProperty("network_policy_refs_data_sequence_minor")
+ private String minor;
+
+ public ContrailPolicyRefSeq() {
+ /* To be done */
+ }
+
+ public ContrailPolicyRefSeq(String major, String minor) {
+ super();
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public String getMajor() {
+ return major;
+ }
+
+ public void setMajor(String major) {
+ this.major = major;
+ }
+
+ public String getMinor() {
+ return minor;
+ }
+
+ public void setMinor(String minor) {
+ this.minor = minor;
+ }
+
+ @Override
+ public String toString() {
+ return "ContrailPolicyRefSeq [major=" + major + ", minor=" + minor
+ + "]";
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnet.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnet.java
new file mode 100644
index 0000000000..019963b242
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnet.java
@@ -0,0 +1,214 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.HostRoute;
+import org.onap.so.openstack.beans.Pool;
+import org.onap.so.openstack.beans.Subnet;
+import org.onap.so.openstack.utils.MsoCommonUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ContrailSubnet {
+ private static final MsoLogger logger = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, ContrailSubnet.class);
+ @Autowired
+ private MsoCommonUtils msoCommonUtils;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet")
+ private ContrailSubnetIp subnet = new ContrailSubnetIp();
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_default_gateway")
+ private String defaultGateway;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_name")
+ private String subnetName;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_enable_dhcp")
+ private Boolean enableDhcp;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_addr_from_start")
+ private Boolean addrFromStart = true;
+ /** future - leave this commented
+ private String subnet_uuid;
+ private String dns_server_address;
+ private List<String> dns_nameservers;
+ private String dhcp_option_list;
+ **/
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_allocation_pools")
+ private List<ContrailSubnetPool> allocationPools = new ArrayList <> ();
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_host_routes")
+ private final ContrailSubnetHostRoutes host_routes = new ContrailSubnetHostRoutes();
+
+ public ContrailSubnet() {
+ super();
+ }
+
+ public String getDefaultGateway() {
+ return defaultGateway;
+ }
+
+ public void setDefaultGateway(String defaultGateway) {
+ this.defaultGateway = defaultGateway;
+ }
+
+ public ContrailSubnetIp getSubnet() {
+ return subnet;
+ }
+
+ public void setSubnet(ContrailSubnetIp subnet) {
+ this.subnet = subnet;
+ }
+
+ public Boolean isEnableDhcp() {
+ return enableDhcp;
+ }
+
+ public void setEnableDhcp(Boolean enableDhcp) {
+ this.enableDhcp = enableDhcp;
+ }
+
+ public String getSubnetName() {
+ return subnetName;
+ }
+
+ public void setSubnetName(String subnetName) {
+ this.subnetName = subnetName;
+ }
+
+ public List<ContrailSubnetPool> getAllocationPools() {
+ return allocationPools;
+ }
+
+ public void setPools(List<ContrailSubnetPool> allocationPools) {
+ this.allocationPools = allocationPools;
+ }
+
+ public Boolean isAddrFromStart() {
+ return addrFromStart;
+ }
+
+ public void setAddrFromStart(Boolean addrFromStart) {
+ this.addrFromStart = addrFromStart;
+ }
+
+ public JsonNode toJsonNode()
+ {
+ JsonNode node = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ node = mapper.convertValue(this, JsonNode.class);
+ }
+ catch (Exception e)
+ {
+ String error = "Error creating JsonNode for Contrail Subnet:" + subnetName;
+ logger.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.SchemaError, "Exception creating JsonNode for Contrail Subnet", e);
+ }
+
+ return node;
+ }
+
+ public String toJsonString()
+ {
+ String jsonString = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ jsonString = mapper.writeValueAsString(this);
+ }
+ catch (Exception e)
+ {
+ String error = "Error creating JsonString for Contrail Subnet:" + subnetName;
+ logger.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.SchemaError, "Exception creating JsonString for Contrail Subnet", e);
+ }
+
+ return jsonString;
+ }
+ //poulate contrail subnet with input(from bopel) subnet
+ public void populateWith(Subnet inputSubnet)
+ {
+ if (inputSubnet != null)
+ {
+ if (!msoCommonUtils.isNullOrEmpty(inputSubnet.getSubnetName()))
+ subnetName = inputSubnet.getSubnetName();
+ else
+ subnetName = inputSubnet.getSubnetId();
+ enableDhcp = inputSubnet.getEnableDHCP();
+ defaultGateway = inputSubnet.getGatewayIp();
+ if (!msoCommonUtils.isNullOrEmpty(inputSubnet.getCidr()) )
+ {
+ int idx = inputSubnet.getCidr().indexOf("/");
+ if (idx != -1)
+ {
+ subnet.setIpPrefix(inputSubnet.getCidr().substring(0, idx));
+ subnet.setIpPrefixLen(inputSubnet.getCidr().substring(idx+1));
+ }
+ }
+ if (inputSubnet.getAllocationPools() != null)
+ {
+ for (Pool pool : inputSubnet.getAllocationPools())
+ {
+ if ( !msoCommonUtils.isNullOrEmpty(pool.getStart()) && !msoCommonUtils.isNullOrEmpty(pool.getEnd()) )
+ {
+ ContrailSubnetPool csp = new ContrailSubnetPool();
+ csp.populateWith(pool);
+ allocationPools.add (csp);
+ }
+ }
+ }
+ if (inputSubnet.getHostRoutes() != null)
+ {
+ List<ContrailSubnetHostRoute> hrList = host_routes.getHost_routes();
+ for (HostRoute hr : inputSubnet.getHostRoutes())
+ {
+ if ( !msoCommonUtils.isNullOrEmpty(hr.getPrefix()) || !msoCommonUtils.isNullOrEmpty(hr.getNextHop()) )
+ {
+ ContrailSubnetHostRoute cshr = new ContrailSubnetHostRoute();
+ cshr.populateWith(hr);
+ hrList.add (cshr);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder ();
+ for (ContrailSubnetPool pool : allocationPools)
+ {
+ buf.append(pool.toString());
+ }
+ return "ContrailSubnet [subnet=" + subnet.toString() + " default_gateway=" + defaultGateway
+ + " enable_dhcp=" + enableDhcp + " addr_from_start=" + addrFromStart + " subnet_name=" + subnetName + " allocation_pools=" + buf + " ]";
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoute.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoute.java
new file mode 100644
index 0000000000..d938306c48
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoute.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import org.onap.so.openstack.beans.HostRoute;
+import com.fasterxml.jackson.annotation.JsonProperty;
+public class ContrailSubnetHostRoute {
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_host_routes_route_prefix")
+ private String prefix;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_host_routes_route_next_hop")
+ private String nextHop;
+
+ public ContrailSubnetHostRoute() {
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getNextHop() {
+ return nextHop;
+ }
+
+ public void setNextHop(String nextHop) {
+ this.nextHop = nextHop;
+ }
+
+ public void populateWith(HostRoute hostRoute)
+ {
+ if (hostRoute != null)
+ {
+ prefix = hostRoute.getPrefix();
+ nextHop = hostRoute.getNextHop();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ContrailSubnetHostRoute [prefix=" + prefix + ", nextHop=" + nextHop + "]";
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoutes.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoutes.java
new file mode 100644
index 0000000000..9b07e20267
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetHostRoutes.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import org.onap.so.openstack.beans.HostRoute;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+public class ContrailSubnetHostRoutes {
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_host_routes_route")
+ private List<ContrailSubnetHostRoute> host_routes = new ArrayList <ContrailSubnetHostRoute> ();
+
+ public ContrailSubnetHostRoutes() {
+ }
+
+ public List<ContrailSubnetHostRoute> getHost_routes() {
+ return host_routes;
+ }
+
+ public void setHost_routes(List<ContrailSubnetHostRoute> host_routes) {
+ this.host_routes = host_routes;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder ();
+ if (host_routes != null)
+ {
+ for (ContrailSubnetHostRoute hr : host_routes)
+ {
+ buf.append(hr.toString());
+ }
+ }
+ return "ContrailSubnetHostRoutes [" + buf.toString() + "]";
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetIp.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetIp.java
new file mode 100644
index 0000000000..91d089eb33
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetIp.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ContrailSubnetIp {
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_ip_prefix")
+ private String ipPrefix;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_ip_prefix_len")
+ private String ipPrefixLen;
+
+ public ContrailSubnetIp() {
+ /* Empty constructor */
+ }
+
+ public String getIpPrefix() {
+ return ipPrefix;
+ }
+
+ public void setIpPrefix(String ipPrefix) {
+ this.ipPrefix = ipPrefix;
+ }
+
+ public String getIpPrefixLen() {
+ return ipPrefixLen;
+ }
+
+ public void setIpPrefixLen(String ipPrefixLen) {
+ this.ipPrefixLen = ipPrefixLen;
+ }
+
+ @Override
+ public String toString() {
+ return "ContrailSubnetIp [ip_prefix=" + ipPrefix + ", ip_prefix_len=" + ipPrefixLen + "]";
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetPool.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetPool.java
new file mode 100644
index 0000000000..710d0cc8fd
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/ContrailSubnetPool.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import org.onap.so.openstack.beans.Pool;
+import com.fasterxml.jackson.annotation.JsonProperty;
+public class ContrailSubnetPool {
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_allocation_pools_start")
+ private String start;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_allocation_pools_end")
+ private String end;
+
+ public ContrailSubnetPool() {
+ /* Empty constructor */
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public void populateWith(Pool pool)
+ {
+ if (pool != null)
+ {
+ start = pool.getStart();
+ end = pool.getEnd();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ContrailSubnetPool [start=" + start + ", end=" + end + "]";
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapter.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapter.java
new file mode 100644
index 0000000000..27829a6156
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapter.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import java.util.List;
+import java.util.Map;
+
+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.onap.so.adapters.network.exceptions.NetworkException;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.openstack.beans.NetworkRollback;
+import org.onap.so.openstack.beans.NetworkStatus;
+import org.onap.so.openstack.beans.RouteTarget;
+import org.onap.so.openstack.beans.Subnet;
+
+@WebService (name="NetworkAdapter", targetNamespace="http://org.onap.so/network")
+public interface MsoNetworkAdapter
+{
+ // TODO: Rename all of these to include Vlan in the service name? At least for the
+ // create and update calls, since they are specific to VLAN-based provider networks.
+
+ /**
+ * This is the "Create Network" Web Service Endpoint definition.
+ */
+ @WebMethod
+ public void createNetwork (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="physicalNetworkName") String physicalNetworkName,
+ @WebParam(name="vlans") List<Integer> vlans,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="networkId", mode=Mode.OUT) Holder<String> networkId,
+ @WebParam(name="neutronNetworkId", mode=Mode.OUT) Holder<String> neutronNetworkId,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+
+ @WebMethod
+ public void createNetworkContrail (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="routeTargets") List<RouteTarget> routeTargets,
+ @WebParam(name="shared") String shared,
+ @WebParam(name="external") String external,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @WebParam(name="policyFqdns") List<String> policyFqdns,
+ @WebParam(name="routeTableFqdns") List<String> routeTableFqdns,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="networkId", mode=Mode.OUT) Holder<String> networkId,
+ @WebParam(name="neutronNetworkId", mode=Mode.OUT) Holder<String> neutronNetworkId,
+ @WebParam(name="networkFqdn", mode=Mode.OUT) Holder<String> networkFqdn,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+
+ /**
+ * This is the "Update VLANs" Web Service Endpoint definition.
+ * This webservice replaces the set of VLANs on a network.
+ */
+ @WebMethod
+ public void updateNetwork (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="physicalNetworkName") @XmlElement(required=true) String physicalNetworkName,
+ @WebParam(name="vlans") @XmlElement(required=true) List<Integer> vlans,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+
+ @WebMethod
+ public void updateNetworkContrail (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="routeTargets") List<RouteTarget> routeTargets,
+ @WebParam(name="shared") String shared,
+ @WebParam(name="external") String external,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @WebParam(name="policyFqdns") List<String> policyFqdns,
+ @WebParam(name="routeTableFqdns") List<String> routeTableFqdns,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+
+ /**
+ * TODO:
+ * This is the "Add VLAN" Web Service Endpoint definition.
+ * This webservice adds a VLAN to a network.
+ * This service assumes that PO supports querying the current vlans in real time.
+ * Otherwise, the caller must have the complete list and should use updateVlans instead.
+ @WebMethod
+ public void addVlan (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="physicalNetworkName") @XmlElement(required=true) String physicalNetworkName,
+ @WebParam(name="vlan") @XmlElement(required=true) Integer vlan,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+ */
+
+ /**
+ * TODO:
+ * This is the "Remove VLAN" Web Service Endpoint definition.
+ * This webservice removes a VLAN from a network.
+ * This service assumes that PO supports querying the current vlans in real time.
+ * Otherwise, the caller must have the complete list and should use updateVlans instead.
+ *
+ * This service returns an indicator (noMoreVLans) if the VLAN that was removed was
+ * the last one on the network.
+ *
+ * It is not clear that Rollback will work for delete. The network can be
+ * recreated from the NetworkRollback object, but the network ID (and stack ID
+ * for Heat-based orchestration) will be different. The caller will need to know
+ * to update these identifiers in the inventory DB (A&AI).
+ @WebMethod
+ public void removeVlan (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="physicalNetworkName") @XmlElement(required=true) String physicalNetworkName,
+ @WebParam(name="vlan") @XmlElement(required=true) Integer vlan,
+ @WebParam(name="noMoreVlans", mode=Mode.OUT) Holder<Boolean> noMoreVlans,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<NetworkRollback> rollback )
+ throws NetworkException;
+ */
+
+ /**
+ * This is the "Query Network" Web Service Endpoint definition.
+ * TODO: Should this just return the NetworkInfo complete structure?
+ */
+ @WebMethod
+ public void queryNetwork (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkNameOrId") @XmlElement(required=true) String networkNameOrId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="networkExists", mode=Mode.OUT) Holder<Boolean> networkExists,
+ @WebParam(name="networkId", mode=Mode.OUT) Holder<String> networkId,
+ @WebParam(name="neutronNetworkId", mode=Mode.OUT) Holder<String> neutronNetworkId,
+ @WebParam(name="status", mode=Mode.OUT) Holder<NetworkStatus> status,
+ @WebParam(name="vlans", mode=Mode.OUT) Holder<List<Integer>> vlans,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap)
+ throws NetworkException;
+
+ @WebMethod
+ public void queryNetworkContrail (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkNameOrId") @XmlElement(required=true) String networkNameOrId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="networkExists", mode=Mode.OUT) Holder<Boolean> networkExists,
+ @WebParam(name="networkId", mode=Mode.OUT) Holder<String> networkId,
+ @WebParam(name="neutronNetworkId", mode=Mode.OUT) Holder<String> neutronNetworkId,
+ @WebParam(name="status", mode=Mode.OUT) Holder<NetworkStatus> status,
+ @WebParam(name="routeTargets", mode=Mode.OUT) Holder<List<RouteTarget>> routeTargets,
+ @WebParam(name="subnetIdMap", mode=Mode.OUT) Holder<Map<String, String>> subnetIdMap)
+ throws NetworkException;
+
+ /**
+ * This is the "Delete Network" Web Service endpoint definition.
+ */
+ @WebMethod
+ public void deleteNetwork (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="networkDeleted", mode=Mode.OUT) Holder<Boolean> networkDeleted)
+ throws NetworkException;
+
+ /**
+ * This is the "Rollback Network" Web Service endpoint definition.
+ */
+ @WebMethod
+ public void rollbackNetwork (@WebParam(name="rollback") @XmlElement(required=true) NetworkRollback rollback)
+ throws NetworkException;
+
+ @WebMethod
+ public void healthCheck ();
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsync.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsync.java
new file mode 100644
index 0000000000..99f590b773
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsync.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import java.util.List;
+
+import javax.jws.Oneway;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.openstack.beans.NetworkRollback;
+import org.onap.so.openstack.beans.Subnet;
+/**
+ * This webservice defines the Asynchronous versions of NETWORK adapter calls.
+ * The notification messages for final responses are documented elsewhere
+ * (by the client service WSDL).
+ *
+ */
+@WebService (name="NetworkAdapterAsync", targetNamespace="http://org.onap.so/networkA")
+public interface MsoNetworkAdapterAsync
+{
+ /**
+ * This is the "Create NETWORK" Web Service Endpoint definition.
+ */
+ @WebMethod
+ @Oneway
+ public void createNetworkA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="physicalNetworkName") String physicalNetworkName,
+ @WebParam(name="vlans") List<Integer> vlans,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @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 updateNetworkA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="physicalNetworkName") @XmlElement(required=true) String physicalNetworkName,
+ @WebParam(name="vlans") @XmlElement(required=true) List<Integer> vlans,
+ @WebParam(name="subnets") List<Subnet> subnets,
+ @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 queryNetworkA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkNameOrId") @XmlElement(required=true) String networkNameOrId,
+ @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 deleteNetworkA (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="networkType") @XmlElement(required=true) String networkType,
+ @WebParam(name="modelCustomizationUuid") String modelCustomizationUuid,
+ @WebParam(name="networkId") @XmlElement(required=true) String networkId,
+ @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 rollbackNetworkA (@WebParam(name="rollback") @XmlElement(required=true) NetworkRollback 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-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsyncImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsyncImpl.java
new file mode 100644
index 0000000000..b483d40b8a
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterAsyncImpl.java
@@ -0,0 +1,698 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+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.onap.so.adapters.network.async.client.CreateNetworkNotification;
+import org.onap.so.adapters.network.async.client.MsoExceptionCategory;
+import org.onap.so.adapters.network.async.client.NetworkAdapterNotify;
+import org.onap.so.adapters.network.async.client.NetworkAdapterNotify_Service;
+import org.onap.so.adapters.network.async.client.QueryNetworkNotification;
+import org.onap.so.adapters.network.async.client.UpdateNetworkNotification;
+import org.onap.so.adapters.network.exceptions.NetworkException;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.NetworkRollback;
+import org.onap.so.openstack.beans.NetworkStatus;
+import org.onap.so.openstack.beans.Subnet;
+import org.onap.so.utils.CryptoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+@WebService(serviceName = "NetworkAdapterAsync", endpointInterface = "org.onap.so.adapters.network.MsoNetworkAdapterAsync", targetNamespace = "http://org.onap.so/networkA")
+public class MsoNetworkAdapterAsyncImpl implements MsoNetworkAdapterAsync {
+
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoNetworkAdapterAsyncImpl.class);
+ private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String BPEL_AUTH_PROP = "org.onap.so.adapters.network.bpelauth";
+ private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private MsoNetworkAdapter networkAdapter;
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheckA () {
+ LOGGER.debug ("Health check call in Network Adapter");
+ }
+
+ /**
+ * This is the "Create Network" web service implementation.
+ * It will create a new Network of the requested type in the specified cloud
+ * and tenant. The tenant must exist at the time this service is called.
+ *
+ * If a network with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * There will be a pre-defined set of network types defined in the MSO Catalog.
+ * All such networks will have a similar configuration, based on the allowable
+ * Openstack networking definitions. This includes basic networks, provider
+ * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
+ *
+ * Initially, all provider networks must be "vlan" type, and multiple segments in
+ * a multi-provider network must be multiple VLANs on the same physical network.
+ *
+ * This service supports two modes of Network creation/update:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition. All Heat-based templates must support some subset of
+ * the same input parameters: network_name, physical_network, vlan(s).
+ *
+ * The method returns the network ID and a NetworkRollback object. This latter
+ * object can be passed as-is to the rollbackNetwork operation to undo everything
+ * that was created. This is useful if a network is successfully created but
+ * the orchestration fails on a subsequent operation.
+ */
+ @Override
+ public void createNetworkA (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ Boolean failIfExists,
+ Boolean backout,
+ List <Subnet> subnets,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateNetworkA");
+ LOGGER.debug ("Async Create Network: " + networkName
+ + " of type "
+ + networkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+ // Use the synchronous method to perform the actual Create
+
+
+ // Synchronous Web Service Outputs
+ Holder <String> networkId = new Holder <> ();
+ Holder <String> neutronNetworkId = new Holder <> ();
+ Holder <NetworkRollback> networkRollback = new Holder <> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <> ();
+
+ try {
+ networkAdapter.createNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ failIfExists,
+ backout,
+ subnets,
+ msoRequest,
+ networkId,
+ neutronNetworkId,
+ subnetIdMap,
+ networkRollback);
+ } catch (NetworkException e) {
+ LOGGER.debug ("Got a NetworkException on createNetwork: ", e);
+ MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = MsoExceptionCategory.fromValue (e.getFaultInfo ().getCategory ().name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.createNetworkNotification (messageId, false, exCat, eMsg, null, null, null, null);
+ } catch (Exception e1) {
+ error = "Error sending createNetwork notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending createNetwork notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+ LOGGER.debug ("Async Create Network:Name " + networkName + " physicalNetworkName:" + physicalNetworkName);
+ // Build and send Asynchronous response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.createNetworkNotification (messageId,
+ true,
+ null,
+ null,
+ networkId.value,
+ neutronNetworkId.value,
+ copyCreateSubnetIdMap (subnetIdMap),
+ copyNrb (networkRollback));
+ } catch (Exception e) {
+ error = "Error sending createNetwork notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending createNetwork notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+
+ /**
+ * This is the "Update Network" web service implementation.
+ * It will update an existing Network of the requested type in the specified cloud
+ * and tenant. The typical use will be to replace the VLANs with the supplied
+ * list (to add or remove a VLAN), but other properties may be updated as well.
+ *
+ * There will be a pre-defined set of network types defined in the MSO Catalog.
+ * All such networks will have a similar configuration, based on the allowable
+ * Openstack networking definitions. This includes basic networks, provider
+ * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
+ *
+ * Initially, all provider networks must currently be "vlan" type, and multi-provider
+ * networks must be multiple VLANs on the same physical network.
+ *
+ * This service supports two modes of Network update:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition. All Heat-based templates must support some subset of
+ * the same input parameters: network_name, physical_network, vlan, segments.
+ *
+ * The method returns a NetworkRollback object. This object can be passed
+ * as-is to the rollbackNetwork operation to undo everything that was updated.
+ * This is useful if a network is successfully updated but orchestration
+ * fails on a subsequent operation.
+ */
+ @Override
+ public void updateNetworkA (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <Subnet> subnets,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+
+ String serviceName = "UpdateNetworkA";
+ MsoLogger.setServiceName (serviceName);
+ MsoLogger.setLogContext (msoRequest);
+ LOGGER.debug ("Async Update Network: " + networkId
+ + " of type "
+ + networkType
+ + "in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+ // Use the synchronous method to perform the actual Create
+
+
+ // Synchronous Web Service Outputs
+ Holder <NetworkRollback> networkRollback = new Holder <> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <> ();
+
+ try {
+ networkAdapter.updateNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkId,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ subnets,
+ msoRequest,
+ subnetIdMap,
+ networkRollback);
+ MsoLogger.setServiceName (serviceName);
+ } catch (NetworkException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Got a NetworkException on updateNetwork: ", e);
+ MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = MsoExceptionCategory.fromValue (e.getFaultInfo ().getCategory ().name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.updateNetworkNotification (messageId, false, exCat, eMsg, null, copyNrb (networkRollback));
+ } catch (Exception e1) {
+ error = "Error sending updateNetwork notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending updateNetwork notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+ LOGGER.debug ("Async Update Network:Name " + networkName + " NetworkId:" + networkId);
+ // Build and send Asynchronous response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.updateNetworkNotification (messageId,
+ true,
+ null,
+ null,
+ copyUpdateSubnetIdMap (subnetIdMap),
+ copyNrb (networkRollback));
+ } catch (Exception e) {
+ error = "Error sending updateNotification request" + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending updateNotification request", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+
+ /**
+ * This is the queryNetwork method. It returns the existence and status of
+ * the specified network, along with its Neutron UUID and list of VLANs.
+ * This method attempts to find the network using both Heat and Neutron.
+ * Heat stacks are first searched based on the provided network name/id.
+ * If none is found, the Neutron is directly queried.
+ */
+ @Override
+ public void queryNetworkA (String cloudSiteId,
+ String tenantId,
+ String networkNameOrId,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+
+ MsoLogger.setLogContext (msoRequest);
+ String serviceName = "QueryNetworkA";
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Async Query Network " + networkNameOrId + " in " + cloudSiteId + "/" + tenantId);
+
+ // Use the synchronous method to perform the actual Create
+
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> networkExists = new Holder <> ();
+ Holder <String> networkId = new Holder <> ();
+ Holder <String> neutronNetworkId = new Holder <> ();
+ Holder <NetworkStatus> status = new Holder <> ();
+ Holder <List <Integer>> vlans = new Holder <> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <> ();
+
+ try {
+ networkAdapter.queryNetwork (cloudSiteId,
+ tenantId,
+ networkNameOrId,
+ msoRequest,
+ networkExists,
+ networkId,
+ neutronNetworkId,
+ status,
+ vlans,
+ subnetIdMap);
+ MsoLogger.setServiceName (serviceName);
+ } catch (NetworkException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Got a NetworkException on createNetwork: ", e);
+ MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = MsoExceptionCategory.fromValue (e.getFaultInfo ().getCategory ().name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.queryNetworkNotification (messageId, false, exCat, eMsg, null, null, null, null, null, null);
+ } catch (Exception e1) {
+ error = "Error sending createNetwork notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending createNetwork notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+ LOGGER.debug ("Async Query Network:NameOrId " + networkNameOrId + " tenantId:" + tenantId);
+ // Build and send Asynchronous response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ org.onap.so.adapters.network.async.client.NetworkStatus networkS = org.onap.so.adapters.network.async.client.NetworkStatus.fromValue (status.value.name ());
+ notifyPort.queryNetworkNotification (messageId,
+ true,
+ null,
+ null,
+ networkExists.value,
+ networkId.value,
+ neutronNetworkId.value,
+ networkS,
+ vlans.value,
+ copyQuerySubnetIdMap (subnetIdMap));
+ } catch (Exception e) {
+ error = "Error sending createNetwork notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending createNetwork notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+
+ /**
+ * This is the "Delete Network" web service implementation.
+ * It will delete a Network in the specified cloud and tenant.
+ *
+ * If the network is not found, it is treated as a success.
+ *
+ * This service supports two modes of Network creation/update/delete:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition.
+ *
+ * For Heat-based orchestration, the networkId should be the stack ID.
+ * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
+ *
+ * The method returns nothing on success. Rollback is not possible for delete
+ * commands, so any failure on delete will require manual fallout in the client.
+ */
+ @Override
+ public void deleteNetworkA (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ MsoLogger.setLogContext (msoRequest);
+ String serviceName = "DeleteNetworkA";
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Async Delete Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
+
+ // Use the synchronous method to perform the actual Create
+
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> networkDeleted = new Holder <> ();
+
+ try {
+ networkAdapter.deleteNetwork (cloudSiteId, tenantId, networkType, modelCustomizationUuid, networkId, msoRequest, networkDeleted);
+ MsoLogger.setServiceName (serviceName);
+ } catch (NetworkException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Got a NetworkException on createNetwork: ", e);
+ MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = MsoExceptionCategory.fromValue (e.getFaultInfo ().getCategory ().name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.deleteNetworkNotification (messageId, false, exCat, eMsg, null);
+ } catch (Exception e1) {
+ error = "Error sending createNetwork notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending createNetwork notification", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+ LOGGER.debug ("Async Delete NetworkId: " + networkId + " tenantId:" + tenantId);
+ // Build and send Asynchronous response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.deleteNetworkNotification (messageId, true, null, null, networkDeleted.value);
+ } catch (Exception e) {
+ error = "Error sending deleteNetwork notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception sending deleteNetwork notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ 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 rollbackNetwork
+ * operation to undo the creation.
+ *
+ * The rollback includes removing the VNF and deleting the tenant if the
+ * tenant did not exist prior to the VNF creation.
+ */
+ @Override
+ public void rollbackNetworkA (NetworkRollback rollback, String messageId, String notificationUrl) {
+ String error;
+ String serviceName = "RollbackNetworkA";
+ MsoLogger.setServiceName (serviceName);
+ // rollback may be null (e.g. if network already existed when Create was called)
+ if (rollback == null) {
+ LOGGER.warn (MessageEnum.RA_ROLLBACK_NULL, "", "", MsoLogger.ErrorCode.SchemaError, "Rollback is null");
+ return;
+ }
+
+ MsoLogger.setLogContext (rollback.getMsoRequest ());
+ LOGGER.info (MessageEnum.RA_ASYNC_ROLLBACK, rollback.getNetworkStackId (), "", "");
+ // Use the synchronous method to perform the actual Create
+
+
+ try {
+ networkAdapter.rollbackNetwork (rollback);
+ MsoLogger.setServiceName (serviceName);
+ } catch (NetworkException e) {
+ MsoLogger.setServiceName (serviceName);
+ LOGGER.debug ("Got a NetworkException on rollbackNetwork: ", e);
+ // Build and send Asynchronous error response
+ MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = MsoExceptionCategory.fromValue (e.getFaultInfo ().getCategory ().name ());
+ } catch (Exception e1) {
+ LOGGER.error (MessageEnum.RA_FAULT_INFO_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception in get fault info", e1);
+ }
+ // Build and send Asynchronous error response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.rollbackNetworkNotification (rollback.getMsoRequest ().getRequestId (), false, exCat, eMsg);
+ } catch (Exception e1) {
+ error = "Error sending createNetwork notification " + e1.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception in sending createNetwork notification ", e1);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+ LOGGER.debug ("Async Rollback NetworkId: " + rollback.getNetworkStackId () + " tenantId:" + rollback.getTenantId ());
+ // Build and send Asynchronous response
+ try {
+ NetworkAdapterNotify notifyPort = getNotifyEP (notificationUrl);
+ notifyPort.rollbackNetworkNotification (rollback.getMsoRequest ().getRequestId (), true, null, null);
+ } catch (Exception e) {
+ error = "Error sending rollbackNetwork notification " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception in sending rollbackNetwork notification", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error);
+ }
+ return;
+ }
+
+ private org.onap.so.adapters.network.async.client.NetworkRollback copyNrb (Holder <NetworkRollback> hNrb) {
+ org.onap.so.adapters.network.async.client.NetworkRollback cnrb = new org.onap.so.adapters.network.async.client.NetworkRollback ();
+
+ if (hNrb != null && hNrb.value != null) {
+ org.onap.so.adapters.network.async.client.MsoRequest cmr = new org.onap.so.adapters.network.async.client.MsoRequest ();
+
+ cnrb.setCloudId (hNrb.value.getCloudId ());
+ cmr.setRequestId (hNrb.value.getMsoRequest ().getRequestId ());
+ cmr.setServiceInstanceId (hNrb.value.getMsoRequest ().getServiceInstanceId ());
+ cnrb.setMsoRequest (cmr);
+ cnrb.setNetworkId (hNrb.value.getNetworkId ());
+ cnrb.setNetworkStackId (hNrb.value.getNetworkStackId ());
+ cnrb.setNeutronNetworkId (hNrb.value.getNeutronNetworkId ());
+ cnrb.setTenantId (hNrb.value.getTenantId ());
+ cnrb.setNetworkType (hNrb.value.getNetworkType ());
+ cnrb.setNetworkCreated (hNrb.value.getNetworkCreated ());
+ cnrb.setNetworkName (hNrb.value.getNetworkName ());
+ cnrb.setPhysicalNetwork (hNrb.value.getPhysicalNetwork ());
+ List <Integer> vlansc = cnrb.getVlans ();
+ List <Integer> vlansh = hNrb.value.getVlans ();
+ if (vlansh != null) {
+ vlansc.addAll (vlansh);
+ }
+ }
+ return cnrb;
+ }
+
+ private NetworkAdapterNotify getNotifyEP (String notificationUrl) {
+
+ URL warWsdlLoc = null;
+ try {
+ warWsdlLoc = Thread.currentThread ().getContextClassLoader ().getResource ("NetworkAdapterNotify.wsdl");
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.RA_WSDL_NOT_FOUND, "NetworkAdpaterNotify.wsdl", "", "", MsoLogger.ErrorCode.DataError, "Exception - WSDL not found", e);
+ }
+ if (warWsdlLoc == null) {
+ LOGGER.error (MessageEnum.RA_WSDL_NOT_FOUND, "NetworkAdpaterNotify.wsdl", "", "", MsoLogger.ErrorCode.DataError, "WSDL not found");
+ } else {
+ try {
+ LOGGER.debug ("NetworkAdpaterNotify.wsdl location:" + warWsdlLoc.toURI ().toString ());
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.RA_WSDL_URL_CONVENTION_EXC, "NetworkAdpaterNotify.wsdl", "", "", MsoLogger.ErrorCode.SchemaError, "Exception - WSDL URL convention", e);
+ }
+ }
+
+ NetworkAdapterNotify_Service notifySvc = new NetworkAdapterNotify_Service (warWsdlLoc,
+ new QName ("http://org.onap.so/networkNotify",
+ "networkAdapterNotify"));
+
+ NetworkAdapterNotify notifyPort = notifySvc.getMsoNetworkAdapterAsyncImplPort ();
+
+ BindingProvider bp = (BindingProvider) notifyPort;
+
+ URL epUrl = null;
+ try {
+ epUrl = new URL (notificationUrl);
+ } catch (MalformedURLException e1) {
+ LOGGER.error (MessageEnum.RA_INIT_NOTIF_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - init notification", e1);
+ }
+
+ if(null != epUrl) {
+ LOGGER.debug ("Notification Endpoint URL: " + epUrl.toExternalForm ());
+ bp.getRequestContext ().put (BindingProvider.ENDPOINT_ADDRESS_PROPERTY, epUrl.toExternalForm ());
+ }
+ else {
+ LOGGER.debug ("Notification Endpoint URL is NULL: ");
+ }
+
+ // authentication
+ try {
+ Map <String, Object> reqCtx = bp.getRequestContext ();
+ Map <String, List <String>> headers = new HashMap <> ();
+
+ String userCredentials = this.getEncryptedProperty (BPEL_AUTH_PROP, "", ENCRYPTION_KEY);
+
+ String basicAuth = "Basic " + DatatypeConverter.printBase64Binary (userCredentials.getBytes ());
+ reqCtx.put (MessageContext.HTTP_REQUEST_HEADERS, headers);
+ headers.put ("Authorization", Collections.singletonList (basicAuth));
+ } catch (Exception e) {
+ String error1 = "Unable to set authorization in callback request" + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_SET_CALLBACK_AUTH_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to set authorization in callback request", e);
+ alarmLogger.sendAlarm ("MsoInternalError", MsoAlarmLogger.CRITICAL, error1);
+ }
+
+ return notifyPort;
+ }
+
+ public String getEncryptedProperty(String key, String defaultValue, String encryptionKey) {
+ try {
+ return CryptoUtils.decrypt(this.environment.getProperty(key), encryptionKey);
+ } catch (GeneralSecurityException e) {
+ LOGGER.debug("Exception while decrypting property: " + this.environment.getProperty(key), e);
+ }
+ return defaultValue;
+
+ }
+
+ private CreateNetworkNotification.SubnetIdMap copyCreateSubnetIdMap (Holder <Map <String, String>> hMap) {
+
+ CreateNetworkNotification.SubnetIdMap subnetIdMap = new CreateNetworkNotification.SubnetIdMap ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <> ();
+ sMap = hMap.value;
+ CreateNetworkNotification.SubnetIdMap.Entry entry = new CreateNetworkNotification.SubnetIdMap.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ subnetIdMap.getEntry ().add (entry);
+ }
+ }
+ return subnetIdMap;
+ }
+
+ private UpdateNetworkNotification.SubnetIdMap copyUpdateSubnetIdMap (Holder <Map <String, String>> hMap) {
+
+ UpdateNetworkNotification.SubnetIdMap subnetIdMap = new UpdateNetworkNotification.SubnetIdMap ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <> ();
+ sMap = hMap.value;
+ UpdateNetworkNotification.SubnetIdMap.Entry entry = new UpdateNetworkNotification.SubnetIdMap.Entry ();
+
+ for (Map.Entry<String,String> mapEntry : sMap.entrySet ()) {
+ String key = mapEntry.getKey();
+ String value = mapEntry.getValue();
+ entry.setKey (key);
+ entry.setValue (value);
+ subnetIdMap.getEntry ().add (entry);
+ }
+ }
+ return subnetIdMap;
+ }
+
+ private QueryNetworkNotification.SubnetIdMap copyQuerySubnetIdMap (Holder <Map <String, String>> hMap) {
+
+ QueryNetworkNotification.SubnetIdMap subnetIdMap = new QueryNetworkNotification.SubnetIdMap ();
+
+ if (hMap != null && hMap.value != null) {
+ Map <String, String> sMap = new HashMap <> ();
+ sMap = hMap.value;
+ QueryNetworkNotification.SubnetIdMap.Entry entry = new QueryNetworkNotification.SubnetIdMap.Entry ();
+
+ for (Map.Entry<String,String> mapEntry : sMap.entrySet ()) {
+ String key = mapEntry.getKey();
+ String value = mapEntry.getValue();
+ entry.setKey (key);
+ entry.setValue (value);
+ subnetIdMap.getEntry ().add (entry);
+ }
+ }
+ return subnetIdMap;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterImpl.java
new file mode 100644
index 0000000000..f5a05b7333
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/MsoNetworkAdapterImpl.java
@@ -0,0 +1,2125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.onap.so.adapters.network.beans.ContrailPolicyRef;
+import org.onap.so.adapters.network.beans.ContrailPolicyRefSeq;
+import org.onap.so.adapters.network.beans.ContrailSubnet;
+import org.onap.so.adapters.network.exceptions.NetworkException;
+import org.onap.so.adapters.network.mappers.ContrailSubnetMapper;
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.CloudSite;
+import org.onap.so.db.catalog.beans.HeatTemplate;
+import org.onap.so.db.catalog.beans.NetworkResource;
+import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
+import org.onap.so.db.catalog.data.repository.NetworkResourceCustomizationRepository;
+import org.onap.so.db.catalog.data.repository.NetworkResourceRepository;
+import org.onap.so.db.catalog.utils.MavenLikeVersioning;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.HeatStatus;
+import org.onap.so.openstack.beans.NetworkInfo;
+import org.onap.so.openstack.beans.NetworkRollback;
+import org.onap.so.openstack.beans.NetworkStatus;
+import org.onap.so.openstack.beans.Pool;
+import org.onap.so.openstack.beans.RouteTarget;
+import org.onap.so.openstack.beans.StackInfo;
+import org.onap.so.openstack.beans.Subnet;
+import org.onap.so.openstack.exceptions.MsoAdapterException;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.onap.so.openstack.utils.MsoCommonUtils;
+import org.onap.so.openstack.utils.MsoHeatUtils;
+import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
+import org.onap.so.openstack.utils.MsoNeutronUtils;
+import org.onap.so.openstack.utils.MsoNeutronUtils.NetworkType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Component
+@Transactional
+@WebService(serviceName = "NetworkAdapter", endpointInterface = "org.onap.so.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.onap.so/network")
+public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
+
+ private static final String AIC3_NW_PROPERTY= "org.onap.so.adapters.network.aic3nw";
+ private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
+ private static final String VLANS = "vlans";
+ private static final String PHYSICAL_NETWORK = "physical_network";
+ private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
+ private static final String NETWORK_ID = "network_id";
+ private static final String NETWORK_FQDN = "network_fqdn";
+ private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
+ private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
+ private static final String NEUTRON_MODE = "NEUTRON";
+
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoNetworkAdapterImpl.class);
+ private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ @Autowired
+ private CloudConfig cloudConfig;
+ @Autowired
+ private Environment environment;
+ @Autowired
+ private MsoNeutronUtils neutron;
+ @Autowired
+ private MsoHeatUtils heat;
+ @Autowired
+ private MsoHeatUtilsWithUpdate heatWithUpdate;
+ @Autowired
+ private MsoCommonUtils commonUtils;
+
+ @Autowired
+ private NetworkResourceCustomizationRepository networkCustomRepo;
+
+ @Autowired
+ private NetworkResourceRepository networkResourceRepo;
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheck () {
+ LOGGER.debug ("Health check call in Network Adapter");
+ }
+
+ /**
+ * Do not use this constructor or the msoPropertiesFactory will be NULL.
+ *
+ * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
+ */
+ public MsoNetworkAdapterImpl() {
+ }
+
+ @Override
+ public void createNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ Boolean failIfExists,
+ Boolean backout,
+ List <Subnet> subnets,
+ MsoRequest msoRequest,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ Holder <String> networkFqdn = new Holder <> ();
+ createNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ null,
+ null,
+ null,
+ failIfExists,
+ backout,
+ subnets,
+ null,
+ null,
+ msoRequest,
+ networkId,
+ neutronNetworkId,
+ networkFqdn,
+ subnetIdMap,
+ rollback);
+ }
+
+ @Override
+ public void createNetworkContrail (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkName,
+ List <RouteTarget> routeTargets,
+ String shared,
+ String external,
+ Boolean failIfExists,
+ Boolean backout,
+ List <Subnet> subnets,
+ List <String> policyFqdns,
+ List<String> routeTableFqdns,
+ MsoRequest msoRequest,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <String> networkFqdn,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ createNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkName,
+ null,
+ null,
+ routeTargets,
+ shared,
+ external,
+ failIfExists,
+ backout,
+ subnets,
+ policyFqdns,
+ routeTableFqdns,
+ msoRequest,
+ networkId,
+ neutronNetworkId,
+ networkFqdn,
+ subnetIdMap,
+ rollback);
+ }
+
+ /**
+ * This is the "Create Network" web service implementation.
+ * It will create a new Network of the requested type in the specified cloud
+ * and tenant. The tenant must exist at the time this service is called.
+ *
+ * If a network with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * There will be a pre-defined set of network types defined in the MSO Catalog.
+ * All such networks will have a similar configuration, based on the allowable
+ * Openstack networking definitions. This includes basic networks, provider
+ * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
+ *
+ * Initially, all provider networks must be "vlan" type, and multiple segments in
+ * a multi-provider network must be multiple VLANs on the same physical network.
+ *
+ * This service supports two modes of Network creation/update:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition. All Heat-based templates must support some subset of
+ * the same input parameters: network_name, physical_network, vlan(s).
+ *
+ * The method returns the network ID and a NetworkRollback object. This latter
+ * object can be passed as-is to the rollbackNetwork operation to undo everything
+ * that was created. This is useful if a network is successfully created but
+ * the orchestration fails on a subsequent operation.
+ */
+
+ private void createNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <RouteTarget> routeTargets,
+ String shared,
+ String external,
+ Boolean failIfExists,
+ Boolean backout,
+ List <Subnet> subnets,
+ List <String> policyFqdns,
+ List <String> routeTableFqdns,
+ MsoRequest msoRequest,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <String> networkFqdn,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateNetwork");
+
+ LOGGER.debug ("*** CREATE Network: " + networkName
+ + " of type "
+ + networkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Build a default rollback object (no actions performed)
+ NetworkRollback networkRollback = new NetworkRollback ();
+ networkRollback.setCloudId (cloudSiteId);
+ networkRollback.setTenantId (tenantId);
+ networkRollback.setMsoRequest (msoRequest);
+ networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
+
+ // tenant query is not required here.
+ // If the tenant doesn't exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
+ // So this is just catching that error in a bit more obvious way up front.
+
+ Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
+ if (!cloudSiteOpt.isPresent())
+ {
+ String error = "Configuration Error. Stack " + networkName + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + " CloudSite does not exist in MSO Configuration";
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ // Set the detailed error as the Exception 'message'
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+
+
+ NetworkResource networkResource = networkCheck (startTime,
+ networkType,
+ modelCustomizationUuid,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ cloudSiteId,
+ cloudSiteOpt.get());
+ String mode = networkResource.getOrchestrationMode ();
+ NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
+
+ if (NEUTRON_MODE.equals (mode)) {
+
+ // Use an MsoNeutronUtils for all neutron commands
+
+ // See if the Network already exists (by name)
+ NetworkInfo netInfo = null;
+ long queryNetworkStarttime = System.currentTimeMillis ();
+ try {
+ netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
+ } catch (MsoException me) {
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
+ LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
+ throw new NetworkException (me);
+ }
+
+ if (netInfo != null) {
+ // Exists. If that's OK, return success with the network ID.
+ // Otherwise, return an exception.
+ if (failIfExists != null && failIfExists) {
+ String error = "Create Nework: Network " + networkName
+ + " already exists in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + " with ID " + netInfo.getId();
+ LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ } else {
+ // Populate the outputs from the existing network.
+ networkId.value = netInfo.getId ();
+ neutronNetworkId.value = netInfo.getId ();
+ rollback.value = networkRollback; // Default rollback - no updates performed
+ String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
+ LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
+ }
+ return;
+ }
+
+ long createNetworkStarttime = System.currentTimeMillis ();
+ try {
+ netInfo = neutron.createNetwork (cloudSiteId,
+ tenantId,
+ neutronNetworkType,
+ networkName,
+ physicalNetworkName,
+ vlans);
+ LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
+ String error = "Create Network: type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ throw new NetworkException (me);
+ }
+
+ // Note: ignoring MsoNetworkAlreadyExists because we already checked.
+
+ // If reach this point, network creation is successful.
+ // Since directly created via Neutron, networkId tracked by MSO is the same
+ // as the neutron network ID.
+ networkId.value = netInfo.getId ();
+ neutronNetworkId.value = netInfo.getId ();
+
+ networkRollback.setNetworkCreated (true);
+ networkRollback.setNetworkId (netInfo.getId ());
+ networkRollback.setNeutronNetworkId (netInfo.getId ());
+ networkRollback.setNetworkType (networkType);
+
+ LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
+ } else if ("HEAT".equals (mode)) {
+
+ HeatTemplate heatTemplate = networkResource.getHeatTemplate();
+ if (heatTemplate == null) {
+ String error = "Network error - undefined Heat Template. Network Type = " + networkType;
+ LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
+ // error,
+ // configuration
+ // must be fixed
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
+ }
+
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString());
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ boolean aic3template=false;
+ String aic3nw = AIC3_NW;
+
+ aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
+
+ if (template.contains(aic3nw))
+ aic3template = true;
+
+ // First, look up to see if the Network already exists (by name).
+ // For HEAT orchestration of networks, the stack name will always match the network name
+ StackInfo heatStack = null;
+ long queryNetworkStarttime = System.currentTimeMillis ();
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
+ String error = "Create Network (heat): query network " + networkName
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+
+ if (heatStack != null && (heatStack.getStatus () != HeatStatus.NOTFOUND)) {
+ // Stack exists. Return success or error depending on input directive
+ if (failIfExists != null && failIfExists) {
+ String error = "CreateNetwork: Stack " + networkName
+ + " already exists in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + " as " + heatStack.getCanonicalName();
+ LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ } else {
+ // Populate the outputs from the existing stack.
+ networkId.value = heatStack.getCanonicalName ();
+ neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
+ rollback.value = networkRollback; // Default rollback - no updates performed
+ if (aic3template)
+ {
+ networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
+ }
+ Map <String, Object> outputs = heatStack.getOutputs ();
+ Map <String, String> sMap = new HashMap <> ();
+ if (outputs != null) {
+ for (String key : outputs.keySet ()) {
+ if (key != null && key.startsWith ("subnet")) {
+ if (aic3template) //one subnet_id output
+ {
+ Map <String, String> map = getSubnetUUId(key, outputs, subnets);
+ sMap.putAll(map);
+ }
+ else //multiples subnet_%aaid% outputs
+ {
+ String subnetUUId = (String) outputs.get(key);
+ sMap.put (key.substring("subnet_id_".length()), subnetUUId);
+ }
+ }
+ }
+ }
+ subnetIdMap.value = sMap;
+ LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
+ }
+ return;
+ }
+
+ // Ready to deploy the new Network
+ // Build the common set of HEAT template parameters
+ Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ shared,
+ external,
+ aic3template);
+
+ // Validate (and update) the input parameters against the DB definition
+ // Shouldn't happen unless DB config is wrong, since all networks use same inputs
+ // and inputs were already validated.
+ try {
+ stackParams = heat.validateStackParams (stackParams, heatTemplate);
+ } catch (IllegalArgumentException e) {
+ String error = "Create Network: Configuration Error: " + e.getMessage ();
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
+ alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
+ // error,
+ // configuration
+ // must be fixed
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ // Input parameters were not valid
+ throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
+ }
+
+ if (subnets != null) {
+ try {
+ if (aic3template)
+ {
+ template = mergeSubnetsAIC3 (template, subnets, stackParams);
+ }
+ else
+ {
+ template = mergeSubnets (template, subnets);
+ }
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ String error = "Create Network (heat): type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException (me);
+ }
+ }
+
+ if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
+ try {
+ mergePolicyRefs (policyFqdns, stackParams);
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException (me);
+ }
+ }
+
+ if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
+ try {
+ mergeRouteTableRefs (routeTableFqdns, stackParams);
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException (me);
+ }
+ }
+
+ // Deploy the network stack
+ // Ignore MsoStackAlreadyExists exception because we already checked.
+ try {
+ if (backout == null)
+ backout = true;
+ heatStack = heat.createStack (cloudSiteId,
+ tenantId,
+ networkName,
+ template,
+ stackParams,
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ null,
+ null,
+ null,
+ backout.booleanValue());
+ } catch (MsoException me) {
+ me.addContext (CREATE_NETWORK_CONTEXT);
+ String error = "Create Network (heat): type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+
+ // Reach this point if createStack is successful.
+
+ // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
+ // and the neutronNetworkId is the network UUID returned in stack outputs.
+ networkId.value = heatStack.getCanonicalName ();
+ neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
+ if (aic3template)
+ {
+ networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
+ }
+ Map <String, Object> outputs = heatStack.getOutputs ();
+ Map <String, String> sMap = new HashMap <> ();
+ if (outputs != null) {
+ for (String key : outputs.keySet ()) {
+ if (key != null && key.startsWith ("subnet")) {
+ if (aic3template) //one subnet output expected
+ {
+ Map <String, String> map = getSubnetUUId(key, outputs, subnets);
+ sMap.putAll(map);
+ }
+ else //multiples subnet_%aaid% outputs allowed
+ {
+ String subnetUUId = (String) outputs.get(key);
+ sMap.put (key.substring("subnet_id_".length()), subnetUUId);
+ }
+ }
+ }
+ }
+ subnetIdMap.value = sMap;
+
+ rollback.value = networkRollback;
+ // Populate remaining rollback info and response parameters.
+ networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
+ networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
+ networkRollback.setNetworkCreated (true);
+ networkRollback.setNetworkType (networkType);
+
+ LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
+ }
+
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
+ return;
+ }
+
+ @Override
+ public void updateNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <Subnet> subnets,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ updateNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkId,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ null,
+ null,
+ null,
+ subnets,
+ null,
+ null,
+ msoRequest,
+ subnetIdMap,
+ rollback);
+
+ }
+
+ @Override
+ public void updateNetworkContrail (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ String networkName,
+ List <RouteTarget> routeTargets,
+ String shared,
+ String external,
+ List <Subnet> subnets,
+ List <String> policyFqdns,
+ List<String> routeTableFqdns,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ updateNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ modelCustomizationUuid,
+ networkId,
+ networkName,
+ null,
+ null,
+ routeTargets,
+ shared,
+ external,
+ subnets,
+ policyFqdns,
+ routeTableFqdns,
+ msoRequest,
+ subnetIdMap,
+ rollback);
+ }
+
+ /**
+ * This is the "Update Network" web service implementation.
+ * It will update an existing Network of the requested type in the specified cloud
+ * and tenant. The typical use will be to replace the VLANs with the supplied
+ * list (to add or remove a VLAN), but other properties may be updated as well.
+ *
+ * There will be a pre-defined set of network types defined in the MSO Catalog.
+ * All such networks will have a similar configuration, based on the allowable
+ * Openstack networking definitions. This includes basic networks, provider
+ * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
+ *
+ * Initially, all provider networks must currently be "vlan" type, and multi-provider
+ * networks must be multiple VLANs on the same physical network.
+ *
+ * This service supports two modes of Network update:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition. All Heat-based templates must support some subset of
+ * the same input parameters: network_name, physical_network, vlan, segments.
+ *
+ * The method returns a NetworkRollback object. This object can be passed
+ * as-is to the rollbackNetwork operation to undo everything that was updated.
+ * This is useful if a network is successfully updated but orchestration
+ * fails on a subsequent operation.
+ */
+ private void updateNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <RouteTarget> routeTargets,
+ String shared,
+ String external,
+ List <Subnet> subnets,
+ List <String> policyFqdns,
+ List<String> routeTableFqdns,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> subnetIdMap,
+ Holder <NetworkRollback> rollback) throws NetworkException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("UpdateNetwork");
+ LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
+ + " of type "
+ + networkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Build a default rollback object (no actions performed)
+ NetworkRollback networkRollback = new NetworkRollback ();
+ networkRollback.setCloudId (cloudSiteId);
+ networkRollback.setTenantId (tenantId);
+ networkRollback.setMsoRequest (msoRequest);
+
+ Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite (cloudSiteId);
+ if (!cloudSiteOpt.isPresent()) {
+ String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + " CloudSite does not exist in MSO Configuration";
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ // Set the detailed error as the Exception 'message'
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+
+
+
+
+ NetworkResource networkResource = networkCheck(
+ startTime,
+ networkType,
+ modelCustomizationUuid,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ cloudSiteId,
+ cloudSiteOpt.get());
+ String mode = networkResource.getOrchestrationMode();
+ NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
+
+ // Use an MsoNeutronUtils for all Neutron commands
+
+ if (NEUTRON_MODE.equals(mode)) {
+
+ // Verify that the Network exists
+ // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
+ NetworkInfo netInfo = null;
+ long queryNetworkStarttime = System.currentTimeMillis();
+ try {
+ netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
+ LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "Update Network (neutron): query " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
+ LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException(me);
+ }
+
+ if (netInfo == null) {
+ String error = "Update Nework: Network " + networkId
+ + " does not exist in "
+ + cloudSiteId
+ + "/"
+ + tenantId;
+ LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ // Does not exist. Throw an exception (can't update a non-existent network)
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ }
+ long updateNetworkStarttime = System.currentTimeMillis();
+ try {
+ netInfo = neutron.updateNetwork(cloudSiteId,
+ tenantId,
+ networkId,
+ neutronNetworkType,
+ physicalNetworkName,
+ vlans);
+ LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "Update Network (neutron): " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
+ LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException(me);
+ }
+
+ // Add the network ID and previously queried vlans to the rollback object
+ networkRollback.setNetworkId(netInfo.getId());
+ networkRollback.setNeutronNetworkId(netInfo.getId());
+ networkRollback.setNetworkType(networkType);
+ // Save previous parameters
+ networkRollback.setNetworkName(netInfo.getName());
+ networkRollback.setPhysicalNetwork(netInfo.getProvider());
+ networkRollback.setVlans(netInfo.getVlans());
+
+ LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
+ } else if ("HEAT".equals(mode)) {
+
+ // First, look up to see that the Network already exists.
+ // For Heat-based orchestration, the networkId is the network Stack ID.
+ StackInfo heatStack = null;
+ long queryStackStarttime = System.currentTimeMillis();
+ try {
+ heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
+ LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "UpdateNetwork (heat): query " + networkName
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
+ LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException(me);
+ }
+
+ if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
+ String error = "UpdateNetwork: Stack " + networkName
+ + " does not exist in "
+ + cloudSiteId
+ + "/"
+ + tenantId;
+ LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ // Network stack does not exist. Return an error
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Get the previous parameters for rollback
+ Map<String, Object> heatParams = heatStack.getParameters();
+
+ String previousNetworkName = (String) heatParams.get("network_name");
+ String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
+
+ List<Integer> previousVlans = new ArrayList<>();
+ String vlansParam = (String) heatParams.get(VLANS);
+ if (vlansParam != null) {
+ for (String vlan : vlansParam.split(",")) {
+ try {
+ previousVlans.add(Integer.parseInt(vlan));
+ } catch (NumberFormatException e) {
+ LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
+ }
+ }
+ }
+ LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
+
+ // Ready to deploy the updated Network via Heat
+
+
+ HeatTemplate heatTemplate = networkResource.getHeatTemplate();
+ if (heatTemplate == null) {
+ String error = "Network error - undefined Heat Template. Network Type=" + networkType;
+ LOGGER.error(MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "OpenStack", "getHeatTemplate", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type=" + networkType);
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
+ }
+
+ LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate();
+ template = template.replaceAll("\r\n", "\n");
+
+ boolean aic3template = false;
+ String aic3nw = AIC3_NW;
+
+ aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
+
+ if (template.contains(aic3nw))
+ aic3template = true;
+
+ // Build the common set of HEAT template parameters
+ Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ shared,
+ external,
+ aic3template);
+
+ // Validate (and update) the input parameters against the DB definition
+ // Shouldn't happen unless DB config is wrong, since all networks use same inputs
+ try {
+ stackParams = heat.validateStackParams(stackParams, heatTemplate);
+ } catch (IllegalArgumentException e) {
+ String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
+ throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
+ }
+
+ if (subnets != null) {
+ try {
+ if (aic3template) {
+ template = mergeSubnetsAIC3(template, subnets, stackParams);
+ } else {
+ template = mergeSubnets(template, subnets);
+ }
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "Update Network (heat): type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException(me);
+ }
+ }
+
+ if (policyFqdns != null && aic3template) {
+ try {
+ mergePolicyRefs(policyFqdns, stackParams);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException(me);
+ }
+ }
+
+ if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
+ try {
+ mergeRouteTableRefs(routeTableFqdns, stackParams);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ throw new NetworkException(me);
+ }
+ }
+
+ // Update the network stack
+ // Ignore MsoStackNotFound exception because we already checked.
+ long updateStackStarttime = System.currentTimeMillis();
+ try {
+ heatStack = heatWithUpdate.updateStack(cloudSiteId,
+ tenantId,
+ networkId,
+ template,
+ stackParams,
+ true,
+ heatTemplate.getTimeoutMinutes());
+ LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
+ } catch (MsoException me) {
+ me.addContext(UPDATE_NETWORK_CONTEXT);
+ String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
+ LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException(me);
+ }
+
+ Map<String, Object> outputs = heatStack.getOutputs();
+ Map<String, String> sMap = new HashMap<>();
+ if (outputs != null) {
+ for (String key : outputs.keySet()) {
+ if (key != null && key.startsWith("subnet")) {
+ if (aic3template) //one subnet output expected
+ {
+ Map<String, String> map = getSubnetUUId(key, outputs, subnets);
+ sMap.putAll(map);
+ } else //multiples subnet_%aaid% outputs allowed
+ {
+ String subnetUUId = (String) outputs.get(key);
+ sMap.put(key.substring("subnet_id_".length()), subnetUUId);
+ }
+ }
+ }
+ }
+ subnetIdMap.value = sMap;
+
+ // Reach this point if createStack is successful.
+ // Populate remaining rollback info and response parameters.
+ networkRollback.setNetworkStackId(heatStack.getCanonicalName());
+ if(null != outputs) {
+ networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
+ }
+ else {
+ LOGGER.debug("outputs is NULL");
+ }
+ networkRollback.setNetworkType(networkType);
+ // Save previous parameters
+ networkRollback.setNetworkName(previousNetworkName);
+ networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
+ networkRollback.setVlans(previousVlans);
+
+ rollback.value = networkRollback;
+
+ LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
+ }
+
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
+ return;
+ }
+
+ private NetworkResource networkCheck (long startTime,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <RouteTarget> routeTargets,
+ String cloudSiteId,
+ CloudSite cloudSite) throws NetworkException {
+ // Retrieve the Network Resource definition
+ NetworkResource networkResource = null;
+ NetworkResourceCustomization networkCust = null;
+ if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
+ if (!commonUtils.isNullOrEmpty(networkType)) {
+ networkResource = networkResourceRepo.findOneByModelName(networkType);
+ }
+ } else {
+ networkCust = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
+ }
+ if(networkCust != null){
+ LOGGER.debug("Got Network Customization definition from Catalog: "
+ + networkCust.toString());
+
+ networkResource = networkCust.getNetworkResource();
+ }
+ if (networkResource == null) {
+ String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
+ + networkType
+ + " or ModelCustomizationUUID:"
+ + modelCustomizationUuid;
+ LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
+ "NetworkType/ModelCustomizationUUID", networkType + "/"
+ + modelCustomizationUuid, "OpenStack", "",
+ MsoLogger.ErrorCode.DataError,
+ "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
+
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug("Got Network definition from Catalog: "
+ + networkResource.toString());
+
+ String mode = networkResource.getOrchestrationMode();
+ NetworkType neutronNetworkType = NetworkType
+ .valueOf(networkResource.getNeutronNetworkType());
+
+ // All Networks are orchestrated via HEAT or Neutron
+ if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
+ String error = "CreateNetwork: Configuration Error: Network Type = "
+ + networkType;
+ LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
+ mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
+ "CreateNetwork: Configuration Error");
+ // Alarm on this error, configuration must be fixed
+ alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
+ MsoAlarmLogger.CRITICAL, error);
+
+ throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
+ }
+
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+ aicV.setVersion(cloudSite.getAicVersion());
+ if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
+ .isTheSameVersion(networkResource.getAicVersionMin())) // aic
+ // >=
+ // min
+ && (aicV.isTheSameVersion(networkResource
+ .getAicVersionMax()) || !(aicV
+ .isMoreRecentThan(networkResource
+ .getAicVersionMax())))) // aic <= max
+ {
+ LOGGER.debug("Network Type:" + networkType + " VersionMin:"
+ + networkResource.getAicVersionMin() + " VersionMax:"
+ + networkResource.getAicVersionMax()
+ + " supported on Cloud:" + cloudSiteId
+ + " with AIC_Version:" + cloudSite.getAicVersion());
+ } else {
+ String error = "Network Type:" + networkType + " Version_Min:"
+ + networkResource.getAicVersionMin() + " Version_Max:"
+ + networkResource.getAicVersionMax()
+ + " not supported on Cloud:" + cloudSiteId
+ + " with AIC_Version:" + cloudSite.getAicVersion();
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
+ MsoLogger.ErrorCode.DataError,
+ "Network Type not supported on Cloud");
+ LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
+ MsoLogger.ResponseCode.DataError, error);
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Validate the Network parameters.
+ String missing = validateNetworkParams(neutronNetworkType,
+ networkName, physicalNetworkName, vlans, routeTargets);
+ if (!missing.isEmpty()) {
+ String error = "Create Network: Missing parameters: " + missing;
+ LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
+ "OpenStack", "", MsoLogger.ErrorCode.DataError,
+ "Create Network: Missing parameters");
+
+ throw new NetworkException(error, MsoExceptionCategory.USERDATA);
+ }
+
+ return networkResource;
+ }
+
+ @Override
+ public void queryNetwork (String cloudSiteId,
+ String tenantId,
+ String networkNameOrId,
+ MsoRequest msoRequest,
+ Holder <Boolean> networkExists,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <NetworkStatus> status,
+ Holder <List <Integer>> vlans,
+ Holder <Map <String, String>> subnetIdMap) throws NetworkException {
+ queryNetwork (cloudSiteId,
+ tenantId,
+ networkNameOrId,
+ msoRequest,
+ networkExists,
+ networkId,
+ neutronNetworkId,
+ status,
+ vlans,
+ null,
+ subnetIdMap);
+ }
+
+ @Override
+ public void queryNetworkContrail (String cloudSiteId,
+ String tenantId,
+ String networkNameOrId,
+ MsoRequest msoRequest,
+ Holder <Boolean> networkExists,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <NetworkStatus> status,
+ Holder <List <RouteTarget>> routeTargets,
+ Holder <Map <String, String>> subnetIdMap) throws NetworkException {
+ queryNetwork (cloudSiteId,
+ tenantId,
+ networkNameOrId,
+ msoRequest,
+ networkExists,
+ networkId,
+ neutronNetworkId,
+ status,
+ null,
+ routeTargets,
+ subnetIdMap);
+ }
+
+ /**
+ * This is the queryNetwork method. It returns the existence and status of
+ * the specified network, along with its Neutron UUID and list of VLANs.
+ * This method attempts to find the network using both Heat and Neutron.
+ * Heat stacks are first searched based on the provided network name/id.
+ * If none is found, the Neutron is directly queried.
+ */
+ private void queryNetwork (String cloudSiteId,
+ String tenantId,
+ String networkNameOrId,
+ MsoRequest msoRequest,
+ Holder <Boolean> networkExists,
+ Holder <String> networkId,
+ Holder <String> neutronNetworkId,
+ Holder <NetworkStatus> status,
+ Holder <List <Integer>> vlans,
+ Holder <List <RouteTarget>> routeTargets,
+ Holder <Map <String, String>> subnetIdMap) throws NetworkException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("QueryNetwork");
+ LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ if (commonUtils.isNullOrEmpty (cloudSiteId)
+ || commonUtils.isNullOrEmpty(tenantId)
+ || commonUtils.isNullOrEmpty(networkNameOrId)) {
+
+ String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+
+ Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
+ if (!cloudSiteOpt.isPresent())
+ {
+ String error = "Configuration Error. Stack " + networkNameOrId + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + " CloudSite does not exist in MSO Configuration";
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ // Set the detailed error as the Exception 'message'
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Use MsoNeutronUtils for all NEUTRON commands
+
+ String mode;
+ String neutronId;
+ // Try Heat first, since networks may be named the same as the Heat stack
+ StackInfo heatStack = null;
+ long queryStackStarttime = System.currentTimeMillis ();
+ try {
+ heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
+ LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
+ } catch (MsoException me) {
+ me.addContext ("QueryNetwork");
+ String error = "Query Network (heat): " + networkNameOrId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
+ LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+
+ // Populate the outputs based on the returned Stack information
+ if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
+ // Found it. Get the neutronNetworkId for further query
+ Map <String, Object> outputs = heatStack.getOutputs ();
+ neutronId = (String) outputs.get (NETWORK_ID);
+ mode = "HEAT";
+
+ Map <String, String> sMap = new HashMap <> ();
+ if (outputs != null) {
+ for (String key : outputs.keySet ()) {
+ if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
+ {
+ String subnetUUId = (String) outputs.get(key);
+ sMap.put (key.substring("subnet_id_".length()), subnetUUId);
+ }
+ else if (key != null && key.startsWith ("subnet")) //one subnet output expected
+ {
+ Map <String, String> map = getSubnetUUId(key, outputs, null);
+ sMap.putAll(map);
+ }
+
+ }
+ }
+ subnetIdMap.value = sMap;
+ } else {
+ // Input ID was not a Heat stack ID. Try it directly in Neutron
+ neutronId = networkNameOrId;
+ mode = NEUTRON_MODE;
+ }
+
+ // Query directly against the Neutron Network for the details
+ // no RouteTargets available for ContrailV2 in neutron net-show
+ // networkId is heatStackId
+ long queryNetworkStarttime = System.currentTimeMillis ();
+ try {
+ NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
+ if (netInfo != null) {
+ // Found. Populate the output elements
+ networkExists.value = Boolean.TRUE;
+ if ("HEAT".equals (mode)) {
+ networkId.value = heatStack.getCanonicalName ();
+ } else {
+ networkId.value = netInfo.getId ();
+ }
+ neutronNetworkId.value = netInfo.getId ();
+ status.value = netInfo.getStatus ();
+ if (vlans != null)
+ vlans.value = netInfo.getVlans ();
+
+ LOGGER.debug ("Network " + networkNameOrId
+ + " found ("
+ + mode
+ + "), ID = "
+ + networkId.value
+ + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
+ } else {
+ // Not found. Populate the status fields, leave the rest null
+ networkExists.value = Boolean.FALSE;
+ status.value = NetworkStatus.NOTFOUND;
+ neutronNetworkId.value = null;
+ if (vlans != null)
+ vlans.value = new ArrayList<>();
+
+ LOGGER.debug ("Network " + networkNameOrId + " not found");
+ }
+ } catch (MsoException me) {
+ me.addContext ("QueryNetwork");
+ String error = "Query Network (neutron): " + networkNameOrId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
+ LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
+ return;
+ }
+
+ /**
+ * This is the "Delete Network" web service implementation.
+ * It will delete a Network in the specified cloud and tenant.
+ *
+ * If the network is not found, it is treated as a success.
+ *
+ * This service supports two modes of Network creation/update/delete:
+ * - via Heat Templates
+ * - via Neutron API
+ * The network orchestration mode for each network type is declared in its
+ * catalog definition.
+ *
+ * For Heat-based orchestration, the networkId should be the stack ID.
+ * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
+ *
+ * The method returns nothing on success. Rollback is not possible for delete
+ * commands, so any failure on delete will require manual fallout in the client.
+ */
+ @Override
+ public void deleteNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String modelCustomizationUuid,
+ String networkId,
+ MsoRequest msoRequest,
+ Holder <Boolean> networkDeleted) throws NetworkException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteNetwork");
+ LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+
+ if (commonUtils.isNullOrEmpty (cloudSiteId)
+ || commonUtils.isNullOrEmpty(tenantId)
+ || commonUtils.isNullOrEmpty(networkId)) {
+ String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Retrieve the Network Resource definition
+ NetworkResource networkResource = null;
+
+ if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
+ if (!commonUtils.isNullOrEmpty(networkType)) {
+ networkResource = networkResourceRepo.findFirstByModelNameOrderByModelVersionDesc(networkType);
+ }
+ } else {
+ NetworkResourceCustomization nrc = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
+ if (nrc != null) {
+ networkResource = nrc.getNetworkResource();
+ }
+ }
+
+ String mode = "";
+ if (networkResource != null) {
+ LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
+
+ mode = networkResource.getOrchestrationMode ();
+ }
+
+ if (NEUTRON_MODE.equals (mode)) {
+
+ // Use MsoNeutronUtils for all NEUTRON commands
+ long deleteNetworkStarttime = System.currentTimeMillis ();
+ try {
+ // The deleteNetwork function in MsoNeutronUtils returns success if the network
+ // was not found. So don't bother to query first.
+ boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
+ LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
+ networkDeleted.value = deleted;
+ } catch (MsoException me) {
+ me.addContext ("DeleteNetwork");
+ String error = "Delete Network (neutron): " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
+ LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+ } else { // DEFAULT to ("HEAT".equals (mode))
+ long deleteStackStarttime = System.currentTimeMillis ();
+
+ try {
+ // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
+ // So query first to report back if stack WAS deleted or just NOTOFUND
+ StackInfo heatStack = null;
+ heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
+ if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
+ {
+ heat.deleteStack (tenantId, cloudSiteId, networkId, true);
+ LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
+ networkDeleted.value = true;
+ }
+ else
+ {
+ networkDeleted.value = false;
+ }
+ } catch (MsoException me) {
+ me.addContext ("DeleteNetwork");
+ String error = "Delete Network (heat): " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
+ LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+ }
+
+
+ // On success, nothing is returned.
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
+ 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.
+ *
+ * The rollback includes removing the VNF and deleting the tenant if the
+ * tenant did not exist prior to the VNF creation.
+ */
+ @Override
+ public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
+ MsoLogger.setServiceName ("RollbackNetwork");
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ if (rollback == null) {
+ LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
+ return;
+ }
+
+ MsoLogger.setLogContext (rollback.getMsoRequest());
+
+ // Get the elements of the VnfRollback object for easier access
+ String cloudSiteId = rollback.getCloudId ();
+ String tenantId = rollback.getTenantId ();
+ String networkId = rollback.getNetworkStackId ();
+ String networkType = rollback.getNetworkType ();
+ String modelCustomizationUuid = rollback.getModelCustomizationUuid();
+
+ LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
+
+
+
+ // Retrieve the Network Resource definition
+ NetworkResource networkResource = null;
+ if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
+ networkResource = networkCustomRepo.findOneByNetworkType(networkType).getNetworkResource();
+ } else {
+ networkResource = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid).getNetworkResource();
+ }
+ String mode = "";
+ if (networkResource != null) {
+
+ LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
+
+ mode = networkResource.getOrchestrationMode ();
+ }
+
+ if (rollback.getNetworkCreated ()) {
+ // Rolling back a newly created network, so delete it.
+ if (NEUTRON_MODE.equals (mode)) {
+ // Use MsoNeutronUtils for all NEUTRON commands
+ long deleteNetworkStarttime = System.currentTimeMillis ();
+ try {
+ // The deleteNetwork function in MsoNeutronUtils returns success if the network
+ // was not found. So don't bother to query first.
+ neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
+ LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
+ } catch (MsoException me) {
+ me.addContext ("RollbackNetwork");
+ String error = "Rollback Network (neutron): " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
+ LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+ } else { // DEFAULT to if ("HEAT".equals (mode))
+ long deleteStackStarttime = System.currentTimeMillis ();
+ try {
+ // The deleteStack function in MsoHeatUtils returns success if the stack
+ // was not found. So don't bother to query first.
+ heat.deleteStack (tenantId, cloudSiteId, networkId, true);
+ LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
+ } catch (MsoException me) {
+ me.addContext ("RollbackNetwork");
+ String error = "Rollback Network (heat): " + networkId
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
+ LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new NetworkException (me);
+ }
+ }
+ }
+
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
+ return;
+ }
+
+ private String validateNetworkParams (NetworkType neutronNetworkType,
+ String networkName,
+ String physicalNetwork,
+ List <Integer> vlans,
+ List <RouteTarget> routeTargets) {
+ String sep = "";
+ StringBuilder missing = new StringBuilder ();
+ if (commonUtils.isNullOrEmpty(networkName)) {
+ missing.append ("networkName");
+ sep = ",";
+ }
+
+ if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
+ if (commonUtils.isNullOrEmpty(physicalNetwork)) {
+ missing.append (sep).append ("physicalNetworkName");
+ sep = ",";
+ }
+ if (vlans == null || vlans.isEmpty ()) {
+ missing.append (sep).append (VLANS);
+ }
+ }
+
+ return missing.toString ();
+ }
+
+ private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
+ String networkName,
+ String physicalNetwork,
+ List <Integer> vlans,
+ List <RouteTarget> routeTargets,
+ String shared,
+ String external,
+ boolean aic3template) {
+ // Build the common set of HEAT template parameters
+ Map <String, Object> stackParams = new HashMap <> ();
+ stackParams.put ("network_name", networkName);
+
+ if (neutronNetworkType == NetworkType.PROVIDER) {
+ // For Provider type
+ stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
+ stackParams.put ("vlan", vlans.get (0).toString ());
+ } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
+ // For Multi-provider, PO supports a custom resource extension of ProviderNet.
+ // It supports all ProviderNet properties except segmentation_id, and adds a
+ // comma-separated-list of VLANs as a "segments" property.
+ // Note that this does not match the Neutron definition of Multi-Provider network,
+ // which contains a list of 'segments', each having physical_network, network_type,
+ // and segmentation_id.
+ StringBuilder buf = new StringBuilder ();
+ String sep = "";
+ for (Integer vlan : vlans) {
+ buf.append (sep).append (vlan.toString ());
+ sep = ",";
+ }
+ String csl = buf.toString ();
+
+ stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
+ stackParams.put (VLANS, csl);
+ }
+ if (routeTargets != null) {
+
+ String rtGlobal = "";
+ String rtImport = "";
+ String rtExport = "";
+ String sep = "";
+ for (RouteTarget rt : routeTargets) {
+ boolean rtIsNull = false;
+ if (rt != null)
+ {
+ String routeTarget = rt.getRouteTarget();
+ String routeTargetRole = rt.getRouteTargetRole();
+ LOGGER.debug("Checking for an actually null route target: " + rt.toString());
+ if (routeTarget == null || routeTarget.equals("") || routeTarget.equalsIgnoreCase("null"))
+ rtIsNull = true;
+ if (routeTargetRole == null || routeTargetRole.equals("") || routeTargetRole.equalsIgnoreCase("null"))
+ rtIsNull = true;
+ } else {
+ rtIsNull = true;
+ }
+ if (!rtIsNull) {
+ LOGGER.debug("Input RT:" + rt.toString());
+ String role = rt.getRouteTargetRole();
+ String rtValue = rt.getRouteTarget();
+
+ if ("IMPORT".equalsIgnoreCase(role))
+ {
+ sep = rtImport.isEmpty() ? "" : ",";
+ rtImport = aic3template ? rtImport + sep + "target:" + rtValue : rtImport + sep + rtValue ;
+ }
+ else if ("EXPORT".equalsIgnoreCase(role))
+ {
+ sep = rtExport.isEmpty() ? "" : ",";
+ rtExport = aic3template ? rtExport + sep + "target:" + rtValue : rtExport + sep + rtValue ;
+ }
+ else // covers BOTH, empty etc
+ {
+ sep = rtGlobal.isEmpty() ? "" : ",";
+ rtGlobal = aic3template ? rtGlobal + sep + "target:" + rtValue : rtGlobal + sep + rtValue ;
+ }
+
+ }
+ }
+
+ if (!rtImport.isEmpty())
+ {
+ stackParams.put ("route_targets_import", rtImport);
+ }
+ if (!rtExport.isEmpty())
+ {
+ stackParams.put ("route_targets_export", rtExport);
+ }
+ if (!rtGlobal.isEmpty())
+ {
+ stackParams.put ("route_targets", rtGlobal);
+ }
+ }
+ if (commonUtils.isNullOrEmpty(shared)) {
+ stackParams.put ("shared", "False");
+ } else {
+ stackParams.put ("shared", shared);
+ }
+ if (commonUtils.isNullOrEmpty(external)) {
+ stackParams.put ("external", "False");
+ } else {
+ stackParams.put ("external", external);
+ }
+ return stackParams;
+ }
+
+
+
+ /** policyRef_list structure in stackParams
+ [
+ {
+ "network_policy_refs_data_sequence": {
+ "network_policy_refs_data_sequence_major": "1",
+ "network_policy_refs_data_sequence_minor": "0"
+ }
+ },
+ {
+ "network_policy_refs_data_sequence": {
+ "network_policy_refs_data_sequence_major": "2",
+ "network_policy_refs_data_sequence_minor": "0"
+ }
+ }
+ ]
+ **/
+ private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
+ //Resource Property
+ List<ContrailPolicyRef> prlist = new ArrayList <> ();
+ int index = 1;
+ for (String pf : pFqdns) {
+ if (!commonUtils.isNullOrEmpty(pf))
+ {
+ ContrailPolicyRef pr = new ContrailPolicyRef();
+ ContrailPolicyRefSeq refSeq = new ContrailPolicyRefSeq(String.valueOf(index), "0");
+ pr.setSeq(refSeq);
+ index++;
+ LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
+ prlist.add(pr);
+ }
+ }
+
+ JsonNode node = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ node = mapper.convertValue(prlist, JsonNode.class);
+ String jsonString = mapper.writeValueAsString(prlist);
+ LOGGER.debug("Json PolicyRefs Data:" + jsonString);
+ }
+ catch (Exception e)
+ {
+ String error = "Error creating JsonNode for policyRefs Data";
+ LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
+ throw new MsoAdapterException (error);
+ }
+ //update parameters
+ if (pFqdns != null && node != null)
+ {
+ StringBuilder buf = new StringBuilder ();
+ String sep = "";
+ for (String pf : pFqdns) {
+ if (!commonUtils.isNullOrEmpty(pf))
+ {
+ buf.append (sep).append (pf);
+ sep = ",";
+ }
+ }
+ String csl = buf.toString ();
+ stackParams.put ("policy_refs", csl);
+ stackParams.put ("policy_refsdata", node);
+ }
+
+ LOGGER.debug ("StackParams updated with policy refs");
+ return;
+ }
+
+ private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
+
+ //update parameters
+ if (rtFqdns != null)
+ {
+ StringBuilder buf = new StringBuilder ();
+ String sep = "";
+ for (String rtf : rtFqdns) {
+ if (!commonUtils.isNullOrEmpty(rtf))
+ {
+ buf.append (sep).append (rtf);
+ sep = ",";
+ }
+ }
+ String csl = buf.toString ();
+ stackParams.put ("route_table_refs", csl);
+ }
+
+ LOGGER.debug ("StackParams updated with route_table refs");
+ return;
+ }
+
+
+ /*** Subnet Output structure from Juniper
+ {
+ "ipam_subnets": [
+ {
+ "subnet": {
+ "ip_prefix": "10.100.1.0",
+ "ip_prefix_len": 28
+ },
+ "addr_from_start": null,
+ "enable_dhcp": false,
+ "default_gateway": "10.100.1.1",
+ "dns_nameservers": [],
+ "dhcp_option_list": null,
+ "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
+ "allocation_pools": [
+ {
+ "start": "10.100.1.3",
+ "end": "10.100.1.5"
+ },
+ {
+ "start": "10.100.1.6",
+ "end": "10.100.1.9"
+ }
+ ],
+ "host_routes": null,
+ "dns_server_address": "10.100.1.13",
+ "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
+ },
+ {
+ "subnet": {
+ "ip_prefix": "10.100.2.16",
+ "ip_prefix_len": 28
+ },
+ "addr_from_start": null,
+ "enable_dhcp": true,
+ "default_gateway": "10.100.2.17",
+ "dns_nameservers": [],
+ "dhcp_option_list": null,
+ "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
+ "allocation_pools": [
+ {
+ "start": "10.100.2.18",
+ "end": "10.100.2.20"
+ }
+ ],
+ "host_routes": null,
+ "dns_server_address": "10.100.2.29",
+ "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
+ }
+ ],
+ "host_routes": null
+ }
+ ***/
+ private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
+
+ //Resource Property
+ List<ContrailSubnet> cslist = new ArrayList <> ();
+ for (Subnet subnet : subnets) {
+ LOGGER.debug("Input Subnet:" + subnet.toString());
+ ContrailSubnet cs = new ContrailSubnetMapper(subnet).map();
+ LOGGER.debug("Contrail Subnet:" + cs.toString());
+ cslist.add(cs);
+ }
+
+ JsonNode node = null;
+ try
+ {
+ ObjectMapper mapper = new ObjectMapper();
+ node = mapper.convertValue(cslist, JsonNode.class);
+ String jsonString = mapper.writeValueAsString(cslist);
+ LOGGER.debug("Json Subnet List:" + jsonString);
+ }
+ catch (Exception e)
+ {
+ String error = "Error creating JsonNode from input subnets";
+ LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
+ throw new MsoAdapterException (error);
+ }
+ //update parameters
+ if (node != null)
+ {
+ stackParams.put ("subnet_list", node);
+ }
+ //Outputs - All subnets are in one ipam_subnets structure
+ String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
+ + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
+
+ // append outputs in heatTemplate
+ int outputsIdx = heatTemplate.indexOf ("outputs:");
+ heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
+ LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
+ return heatTemplate;
+ }
+
+
+ private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
+
+ String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
+ + " properties:\n"
+ + " name: %name%\n"
+ + " network_id: { get_resource: network }\n"
+ + " cidr: %cidr%\n";
+
+ /* make these optional
+ + " ip_version: %ipversion%\n"
+ + " enable_dhcp: %enabledhcp%\n"
+ + " gateway_ip: %gatewayip%\n"
+ + " allocation_pools:\n"
+ + " - start: %poolstart%\n"
+ + " end: %poolend%\n";
+
+ */
+
+ String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
+ + " value: {get_resource: subnet_%subnetId%}\n";
+
+ String curR;
+ String curO;
+ StringBuilder resourcesBuf = new StringBuilder ();
+ StringBuilder outputsBuf = new StringBuilder ();
+ for (Subnet subnet : subnets) {
+
+ // build template for each subnet
+ curR = resourceTempl;
+ if (subnet.getSubnetId () != null) {
+ curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
+ } else {
+ String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
+ throw new MsoAdapterException (error);
+ }
+
+ if (subnet.getSubnetName () != null) {
+ curR = curR.replace ("%name%", subnet.getSubnetName ());
+ } else {
+ curR = curR.replace ("%name%", subnet.getSubnetId ());
+ }
+
+ if (subnet.getCidr () != null) {
+ curR = curR.replace ("%cidr%", subnet.getCidr ());
+ } else {
+ String error = "Missing Required cidr for subnet in HEAT Template";
+ LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
+ throw new MsoAdapterException (error);
+ }
+
+ if (subnet.getIpVersion () != null) {
+ curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
+ }
+ if (subnet.getEnableDHCP () != null) {
+ curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
+ }
+ if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
+ curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
+ }
+
+ if (subnet.getAllocationPools() != null) {
+ curR = curR + " allocation_pools:\n";
+ for (Pool pool : subnet.getAllocationPools())
+ {
+ if (!commonUtils.isNullOrEmpty(pool.getStart()) && !commonUtils.isNullOrEmpty(pool.getEnd()))
+ {
+ curR = curR + " - start: " + pool.getStart () + "\n";
+ curR = curR + " end: " + pool.getEnd () + "\n";
+ }
+ }
+ }
+
+ resourcesBuf.append (curR);
+
+ curO = outputTempl;
+ curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
+
+ outputsBuf.append (curO);
+
+ }
+ // append resources and outputs in heatTemplate
+ LOGGER.debug ("Tempate initial:" + heatTemplate);
+ int outputsIdx = heatTemplate.indexOf ("outputs:");
+ heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
+ int resourcesIdx = heatTemplate.indexOf ("resources:");
+ heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
+
+ LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
+ return heatTemplate;
+ }
+
+ private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
+
+ Map <String, String> sMap = new HashMap <> ();
+
+ try{
+ Object obj = outputs.get(key);
+ ObjectMapper mapper = new ObjectMapper();
+ String jStr = mapper.writeValueAsString(obj);
+ LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
+
+ JsonNode rootNode = mapper.readTree(jStr);
+ for (JsonNode sNode : rootNode.path("ipam_subnets"))
+ {
+ LOGGER.debug("Output Subnet Node" + sNode.toString());
+ String name = sNode.path("subnet_name").textValue();
+ String uuid = sNode.path("subnet_uuid").textValue();
+ String aaiId = name; // default
+ // try to find aaiId for name in input subnetList
+ if (subnets != null)
+ {
+ for (Subnet subnet : subnets)
+ {
+ if ( subnet != null && !commonUtils.isNullOrEmpty(subnet.getSubnetName()))
+ {
+ if (subnet.getSubnetName().equals(name))
+ {
+ aaiId = subnet.getSubnetId();
+ break;
+ }
+ }
+ }
+ }
+ sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
+ }
+
+ LOGGER.debug ("Return sMap" + sMap.toString());
+ return sMap;
+ }
+
+ private static String insertStr (String template, String snippet, int index) {
+
+ String updatedTemplate;
+
+ LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
+
+ String templateBeg = template.substring (0, index);
+ String templateEnd = template.substring (index);
+
+ updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
+
+ LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
+ return updatedTemplate;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/NetworkAdapterRest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/NetworkAdapterRest.java
new file mode 100644
index 0000000000..465fb6d866
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/NetworkAdapterRest.java
@@ -0,0 +1,671 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network;
+
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Provider;
+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.onap.so.adapters.network.exceptions.NetworkException;
+import org.onap.so.adapters.nwrest.ContrailNetwork;
+import org.onap.so.adapters.nwrest.CreateNetworkError;
+import org.onap.so.adapters.nwrest.CreateNetworkRequest;
+import org.onap.so.adapters.nwrest.CreateNetworkResponse;
+import org.onap.so.adapters.nwrest.DeleteNetworkError;
+import org.onap.so.adapters.nwrest.DeleteNetworkRequest;
+import org.onap.so.adapters.nwrest.DeleteNetworkResponse;
+import org.onap.so.adapters.nwrest.ProviderVlanNetwork;
+import org.onap.so.adapters.nwrest.QueryNetworkError;
+import org.onap.so.adapters.nwrest.QueryNetworkResponse;
+import org.onap.so.adapters.nwrest.RollbackNetworkError;
+import org.onap.so.adapters.nwrest.RollbackNetworkRequest;
+import org.onap.so.adapters.nwrest.RollbackNetworkResponse;
+import org.onap.so.adapters.nwrest.UpdateNetworkError;
+import org.onap.so.adapters.nwrest.UpdateNetworkRequest;
+import org.onap.so.adapters.nwrest.UpdateNetworkResponse;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.NetworkRollback;
+import org.onap.so.openstack.beans.NetworkStatus;
+import org.onap.so.openstack.beans.RouteTarget;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+@Path("/v1/networks")
+@Api(value = "/v1/networks", description = "root of network adapters restful web service")
+@Component
+@Transactional
+public class NetworkAdapterRest {
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,NetworkAdapterRest.class);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+
+
+
+ @Autowired
+ private MsoNetworkAdapterImpl adapter;
+ @Autowired
+ @Qualifier("NetworkBpel")
+ private Provider<BpelRestClient> bpelRestClientProvider;
+
+
+ @POST
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "CreateNetwork",
+ response = Response.class,
+ notes = "Creates a new network, CreateNetworkRquest JSON is required")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "network has been successfully created"),
+ @ApiResponse(code = 202, message = "create network request has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "create network failed, examine entity object for details") })
+ public Response createNetwork(
+ @ApiParam(value = "details of network being created", required = true)
+ CreateNetworkRequest req) {
+ LOGGER.debug("createNetwork enter: " + req.toJsonString());
+ CreateNetworkTask task = new CreateNetworkTask(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_NETWORK_EXC, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while create network", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("createNetwork exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class CreateNetworkTask implements Runnable {
+ private final CreateNetworkRequest req;
+ private CreateNetworkResponse response = null;
+ private CreateNetworkError eresp = null;
+ private boolean sendxml;
+
+ public CreateNetworkTask(CreateNetworkRequest 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<CreateNetworkResponse>(response) {}
+ : new GenericEntity<CreateNetworkError>(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 ("CreateNetworkTask start");
+ try {
+ // Synchronous Web Service Outputs
+ Holder<String> networkId = new Holder<>();
+ Holder<String> neutronNetworkId = new Holder<>();
+ Holder<String> networkFqdn = new Holder<>();
+ Holder<Map<String, String>> subnetIdMap = new Holder<>();
+ Holder<NetworkRollback> rollback = new Holder<>();
+
+ String cloudsite = req.getCloudSiteId();
+ if (cloudsite != null && cloudsite.equals(TESTING_KEYWORD)) {
+ String tenant = req.getTenantId();
+ if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
+ throw new NetworkException("testing.");
+ }
+ networkId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
+ neutronNetworkId.value = "55e55884-28fa-11e6-8971-0017f20fe1b8";
+ networkFqdn.value = "086f70b6-28fb-11e6-8260-0017f20fe1b8";
+ subnetIdMap.value = testMap();
+ rollback.value = new NetworkRollback();
+ } else if (req.isContrailRequest()) {
+ ContrailNetwork ctn = req.getContrailNetwork();
+ if (ctn == null) {
+ ctn = new ContrailNetwork();
+ req.setContrailNetwork(ctn);
+ }
+ adapter.createNetworkContrail(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getModelCustomizationUuid(),
+ req.getNetworkName(),
+ req.getContrailNetwork().getRouteTargets(),
+ req.getContrailNetwork().getShared(),
+ req.getContrailNetwork().getExternal(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getSubnets(),
+ req.getContrailNetwork().getPolicyFqdns(),
+ req.getContrailNetwork().getRouteTableFqdns(),
+ req.getMsoRequest(),
+ networkId,
+ neutronNetworkId,
+ networkFqdn,
+ subnetIdMap,
+ rollback);
+ } else {
+ ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
+ if (pvn == null) {
+ pvn = new ProviderVlanNetwork();
+ req.setProviderVlanNetwork(pvn);
+ }
+ adapter.createNetwork(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getModelCustomizationUuid(),
+ req.getNetworkName(),
+ req.getProviderVlanNetwork().getPhysicalNetworkName(),
+ req.getProviderVlanNetwork().getVlans(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getSubnets(),
+ req.getMsoRequest(),
+ networkId,
+ neutronNetworkId,
+ subnetIdMap,
+ rollback);
+ }
+ response = new CreateNetworkResponse(
+ req.getNetworkId(),
+ neutronNetworkId.value,
+ rollback.value.getNetworkStackId(),
+ networkFqdn.value,
+ rollback.value.getNetworkCreated(),
+ subnetIdMap.value,
+ rollback.value,
+ req.getMessageId());
+ } catch (NetworkException e) {
+ LOGGER.debug ("Exception:", e);
+ eresp = new CreateNetworkError(
+ e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("CreateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @DELETE
+ @Path("{aaiNetworkId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "DeleteNetwork",
+ response = Response.class,
+ notes = "Deletes an existing network, aaiNetworkId and DeleteNetworkRequest JSON are required")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "network has been successfully deleted"),
+ @ApiResponse(code = 202, message = "request to delete network has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "delete network failed, examine entity object for details") })
+ public Response deleteNetwork(
+ @ApiParam(value = "aaiNetworkId to be deleted ", required = true)
+ @PathParam("aaiNetworkId") String aaiNetworkId,
+ @ApiParam(value = "details of network being deleted", required = true)
+ DeleteNetworkRequest req)
+ {
+ LOGGER.debug("deleteNetwork enter: " + req.toJsonString());
+ if (aaiNetworkId == null || !aaiNetworkId.equals(req.getNetworkId())) {
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("A&AI NetworkId in URL ("+aaiNetworkId+") does not match content ("+req.getNetworkId()+")")
+ .build();
+ }
+ DeleteNetworkTask task = new DeleteNetworkTask(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_NETWORK_EXC, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while delete network", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("deleteNetwork exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class DeleteNetworkTask implements Runnable {
+ private final DeleteNetworkRequest req;
+ private DeleteNetworkResponse response = null;
+ private DeleteNetworkError eresp = null;
+ private boolean sendxml;
+
+ public DeleteNetworkTask(DeleteNetworkRequest 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<DeleteNetworkResponse>(response) {}
+ : new GenericEntity<DeleteNetworkError>(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("DeleteNetworkTask start");
+ try {
+ Holder<Boolean> networkDeleted = new Holder<>();
+ if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ networkDeleted.value = true;
+ } else {
+ adapter.deleteNetwork(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getModelCustomizationUuid(),
+ req.getNetworkStackId(),
+ req.getMsoRequest(),
+ networkDeleted);
+ }
+ response = new DeleteNetworkResponse(req.getNetworkId(), networkDeleted.value, req.getMessageId());
+ } catch (NetworkException e) {
+ LOGGER.debug ("Exception:", e);
+ eresp = new DeleteNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("DeleteNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @GET
+ @Path("{aaiNetworkId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "QueryNetwork",
+ response = Response.class,
+ notes = "Queries an existing network")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "Query network successful"),
+ @ApiResponse(code = 500, message = "Query network failed, examine entity object for details") })
+ public Response queryNetwork(
+ @ApiParam(value = "cloudSiteId", required = false)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "tenantId", required = false)
+ @QueryParam("tenantId") String tenantId,
+ @ApiParam(value = "networkStackId", required = false)
+ @QueryParam("networkStackId") String networkStackId,
+ @ApiParam(value = "skipAAI", required = false)
+ @QueryParam("skipAAI") String skipAAI,
+ @ApiParam(value = "msoRequest.requestId", required = false)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = false)
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
+ @ApiParam(value = "aaiNetworkId", required = false)
+ @PathParam("aaiNetworkId") String aaiNetworkId)
+ {
+ //This request responds synchronously only
+ LOGGER.debug ("Query network enter:" + aaiNetworkId);
+ MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
+
+ try {
+ int respStatus = HttpStatus.SC_OK;
+ QueryNetworkResponse resp = new QueryNetworkResponse(networkStackId, null, networkStackId, null, null);
+ Holder<Boolean> networkExists = new Holder<>();
+ Holder<String> networkId = new Holder<>();
+ Holder<String> neutronNetworkId = new Holder<>();
+ Holder<NetworkStatus> status = new Holder<>();
+ Holder<List<RouteTarget>> routeTargets = new Holder<>();
+ Holder<Map<String, String>> subnetIdMap = new Holder<>();
+
+ adapter.queryNetworkContrail(cloudSiteId, tenantId, aaiNetworkId, msoRequest,
+ networkExists, networkId, neutronNetworkId, status, routeTargets, subnetIdMap);
+
+ if (!networkExists.value) {
+ LOGGER.debug ("network not found");
+ respStatus = HttpStatus.SC_NOT_FOUND;
+ } else {
+ LOGGER.debug ("network found" + networkId.value + ", status=" + status.value);
+ resp.setNetworkExists(networkExists.value);
+ resp.setNetworkId(networkId.value);
+ resp.setNeutronNetworkId(neutronNetworkId.value);
+ resp.setNetworkStatus(status.value);
+ resp.setRouteTargets(routeTargets.value);
+ resp.setSubnetIdMap(subnetIdMap.value);
+ }
+ LOGGER.debug ("Query network exit");
+ return Response
+ .status(respStatus)
+ .entity(new GenericEntity<QueryNetworkResponse>(resp) {})
+ .build();
+ } catch (NetworkException e) {
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, aaiNetworkId, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception when query VNF", e);
+ QueryNetworkError err = new QueryNetworkError();
+ err.setMessage(e.getMessage());
+ err.setCategory(MsoExceptionCategory.INTERNAL);
+ return Response
+ .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
+ .entity(new GenericEntity<QueryNetworkError>(err) {})
+ .build();
+ }
+ }
+
+ @DELETE
+ @Path("{aaiNetworkId}/rollback")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "RollbackNetwork",
+ response = Response.class,
+ notes = "Rollback an existing network")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "Rollback network successful"),
+ @ApiResponse(code = 202, message = "Rollback network request has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "Rollback network failed, examine entity object for details") })
+ public Response rollbackNetwork(
+ @ApiParam(value = "RollbackNetworkRequest in JSON format", required = true)
+ RollbackNetworkRequest req)
+ {
+ LOGGER.debug("rollbackNetwork enter: " + req.toJsonString());
+ RollbackNetworkTask task = new RollbackNetworkTask(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_NULL, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in rollbackNetwork", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug("rollbackNetwork exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class RollbackNetworkTask implements Runnable {
+ private final RollbackNetworkRequest req;
+ private RollbackNetworkResponse response = null;
+ private RollbackNetworkError eresp = null;
+ private boolean sendxml;
+
+ public RollbackNetworkTask(RollbackNetworkRequest 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<RollbackNetworkResponse>(response) {}
+ : new GenericEntity<RollbackNetworkError>(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("RollbackNetworkTask start");
+ try {
+ NetworkRollback nwr = req.getNetworkRollback();
+ adapter.rollbackNetwork(nwr);
+ response = new RollbackNetworkResponse(true, req.getMessageId());
+ } catch (NetworkException e) {
+ LOGGER.debug ("Exception:", e);
+ eresp = new RollbackNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("RollbackNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @PUT
+ @Path("{aaiNetworkId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "UpdateNetwork",
+ response = Response.class,
+ notes = "Update an existing network")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "Update network successful"),
+ @ApiResponse(code = 202, message = "Update network request has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "Update network failed, examine entity object for details") })
+ public Response updateNetwork(
+ @ApiParam(value = "aaiNetworkId", required = true)
+ @PathParam("aaiNetworkId") String aaiNetworkId,
+ @ApiParam(value = "UpdateNetworkRequest in JSON format", required = true)
+ UpdateNetworkRequest req)
+ {
+ LOGGER.debug("updateNetwork enter: " + req.toJsonString());
+ if (aaiNetworkId == null || !aaiNetworkId.equals(req.getNetworkId())) {
+ return Response
+ .status(HttpStatus.SC_BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("A&AI NetworkId in URL ("+aaiNetworkId+") does not match content ("+req.getNetworkId()+")")
+ .build();
+ }
+ UpdateNetworkTask task = new UpdateNetworkTask(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_NETWORK_ERR, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in updateNetwork", e);
+ return Response.serverError().build();
+ }
+ // send sync response (ACK) to caller
+ LOGGER.debug ("updateNetwork exit");
+ return Response.status(HttpStatus.SC_ACCEPTED).build();
+ }
+ }
+
+ public class UpdateNetworkTask implements Runnable {
+ private final UpdateNetworkRequest req;
+ private UpdateNetworkResponse response = null;
+ private UpdateNetworkError eresp = null;
+ private boolean sendxml;
+
+ public UpdateNetworkTask(UpdateNetworkRequest 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<UpdateNetworkResponse>(response) {}
+ : new GenericEntity<UpdateNetworkError>(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("UpdateNetworkTask start");
+ try {
+ Holder<Map<String, String>> subnetIdMap = new Holder<>();
+ Holder<NetworkRollback> rollback = new Holder<> ();
+
+ if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ subnetIdMap.value = testMap();
+ NetworkRollback rb = new NetworkRollback ();
+ rb.setCloudId(req.getCloudSiteId());
+ rb.setTenantId(req.getTenantId());
+ rb.setMsoRequest(req.getMsoRequest());
+ rollback.value = rb;
+ } else if (req.isContrailRequest()) {
+ ContrailNetwork ctn = req.getContrailNetwork();
+ if (ctn == null) {
+ ctn = new ContrailNetwork();
+ req.setContrailNetwork(ctn);
+ }
+ adapter.updateNetworkContrail(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getModelCustomizationUuid(),
+ req.getNetworkStackId(),
+ req.getNetworkName(),
+ req.getContrailNetwork().getRouteTargets(),
+ req.getContrailNetwork().getShared(),
+ req.getContrailNetwork().getExternal(),
+ req.getSubnets(),
+ req.getContrailNetwork().getPolicyFqdns(),
+ req.getContrailNetwork().getRouteTableFqdns(),
+ req.getMsoRequest(),
+ subnetIdMap,
+ rollback);
+ } else {
+ ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
+ if (pvn == null) {
+ pvn = new ProviderVlanNetwork();
+ req.setProviderVlanNetwork(pvn);
+ }
+ adapter.updateNetwork(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getModelCustomizationUuid(),
+ req.getNetworkStackId(),
+ req.getNetworkName(),
+ req.getProviderVlanNetwork().getPhysicalNetworkName(),
+ req.getProviderVlanNetwork().getVlans(),
+ req.getSubnets(),
+ req.getMsoRequest(),
+ subnetIdMap,
+ rollback);
+ }
+ response = new UpdateNetworkResponse(
+ req.getNetworkId(),
+ null, // NeutronNetworkId is not available from an update
+ subnetIdMap.value,
+ req.getMessageId());
+ } catch (NetworkException e) {
+ LOGGER.debug ("Exception:", e);
+ eresp = new UpdateNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("UpdateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ public static Map<String, String> testMap() {
+ Map<String, String> m = new HashMap<>();
+ m.put("mickey", "7");
+ m.put("clyde", "10");
+ m.put("wayne", "99");
+ return m;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotification.java
new file mode 100644
index 0000000000..8135088d7c
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotification.java
@@ -0,0 +1,437 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for createNetworkNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="createNetworkNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/networkNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="neutronNetworkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="subnetIdMap" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="rollback" type="{http://org.onap.so/networkNotify}networkRollback" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "createNetworkNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "networkId",
+ "neutronNetworkId",
+ "subnetIdMap",
+ "rollback"
+})
+public class CreateNetworkNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected String networkId;
+ protected String neutronNetworkId;
+ protected CreateNetworkNotification.SubnetIdMap subnetIdMap;
+ protected NetworkRollback rollback;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the networkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkId() {
+ return networkId;
+ }
+
+ /**
+ * Sets the value of the networkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkId(String value) {
+ this.networkId = value;
+ }
+
+ /**
+ * Gets the value of the neutronNetworkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNeutronNetworkId() {
+ return neutronNetworkId;
+ }
+
+ /**
+ * Sets the value of the neutronNetworkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNeutronNetworkId(String value) {
+ this.neutronNetworkId = value;
+ }
+
+ /**
+ * Gets the value of the subnetIdMap property.
+ *
+ * @return
+ * possible object is
+ * {@link CreateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public CreateNetworkNotification.SubnetIdMap getSubnetIdMap() {
+ return subnetIdMap;
+ }
+
+ /**
+ * Sets the value of the subnetIdMap property.
+ *
+ * @param value
+ * allowed object is
+ * {@link CreateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public void setSubnetIdMap(CreateNetworkNotification.SubnetIdMap value) {
+ this.subnetIdMap = value;
+ }
+
+ /**
+ * Gets the value of the rollback property.
+ *
+ * @return
+ * possible object is
+ * {@link NetworkRollback }
+ *
+ */
+ public NetworkRollback getRollback() {
+ return rollback;
+ }
+
+ /**
+ * Sets the value of the rollback property.
+ *
+ * @param value
+ * allowed object is
+ * {@link NetworkRollback }
+ *
+ */
+ public void setRollback(NetworkRollback value) {
+ this.rollback = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class SubnetIdMap {
+
+ protected List<CreateNetworkNotification.SubnetIdMap.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link CreateNetworkNotification.SubnetIdMap.Entry }
+ *
+ *
+ */
+ public List<CreateNetworkNotification.SubnetIdMap.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<CreateNetworkNotification.SubnetIdMap.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotificationResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotificationResponse.java
new file mode 100644
index 0000000000..a0e40c0e6a
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/CreateNetworkNotificationResponse.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for createNetworkNotificationResponse complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="createNetworkNotificationResponse">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "createNetworkNotificationResponse")
+public class CreateNetworkNotificationResponse {
+
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotification.java
new file mode 100644
index 0000000000..d4f992a9b4
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotification.java
@@ -0,0 +1,181 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for deleteNetworkNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="deleteNetworkNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/networkNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkDeleted" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "deleteNetworkNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "networkDeleted"
+})
+public class DeleteNetworkNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected Boolean networkDeleted;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the networkDeleted property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public Boolean isNetworkDeleted() {
+ return networkDeleted;
+ }
+
+ /**
+ * Sets the value of the networkDeleted property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setNetworkDeleted(Boolean value) {
+ this.networkDeleted = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotificationResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotificationResponse.java
new file mode 100644
index 0000000000..76eb8115d5
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/DeleteNetworkNotificationResponse.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for deleteNetworkNotificationResponse complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="deleteNetworkNotificationResponse">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "deleteNetworkNotificationResponse")
+public class DeleteNetworkNotificationResponse {
+
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoExceptionCategory.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoExceptionCategory.java
new file mode 100644
index 0000000000..8c18a59e68
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoExceptionCategory.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for msoExceptionCategory.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p>
+ * <pre>
+ * &lt;simpleType name="msoExceptionCategory">
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * &lt;enumeration value="OPENSTACK"/>
+ * &lt;enumeration value="IO"/>
+ * &lt;enumeration value="INTERNAL"/>
+ * &lt;enumeration value="USERDATA"/>
+ * &lt;/restriction>
+ * &lt;/simpleType>
+ * </pre>
+ *
+ */
+@XmlType(name = "msoExceptionCategory")
+@XmlEnum
+public enum MsoExceptionCategory {
+
+ OPENSTACK,
+ IO,
+ INTERNAL,
+ USERDATA;
+
+ public String value() {
+ return name();
+ }
+
+ public static MsoExceptionCategory fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoRequest.java
new file mode 100644
index 0000000000..aa6f34f2e0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/MsoRequest.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for msoRequest complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="msoRequest">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="requestId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="serviceInstanceId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "msoRequest", propOrder = {
+ "requestId",
+ "serviceInstanceId"
+})
+public class MsoRequest {
+
+ protected String requestId;
+ protected String serviceInstanceId;
+
+ /**
+ * Gets the value of the requestId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets the value of the requestId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setRequestId(String value) {
+ this.requestId = value;
+ }
+
+ /**
+ * Gets the value of the serviceInstanceId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getServiceInstanceId() {
+ return serviceInstanceId;
+ }
+
+ /**
+ * Sets the value of the serviceInstanceId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setServiceInstanceId(String value) {
+ this.serviceInstanceId = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify.java
new file mode 100644
index 0000000000..0433aab0cc
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify.java
@@ -0,0 +1,191 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.util.List;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.ws.Action;
+import javax.xml.ws.RequestWrapper;
+import javax.xml.ws.ResponseWrapper;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.9-b14002
+ * Generated source version: 2.2
+ *
+ */
+@WebService(name = "networkAdapterNotify", targetNamespace = "http://org.onap.so/networkNotify")
+@XmlSeeAlso({
+ ObjectFactory.class
+})
+public interface NetworkAdapterNotify {
+
+
+ /**
+ *
+ * @param exception
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ */
+ @WebMethod
+ @RequestWrapper(localName = "rollbackNetworkNotification", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.RollbackNetworkNotification")
+ @ResponseWrapper(localName = "rollbackNetworkNotificationResponse", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.RollbackNetworkNotificationResponse")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/rollbackNetworkNotificationRequest", output = "http://org.onap.so/notify/adapterNotify/rollbackNetworkNotificationResponse")
+ public void rollbackNetworkNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage);
+
+ /**
+ *
+ * @param exception
+ * @param vlans
+ * @param networkExists
+ * @param errorMessage
+ * @param messageId
+ * @param networkId
+ * @param completed
+ * @param neutronNetworkId
+ * @param status
+ * @param subnetIdMap
+ */
+ @WebMethod
+ @RequestWrapper(localName = "queryNetworkNotification", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.QueryNetworkNotification")
+ @ResponseWrapper(localName = "queryNetworkNotificationResponse", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.QueryNetworkNotificationResponse")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/queryNetworkNotificationRequest", output = "http://org.onap.so/notify/adapterNotify/queryNetworkNotificationResponse")
+ public void queryNetworkNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "networkExists", targetNamespace = "")
+ Boolean networkExists,
+ @WebParam(name = "networkId", targetNamespace = "")
+ String networkId,
+ @WebParam(name = "neutronNetworkId", targetNamespace = "")
+ String neutronNetworkId,
+ @WebParam(name = "status", targetNamespace = "")
+ NetworkStatus status,
+ @WebParam(name = "vlans", targetNamespace = "")
+ List<Integer> vlans,
+ @WebParam(name = "subnetIdMap", targetNamespace = "")
+ org.onap.so.adapters.network.async.client.QueryNetworkNotification.SubnetIdMap subnetIdMap);
+
+ /**
+ *
+ * @param exception
+ * @param rollback
+ * @param errorMessage
+ * @param messageId
+ * @param networkId
+ * @param completed
+ * @param neutronNetworkId
+ * @param subnetIdMap
+ */
+ @WebMethod
+ @RequestWrapper(localName = "createNetworkNotification", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.CreateNetworkNotification")
+ @ResponseWrapper(localName = "createNetworkNotificationResponse", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.CreateNetworkNotificationResponse")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/createNetworkNotificationRequest", output = "http://org.onap.so/notify/adapterNotify/createNetworkNotificationResponse")
+ public void createNetworkNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "networkId", targetNamespace = "")
+ String networkId,
+ @WebParam(name = "neutronNetworkId", targetNamespace = "")
+ String neutronNetworkId,
+ @WebParam(name = "subnetIdMap", targetNamespace = "")
+ org.onap.so.adapters.network.async.client.CreateNetworkNotification.SubnetIdMap subnetIdMap,
+ @WebParam(name = "rollback", targetNamespace = "")
+ NetworkRollback rollback);
+
+ /**
+ *
+ * @param exception
+ * @param networkDeleted
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ */
+ @WebMethod
+ @RequestWrapper(localName = "deleteNetworkNotification", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.DeleteNetworkNotification")
+ @ResponseWrapper(localName = "deleteNetworkNotificationResponse", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.DeleteNetworkNotificationResponse")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/deleteNetworkNotificationRequest", output = "http://org.onap.so/notify/adapterNotify/deleteNetworkNotificationResponse")
+ public void deleteNetworkNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "networkDeleted", targetNamespace = "")
+ Boolean networkDeleted);
+
+ /**
+ *
+ * @param exception
+ * @param rollback
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ * @param subnetIdMap
+ */
+ @WebMethod
+ @RequestWrapper(localName = "updateNetworkNotification", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.UpdateNetworkNotification")
+ @ResponseWrapper(localName = "updateNetworkNotificationResponse", targetNamespace = "http://org.onap.so/networkNotify", className = "org.onap.so.adapters.network.async.client.UpdateNetworkNotificationResponse")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/updateNetworkNotificationRequest", output = "http://org.onap.so/notify/adapterNotify/updateNetworkNotificationResponse")
+ public void updateNetworkNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "subnetIdMap", targetNamespace = "")
+ org.onap.so.adapters.network.async.client.UpdateNetworkNotification.SubnetIdMap subnetIdMap,
+ @WebParam(name = "rollback", targetNamespace = "")
+ NetworkRollback rollback);
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify_Service.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify_Service.java
new file mode 100644
index 0000000000..fb69db702a
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkAdapterNotify_Service.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebEndpoint;
+import javax.xml.ws.WebServiceClient;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.WebServiceFeature;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.9-b14002
+ * Generated source version: 2.2
+ *
+ */
+@WebServiceClient(name = "networkAdapterNotify", targetNamespace = "http://org.onap.so/networkNotify", wsdlLocation = "/NetworkAdapterNotify.wsdl")
+public class NetworkAdapterNotify_Service
+ extends Service
+{
+
+ private final static URL NETWORKADAPTERNOTIFY_WSDL_LOCATION;
+ private final static WebServiceException NETWORKADAPTERNOTIFY_EXCEPTION;
+ private final static QName NETWORKADAPTERNOTIFY_QNAME = new QName("http://org.onap.so/networkNotify", "networkAdapterNotify");
+
+ static {
+ NETWORKADAPTERNOTIFY_WSDL_LOCATION = org.onap.so.adapters.network.async.client.NetworkAdapterNotify_Service.class.getResource("/NetworkAdapterNotify.wsdl");
+ WebServiceException e = null;
+ if (NETWORKADAPTERNOTIFY_WSDL_LOCATION == null) {
+ e = new WebServiceException("Cannot find '/NetworkAdapterNotify.wsdl' wsdl. Place the resource correctly in the classpath.");
+ }
+ NETWORKADAPTERNOTIFY_EXCEPTION = e;
+ }
+
+ public NetworkAdapterNotify_Service() {
+ super(__getWsdlLocation(), NETWORKADAPTERNOTIFY_QNAME);
+ }
+
+ public NetworkAdapterNotify_Service(WebServiceFeature... features) {
+ super(__getWsdlLocation(), NETWORKADAPTERNOTIFY_QNAME, features);
+ }
+
+ public NetworkAdapterNotify_Service(URL wsdlLocation) {
+ super(wsdlLocation, NETWORKADAPTERNOTIFY_QNAME);
+ }
+
+ public NetworkAdapterNotify_Service(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, NETWORKADAPTERNOTIFY_QNAME, features);
+ }
+
+ public NetworkAdapterNotify_Service(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public NetworkAdapterNotify_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ *
+ * @return
+ * returns NetworkAdapterNotify
+ */
+ @WebEndpoint(name = "MsoNetworkAdapterAsyncImplPort")
+ public NetworkAdapterNotify getMsoNetworkAdapterAsyncImplPort() {
+ return super.getPort(new QName("http://org.onap.so/networkNotify", "MsoNetworkAdapterAsyncImplPort"), NetworkAdapterNotify.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
+ * @return
+ * returns NetworkAdapterNotify
+ */
+ @WebEndpoint(name = "MsoNetworkAdapterAsyncImplPort")
+ public NetworkAdapterNotify getMsoNetworkAdapterAsyncImplPort(WebServiceFeature... features) {
+ return super.getPort(new QName("http://org.onap.so/networkNotify", "MsoNetworkAdapterAsyncImplPort"), NetworkAdapterNotify.class, features);
+ }
+
+ private static URL __getWsdlLocation() {
+ if (NETWORKADAPTERNOTIFY_EXCEPTION!= null) {
+ throw NETWORKADAPTERNOTIFY_EXCEPTION;
+ }
+ return NETWORKADAPTERNOTIFY_WSDL_LOCATION;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkRollback.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkRollback.java
new file mode 100644
index 0000000000..4fde850a53
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkRollback.java
@@ -0,0 +1,370 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for networkRollback complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="networkRollback">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="cloudId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="msoRequest" type="{http://org.onap.so/networkNotify}msoRequest" minOccurs="0"/>
+ * &lt;element name="networkCreated" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="networkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkStackId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkUpdated" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="neutronNetworkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="physicalNetwork" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="tenantId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="vlans" type="{http://www.w3.org/2001/XMLSchema}int" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "networkRollback", propOrder = {
+ "cloudId",
+ "msoRequest",
+ "networkCreated",
+ "networkId",
+ "networkStackId",
+ "networkName",
+ "networkType",
+ "networkUpdated",
+ "neutronNetworkId",
+ "physicalNetwork",
+ "tenantId",
+ "vlans"
+})
+public class NetworkRollback {
+
+ protected String cloudId;
+ protected MsoRequest msoRequest;
+ protected boolean networkCreated;
+ protected String networkId;
+ protected String networkStackId;
+ protected String networkName;
+ protected String networkType;
+ protected boolean networkUpdated;
+ protected String neutronNetworkId;
+ protected String physicalNetwork;
+ protected String tenantId;
+ @XmlElement(nillable = true)
+ protected List<Integer> vlans;
+
+ /**
+ * Gets the value of the cloudId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getCloudId() {
+ return cloudId;
+ }
+
+ /**
+ * Sets the value of the cloudId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setCloudId(String value) {
+ this.cloudId = value;
+ }
+
+ /**
+ * Gets the value of the msoRequest property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoRequest }
+ *
+ */
+ public MsoRequest getMsoRequest() {
+ return msoRequest;
+ }
+
+ /**
+ * Sets the value of the msoRequest property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoRequest }
+ *
+ */
+ public void setMsoRequest(MsoRequest value) {
+ this.msoRequest = value;
+ }
+
+ /**
+ * Gets the value of the networkCreated property.
+ *
+ */
+ public boolean isNetworkCreated() {
+ return networkCreated;
+ }
+
+ /**
+ * Sets the value of the networkCreated property.
+ *
+ */
+ public void setNetworkCreated(boolean value) {
+ this.networkCreated = value;
+ }
+
+ /**
+ * Gets the value of the networkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkId() {
+ return networkId;
+ }
+
+ /**
+ * Sets the value of the networkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkId(String value) {
+ this.networkId = value;
+ }
+
+ /**
+ * Gets the value of the networkStackId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkStackId() {
+ return networkStackId;
+ }
+
+ /**
+ * Sets the value of the networkStackId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkStackId(String value) {
+ this.networkStackId = value;
+ }
+
+ /**
+ * Gets the value of the networkName property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkName() {
+ return networkName;
+ }
+
+ /**
+ * Sets the value of the networkName property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkName(String value) {
+ this.networkName = value;
+ }
+
+ /**
+ * Gets the value of the networkType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkType() {
+ return networkType;
+ }
+
+ /**
+ * Sets the value of the networkType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkType(String value) {
+ this.networkType = value;
+ }
+
+ /**
+ * Gets the value of the networkUpdated property.
+ *
+ */
+ public boolean isNetworkUpdated() {
+ return networkUpdated;
+ }
+
+ /**
+ * Sets the value of the networkUpdated property.
+ *
+ */
+ public void setNetworkUpdated(boolean value) {
+ this.networkUpdated = value;
+ }
+
+ /**
+ * Gets the value of the neutronNetworkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNeutronNetworkId() {
+ return neutronNetworkId;
+ }
+
+ /**
+ * Sets the value of the neutronNetworkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNeutronNetworkId(String value) {
+ this.neutronNetworkId = value;
+ }
+
+ /**
+ * Gets the value of the physicalNetwork property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPhysicalNetwork() {
+ return physicalNetwork;
+ }
+
+ /**
+ * Sets the value of the physicalNetwork property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPhysicalNetwork(String value) {
+ this.physicalNetwork = value;
+ }
+
+ /**
+ * Gets the value of the tenantId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ /**
+ * Sets the value of the tenantId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTenantId(String value) {
+ this.tenantId = value;
+ }
+
+ /**
+ * Gets the value of the vlans property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the vlans property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getVlans().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Integer }
+ *
+ *
+ */
+ public List<Integer> getVlans() {
+ if (vlans == null) {
+ vlans = new ArrayList<Integer>();
+ }
+ return this.vlans;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkStatus.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkStatus.java
new file mode 100644
index 0000000000..982f214bd8
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/NetworkStatus.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for networkStatus.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p>
+ * <pre>
+ * &lt;simpleType name="networkStatus">
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * &lt;enumeration value="NOTFOUND"/>
+ * &lt;enumeration value="ACTIVE"/>
+ * &lt;enumeration value="DOWN"/>
+ * &lt;enumeration value="BUILD"/>
+ * &lt;enumeration value="ERROR"/>
+ * &lt;enumeration value="UNKNOWN"/>
+ * &lt;/restriction>
+ * &lt;/simpleType>
+ * </pre>
+ *
+ */
+@XmlType(name = "networkStatus")
+@XmlEnum
+public enum NetworkStatus {
+
+ NOTFOUND,
+ ACTIVE,
+ DOWN,
+ BUILD,
+ ERROR,
+ UNKNOWN;
+
+ public String value() {
+ return name();
+ }
+
+ public static NetworkStatus fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/ObjectFactory.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/ObjectFactory.java
new file mode 100644
index 0000000000..91243769aa
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/ObjectFactory.java
@@ -0,0 +1,298 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.onap.so.adapters.network.async.client package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _RollbackNetworkNotification_QNAME = new QName("http://org.onap.so/networkNotify", "rollbackNetworkNotification");
+ private final static QName _UpdateNetworkNotification_QNAME = new QName("http://org.onap.so/networkNotify", "updateNetworkNotification");
+ private final static QName _QueryNetworkNotificationResponse_QNAME = new QName("http://org.onap.so/networkNotify", "queryNetworkNotificationResponse");
+ private final static QName _UpdateNetworkNotificationResponse_QNAME = new QName("http://org.onap.so/networkNotify", "updateNetworkNotificationResponse");
+ private final static QName _CreateNetworkNotificationResponse_QNAME = new QName("http://org.onap.so/networkNotify", "createNetworkNotificationResponse");
+ private final static QName _DeleteNetworkNotification_QNAME = new QName("http://org.onap.so/networkNotify", "deleteNetworkNotification");
+ private final static QName _DeleteNetworkNotificationResponse_QNAME = new QName("http://org.onap.so/networkNotify", "deleteNetworkNotificationResponse");
+ private final static QName _CreateNetworkNotification_QNAME = new QName("http://org.onap.so/networkNotify", "createNetworkNotification");
+ private final static QName _QueryNetworkNotification_QNAME = new QName("http://org.onap.so/networkNotify", "queryNetworkNotification");
+ private final static QName _RollbackNetworkNotificationResponse_QNAME = new QName("http://org.onap.so/networkNotify", "rollbackNetworkNotificationResponse");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.onap.so.adapters.network.async.client
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link QueryNetworkNotification }
+ *
+ */
+ public QueryNetworkNotification createQueryNetworkNotification() {
+ return new QueryNetworkNotification();
+ }
+
+ /**
+ * Create an instance of {@link QueryNetworkNotification.SubnetIdMap }
+ *
+ */
+ public QueryNetworkNotification.SubnetIdMap createQueryNetworkNotificationSubnetIdMap() {
+ return new QueryNetworkNotification.SubnetIdMap();
+ }
+
+ /**
+ * Create an instance of {@link CreateNetworkNotification }
+ *
+ */
+ public CreateNetworkNotification createCreateNetworkNotification() {
+ return new CreateNetworkNotification();
+ }
+
+ /**
+ * Create an instance of {@link CreateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public CreateNetworkNotification.SubnetIdMap createCreateNetworkNotificationSubnetIdMap() {
+ return new CreateNetworkNotification.SubnetIdMap();
+ }
+
+ /**
+ * Create an instance of {@link UpdateNetworkNotification }
+ *
+ */
+ public UpdateNetworkNotification createUpdateNetworkNotification() {
+ return new UpdateNetworkNotification();
+ }
+
+ /**
+ * Create an instance of {@link UpdateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public UpdateNetworkNotification.SubnetIdMap createUpdateNetworkNotificationSubnetIdMap() {
+ return new UpdateNetworkNotification.SubnetIdMap();
+ }
+
+ /**
+ * Create an instance of {@link UpdateNetworkNotificationResponse }
+ *
+ */
+ public UpdateNetworkNotificationResponse createUpdateNetworkNotificationResponse() {
+ return new UpdateNetworkNotificationResponse();
+ }
+
+ /**
+ * Create an instance of {@link CreateNetworkNotificationResponse }
+ *
+ */
+ public CreateNetworkNotificationResponse createCreateNetworkNotificationResponse() {
+ return new CreateNetworkNotificationResponse();
+ }
+
+ /**
+ * Create an instance of {@link RollbackNetworkNotification }
+ *
+ */
+ public RollbackNetworkNotification createRollbackNetworkNotification() {
+ return new RollbackNetworkNotification();
+ }
+
+ /**
+ * Create an instance of {@link QueryNetworkNotificationResponse }
+ *
+ */
+ public QueryNetworkNotificationResponse createQueryNetworkNotificationResponse() {
+ return new QueryNetworkNotificationResponse();
+ }
+
+ /**
+ * Create an instance of {@link RollbackNetworkNotificationResponse }
+ *
+ */
+ public RollbackNetworkNotificationResponse createRollbackNetworkNotificationResponse() {
+ return new RollbackNetworkNotificationResponse();
+ }
+
+ /**
+ * Create an instance of {@link DeleteNetworkNotification }
+ *
+ */
+ public DeleteNetworkNotification createDeleteNetworkNotification() {
+ return new DeleteNetworkNotification();
+ }
+
+ /**
+ * Create an instance of {@link DeleteNetworkNotificationResponse }
+ *
+ */
+ public DeleteNetworkNotificationResponse createDeleteNetworkNotificationResponse() {
+ return new DeleteNetworkNotificationResponse();
+ }
+
+ /**
+ * Create an instance of {@link NetworkRollback }
+ *
+ */
+ public NetworkRollback createNetworkRollback() {
+ return new NetworkRollback();
+ }
+
+ /**
+ * Create an instance of {@link MsoRequest }
+ *
+ */
+ public MsoRequest createMsoRequest() {
+ return new MsoRequest();
+ }
+
+ /**
+ * Create an instance of {@link QueryNetworkNotification.SubnetIdMap.Entry }
+ *
+ */
+ public QueryNetworkNotification.SubnetIdMap.Entry createQueryNetworkNotificationSubnetIdMapEntry() {
+ return new QueryNetworkNotification.SubnetIdMap.Entry();
+ }
+
+ /**
+ * Create an instance of {@link CreateNetworkNotification.SubnetIdMap.Entry }
+ *
+ */
+ public CreateNetworkNotification.SubnetIdMap.Entry createCreateNetworkNotificationSubnetIdMapEntry() {
+ return new CreateNetworkNotification.SubnetIdMap.Entry();
+ }
+
+ /**
+ * Create an instance of {@link UpdateNetworkNotification.SubnetIdMap.Entry }
+ *
+ */
+ public UpdateNetworkNotification.SubnetIdMap.Entry createUpdateNetworkNotificationSubnetIdMapEntry() {
+ return new UpdateNetworkNotification.SubnetIdMap.Entry();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link RollbackNetworkNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "rollbackNetworkNotification")
+ public JAXBElement<RollbackNetworkNotification> createRollbackNetworkNotification(RollbackNetworkNotification value) {
+ return new JAXBElement<RollbackNetworkNotification>(_RollbackNetworkNotification_QNAME, RollbackNetworkNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link UpdateNetworkNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "updateNetworkNotification")
+ public JAXBElement<UpdateNetworkNotification> createUpdateNetworkNotification(UpdateNetworkNotification value) {
+ return new JAXBElement<UpdateNetworkNotification>(_UpdateNetworkNotification_QNAME, UpdateNetworkNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link QueryNetworkNotificationResponse }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "queryNetworkNotificationResponse")
+ public JAXBElement<QueryNetworkNotificationResponse> createQueryNetworkNotificationResponse(QueryNetworkNotificationResponse value) {
+ return new JAXBElement<QueryNetworkNotificationResponse>(_QueryNetworkNotificationResponse_QNAME, QueryNetworkNotificationResponse.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link UpdateNetworkNotificationResponse }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "updateNetworkNotificationResponse")
+ public JAXBElement<UpdateNetworkNotificationResponse> createUpdateNetworkNotificationResponse(UpdateNetworkNotificationResponse value) {
+ return new JAXBElement<UpdateNetworkNotificationResponse>(_UpdateNetworkNotificationResponse_QNAME, UpdateNetworkNotificationResponse.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link CreateNetworkNotificationResponse }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "createNetworkNotificationResponse")
+ public JAXBElement<CreateNetworkNotificationResponse> createCreateNetworkNotificationResponse(CreateNetworkNotificationResponse value) {
+ return new JAXBElement<CreateNetworkNotificationResponse>(_CreateNetworkNotificationResponse_QNAME, CreateNetworkNotificationResponse.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link DeleteNetworkNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "deleteNetworkNotification")
+ public JAXBElement<DeleteNetworkNotification> createDeleteNetworkNotification(DeleteNetworkNotification value) {
+ return new JAXBElement<DeleteNetworkNotification>(_DeleteNetworkNotification_QNAME, DeleteNetworkNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link DeleteNetworkNotificationResponse }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "deleteNetworkNotificationResponse")
+ public JAXBElement<DeleteNetworkNotificationResponse> createDeleteNetworkNotificationResponse(DeleteNetworkNotificationResponse value) {
+ return new JAXBElement<DeleteNetworkNotificationResponse>(_DeleteNetworkNotificationResponse_QNAME, DeleteNetworkNotificationResponse.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link CreateNetworkNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "createNetworkNotification")
+ public JAXBElement<CreateNetworkNotification> createCreateNetworkNotification(CreateNetworkNotification value) {
+ return new JAXBElement<CreateNetworkNotification>(_CreateNetworkNotification_QNAME, CreateNetworkNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link QueryNetworkNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "queryNetworkNotification")
+ public JAXBElement<QueryNetworkNotification> createQueryNetworkNotification(QueryNetworkNotification value) {
+ return new JAXBElement<QueryNetworkNotification>(_QueryNetworkNotification_QNAME, QueryNetworkNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link RollbackNetworkNotificationResponse }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/networkNotify", name = "rollbackNetworkNotificationResponse")
+ public JAXBElement<RollbackNetworkNotificationResponse> createRollbackNetworkNotificationResponse(RollbackNetworkNotificationResponse value) {
+ return new JAXBElement<RollbackNetworkNotificationResponse>(_RollbackNetworkNotificationResponse_QNAME, RollbackNetworkNotificationResponse.class, null, value);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotification.java
new file mode 100644
index 0000000000..55a8e3d0d1
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotification.java
@@ -0,0 +1,497 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for queryNetworkNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="queryNetworkNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/networkNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="networkExists" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ * &lt;element name="networkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="neutronNetworkId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="status" type="{http://org.onap.so/networkNotify}networkStatus" minOccurs="0"/>
+ * &lt;element name="vlans" type="{http://www.w3.org/2001/XMLSchema}int" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;element name="subnetIdMap" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "queryNetworkNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "networkExists",
+ "networkId",
+ "neutronNetworkId",
+ "status",
+ "vlans",
+ "subnetIdMap"
+})
+public class QueryNetworkNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected Boolean networkExists;
+ protected String networkId;
+ protected String neutronNetworkId;
+ protected NetworkStatus status;
+ @XmlElement(type = Integer.class)
+ protected List<Integer> vlans;
+ protected QueryNetworkNotification.SubnetIdMap subnetIdMap;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the networkExists property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public Boolean isNetworkExists() {
+ return networkExists;
+ }
+
+ /**
+ * Sets the value of the networkExists property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setNetworkExists(Boolean value) {
+ this.networkExists = value;
+ }
+
+ /**
+ * Gets the value of the networkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNetworkId() {
+ return networkId;
+ }
+
+ /**
+ * Sets the value of the networkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNetworkId(String value) {
+ this.networkId = value;
+ }
+
+ /**
+ * Gets the value of the neutronNetworkId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNeutronNetworkId() {
+ return neutronNetworkId;
+ }
+
+ /**
+ * Sets the value of the neutronNetworkId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNeutronNetworkId(String value) {
+ this.neutronNetworkId = value;
+ }
+
+ /**
+ * Gets the value of the status property.
+ *
+ * @return
+ * possible object is
+ * {@link NetworkStatus }
+ *
+ */
+ public NetworkStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the value of the status property.
+ *
+ * @param value
+ * allowed object is
+ * {@link NetworkStatus }
+ *
+ */
+ public void setStatus(NetworkStatus value) {
+ this.status = value;
+ }
+
+ /**
+ * Gets the value of the vlans property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the vlans property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getVlans().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Integer }
+ *
+ *
+ */
+ public List<Integer> getVlans() {
+ if (vlans == null) {
+ vlans = new ArrayList<Integer>();
+ }
+ return this.vlans;
+ }
+
+ /**
+ * Gets the value of the subnetIdMap property.
+ *
+ * @return
+ * possible object is
+ * {@link QueryNetworkNotification.SubnetIdMap }
+ *
+ */
+ public QueryNetworkNotification.SubnetIdMap getSubnetIdMap() {
+ return subnetIdMap;
+ }
+
+ /**
+ * Sets the value of the subnetIdMap property.
+ *
+ * @param value
+ * allowed object is
+ * {@link QueryNetworkNotification.SubnetIdMap }
+ *
+ */
+ public void setSubnetIdMap(QueryNetworkNotification.SubnetIdMap value) {
+ this.subnetIdMap = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class SubnetIdMap {
+
+ protected List<QueryNetworkNotification.SubnetIdMap.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link QueryNetworkNotification.SubnetIdMap.Entry }
+ *
+ *
+ */
+ public List<QueryNetworkNotification.SubnetIdMap.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<QueryNetworkNotification.SubnetIdMap.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotificationResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotificationResponse.java
new file mode 100644
index 0000000000..0320df27fc
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/QueryNetworkNotificationResponse.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for queryNetworkNotificationResponse complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="queryNetworkNotificationResponse">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "queryNetworkNotificationResponse")
+public class QueryNetworkNotificationResponse {
+
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotification.java
new file mode 100644
index 0000000000..08f37fc85d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotification.java
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for rollbackNetworkNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="rollbackNetworkNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/networkNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "rollbackNetworkNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage"
+})
+public class RollbackNetworkNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotificationResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotificationResponse.java
new file mode 100644
index 0000000000..44db3a1583
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/RollbackNetworkNotificationResponse.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for rollbackNetworkNotificationResponse complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="rollbackNetworkNotificationResponse">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "rollbackNetworkNotificationResponse")
+public class RollbackNetworkNotificationResponse {
+
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotification.java
new file mode 100644
index 0000000000..f61d0a8dea
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotification.java
@@ -0,0 +1,383 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for updateNetworkNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="updateNetworkNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/networkNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="subnetIdMap" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="rollback" type="{http://org.onap.so/networkNotify}networkRollback" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "updateNetworkNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "subnetIdMap",
+ "rollback"
+})
+public class UpdateNetworkNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected UpdateNetworkNotification.SubnetIdMap subnetIdMap;
+ protected NetworkRollback rollback;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the subnetIdMap property.
+ *
+ * @return
+ * possible object is
+ * {@link UpdateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public UpdateNetworkNotification.SubnetIdMap getSubnetIdMap() {
+ return subnetIdMap;
+ }
+
+ /**
+ * Sets the value of the subnetIdMap property.
+ *
+ * @param value
+ * allowed object is
+ * {@link UpdateNetworkNotification.SubnetIdMap }
+ *
+ */
+ public void setSubnetIdMap(UpdateNetworkNotification.SubnetIdMap value) {
+ this.subnetIdMap = value;
+ }
+
+ /**
+ * Gets the value of the rollback property.
+ *
+ * @return
+ * possible object is
+ * {@link NetworkRollback }
+ *
+ */
+ public NetworkRollback getRollback() {
+ return rollback;
+ }
+
+ /**
+ * Sets the value of the rollback property.
+ *
+ * @param value
+ * allowed object is
+ * {@link NetworkRollback }
+ *
+ */
+ public void setRollback(NetworkRollback value) {
+ this.rollback = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class SubnetIdMap {
+
+ protected List<UpdateNetworkNotification.SubnetIdMap.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link UpdateNetworkNotification.SubnetIdMap.Entry }
+ *
+ *
+ */
+ public List<UpdateNetworkNotification.SubnetIdMap.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<UpdateNetworkNotification.SubnetIdMap.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotificationResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotificationResponse.java
new file mode 100644
index 0000000000..e0016d9b8e
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/UpdateNetworkNotificationResponse.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for updateNetworkNotificationResponse complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="updateNetworkNotificationResponse">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "updateNetworkNotificationResponse")
+public class UpdateNetworkNotificationResponse {
+
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/package-info.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/package-info.java
new file mode 100644
index 0000000000..fdd8711170
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/async/client/package-info.java
@@ -0,0 +1,21 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://org.onap.so/networkNotify")
+package org.onap.so.adapters.network.async.client;
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkException.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkException.java
new file mode 100644
index 0000000000..cb4cd8b927
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkException.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * This class simply extends Exception (without addition additional functionality)
+ * to provide an identifier for Network related exceptions on create, delete, query.
+ *
+ *
+ */
+@WebFault (name="NetworkException", faultBean="org.onap.so.adapters.network.exceptions.NetworkExceptionBean", targetNamespace="http://org.onap.so/network")
+public class NetworkException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private NetworkExceptionBean faultInfo;
+
+ public NetworkException (String msg) {
+ super(msg);
+ faultInfo = new NetworkExceptionBean (msg);
+ }
+
+ public NetworkException (Throwable e) {
+ super(e);
+ faultInfo = new NetworkExceptionBean (e.getMessage());
+ }
+
+ public NetworkException (String msg, Throwable e) {
+ super (msg, e);
+ faultInfo = new NetworkExceptionBean (msg);
+ }
+
+ public NetworkException (String msg, MsoExceptionCategory category) {
+ super(msg);
+ faultInfo = new NetworkExceptionBean (msg, category);
+ }
+
+ public NetworkException (String msg, MsoExceptionCategory category, Throwable e) {
+ super (msg, e);
+ faultInfo = new NetworkExceptionBean (msg, category);
+ }
+
+ public NetworkException (MsoException e) {
+ super (e);
+ faultInfo = new NetworkExceptionBean (e.getContextMessage(), e.getCategory());
+ }
+
+ public NetworkExceptionBean getFaultInfo() {
+ return faultInfo;
+ }
+
+ public void setFaultInfo(NetworkExceptionBean faultInfo) {
+ this.faultInfo = faultInfo;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkExceptionBean.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkExceptionBean.java
new file mode 100644
index 0000000000..5256891ffa
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/network/exceptions/NetworkExceptionBean.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.network.exceptions;
+
+
+import java.io.Serializable;
+
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * Jax-WS Fault Bean for Network Exceptions
+ */
+public class NetworkExceptionBean implements Serializable {
+
+ private static final long serialVersionUID = 1655343530371342871L;
+
+ private String message;
+ private MsoExceptionCategory category;
+ private Boolean rolledBack;
+
+ public NetworkExceptionBean () {}
+
+ public NetworkExceptionBean (String message) {
+ this.message = message;
+ }
+
+ public NetworkExceptionBean (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-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java
new file mode 100644
index 0000000000..d29818614d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/CXFConfiguration.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.openstack;
+
+import java.util.Arrays;
+
+import javax.xml.ws.Endpoint;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.spring.SpringBus;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.swagger.Swagger2Feature;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.transport.servlet.CXFServlet;
+import org.onap.so.adapters.network.MsoNetworkAdapterAsyncImpl;
+import org.onap.so.adapters.network.MsoNetworkAdapterImpl;
+import org.onap.so.adapters.network.NetworkAdapterRest;
+import org.onap.so.adapters.tenant.MsoTenantAdapterImpl;
+import org.onap.so.adapters.tenant.TenantAdapterRest;
+import org.onap.so.adapters.vnf.MsoVnfAdapterAsyncImpl;
+import org.onap.so.adapters.vnf.MsoVnfAdapterImpl;
+import org.onap.so.adapters.vnf.MsoVnfCloudifyAdapterImpl;
+import org.onap.so.adapters.vnf.VnfAdapterRest;
+import org.onap.so.adapters.vnf.VnfAdapterRestV2;
+import org.onap.so.adapters.vnf.VolumeAdapterRest;
+import org.onap.so.adapters.vnf.VolumeAdapterRestV2;
+import org.onap.so.client.policy.JettisonStyleMapperProvider;
+import org.onap.so.logger.MsoLogger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+
+@Configuration
+public class CXFConfiguration {
+ private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA, CXFConfiguration.class);
+
+ @Autowired
+ private NetworkAdapterRest networkAdapterRest;
+ @Autowired
+ private TenantAdapterRest tenantAdapterRest;
+ @Autowired
+ private VnfAdapterRest vnfAdapterRest;
+ @Autowired
+ private VnfAdapterRestV2 vnfAdapterRestV2;
+ @Autowired
+ private VolumeAdapterRest volumeAdapterRest;
+ @Autowired
+ private VolumeAdapterRestV2 volumeAdapterRestV2;
+ @Autowired
+ private MsoNetworkAdapterImpl networkAdapterImpl;
+ @Autowired
+ private MsoNetworkAdapterAsyncImpl networkAdapterAsyncImpl;
+ @Autowired
+ private MsoTenantAdapterImpl tenantAdapterImpl;
+ @Autowired
+ private MsoVnfAdapterImpl vnfAdapterImpl;
+ @Autowired
+ private MsoVnfAdapterAsyncImpl vnfAdapterAsyncImpl;
+ @Autowired
+ private MsoVnfCloudifyAdapterImpl vnfCloudifyAdapterImpl;
+ @Autowired
+ private JettisonStyleMapperProvider jettisonStyleObjectMapper;
+
+
+ @Bean(name=Bus.DEFAULT_BUS_ID)
+ public SpringBus springBus() {
+ return new SpringBus();
+ }
+
+ @Bean
+ public ServletRegistrationBean SoapDispatcherServlet() {
+ ServletRegistrationBean servletRegistrationBean =
+ new ServletRegistrationBean(new CXFServlet(), "/services/*");
+ servletRegistrationBean.setName("services");
+ return servletRegistrationBean;
+ }
+
+ /*
+ * network adapter endpoint
+ */
+ @Bean
+ public Endpoint networkAdapterEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), networkAdapterImpl);
+ endpoint.publish("/NetworkAdapter");
+ endpoint.setWsdlLocation("NetworkAdapter.wsdl");
+ return endpoint;
+ }
+
+ @Bean
+ public Endpoint networkAdapterAsyncEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), networkAdapterAsyncImpl);
+ endpoint.publish("/NetworkAdapterAsync");
+ endpoint.setWsdlLocation("NetworkAdapterAsync.wsdl");
+ return endpoint;
+ }
+
+ /*
+ * tenant adapter endpoint
+ */
+ @Bean
+ public Endpoint tenantAdapterEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), tenantAdapterImpl);
+ endpoint.publish("/TenantAdapter");
+ endpoint.setWsdlLocation("TenantAdapter.wsdl");
+ return endpoint;
+ }
+
+ /*
+ * vnfAdapterEndpoint
+ * VnfAsyncAdapterEndpoint
+ * VnfCloudAdapterEndpoint
+ */
+ @Bean
+ public Endpoint vnfAdapterEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), vnfAdapterImpl);
+ endpoint.publish("/VnfAdapter");
+ endpoint.setWsdlLocation("VnfAdapter.wsdl");
+ return endpoint;
+ }
+
+ @Bean
+ public Endpoint VnfAsyncAdapterEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), vnfAdapterAsyncImpl);
+ endpoint.publish("/VnfAsyncAdapter");
+ endpoint.setWsdlLocation("VnfAsyncAdapter.wsdl");
+ return endpoint;
+ }
+
+ @Bean
+ public Endpoint VnfCloudAdapterEndpoint() {
+ EndpointImpl endpoint = new EndpointImpl(springBus(), vnfCloudifyAdapterImpl);
+ endpoint.publish("/VnfCloudifyAdapterImpl");
+ endpoint.setWsdlLocation("VnfCloudifyAdapterImpl.wsdl");
+ return endpoint;
+ }
+
+ @Bean
+ public Server rsServer() {
+ JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean();
+ endpoint.setBus(springBus());
+ endpoint.setServiceBeans(Arrays.<Object>asList(networkAdapterRest,
+ tenantAdapterRest,
+ vnfAdapterRest,
+ vnfAdapterRestV2,
+ volumeAdapterRest,
+ volumeAdapterRestV2));
+ endpoint.setAddress("/rest");
+ endpoint.setFeatures(Arrays.asList(createSwaggerFeature(), new LoggingFeature()));
+ endpoint.setProvider(new JacksonJsonProvider(jettisonStyleObjectMapper.getMapper()));
+ return endpoint.create();
+ }
+
+
+ @Bean
+ public Swagger2Feature createSwaggerFeature() {
+ Swagger2Feature swagger2Feature= new Swagger2Feature();
+ swagger2Feature.setPrettyPrint(true);
+ swagger2Feature.setTitle("SO Orchestration Application");
+ swagger2Feature.setContact("The ONAP SO team");
+ swagger2Feature.setDescription("This project is the SO Orchestration Engine");
+ swagger2Feature.setVersion("1.0.0");
+ swagger2Feature.setResourcePackage("org.onap.so.adapters.network,org.onap.so.adapters.tenant,org.onap.so.adapters.vnf");
+ swagger2Feature.setScan(true);
+ return swagger2Feature;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/MsoOpenstackAdaptersApplication.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/MsoOpenstackAdaptersApplication.java
new file mode 100644
index 0000000000..d67a4b684c
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/MsoOpenstackAdaptersApplication.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.openstack;
+
+import java.util.concurrent.Executor;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+@SpringBootApplication(scanBasePackages = { "org.onap.so" })
+@EnableAsync
+@EnableJpaRepositories({ "org.onap.so.db.catalog.data.repository",
+ "org.onap.so.db.request.data.repository" })
+@EntityScan({ "org.onap.so.db.catalog.beans", "org.onap.so.db.request.beans" })
+public class MsoOpenstackAdaptersApplication {
+
+ @Value("${mso.async.core-pool-size}")
+ private int corePoolSize;
+
+ @Value("${mso.async.max-pool-size}")
+ private int maxPoolSize;
+
+ @Value("${mso.async.queue-capacity}")
+ private int queueCapacity;
+
+ private static final String LOGS_DIR = "logs_dir";
+
+ private static void setLogsDir() {
+ if (System.getProperty(LOGS_DIR) == null) {
+ System.getProperties().setProperty(LOGS_DIR, "./logs/openstack/");
+ }
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(MsoOpenstackAdaptersApplication.class, args);
+ setLogsDir();
+ }
+
+ @Bean
+ public Executor asyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(corePoolSize);
+ executor.setMaxPoolSize(maxPoolSize);
+ executor.setQueueCapacity(queueCapacity);
+ executor.setThreadNamePrefix("OpenstackAdapters-");
+ executor.initialize();
+ return executor;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/WebSecurityConfigImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/WebSecurityConfigImpl.java
new file mode 100644
index 0000000000..6bbdebea52
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/openstack/WebSecurityConfigImpl.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 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.onap.so.adapters.openstack;
+
+import org.onap.so.security.MSOSpringFirewall;
+import org.onap.so.security.WebSecurityConfig;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.firewall.StrictHttpFirewall;
+import org.springframework.util.StringUtils;
+
+@EnableWebSecurity
+public class WebSecurityConfigImpl extends WebSecurityConfig {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable()
+ .authorizeRequests()
+ .antMatchers("/manage/health","/manage/info").permitAll()
+ .antMatchers("/**").hasAnyRole(StringUtils.collectionToDelimitedString(getRoles(),",").toString())
+ .and()
+ .httpBasic();
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ super.configure(web);
+ StrictHttpFirewall firewall = new MSOSpringFirewall();
+ web.httpFirewall(firewall);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapter.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapter.java
new file mode 100644
index 0000000000..ef66d6876c
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapter.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant;
+
+
+import java.util.Map;
+
+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.onap.so.adapters.tenant.exceptions.TenantAlreadyExists;
+import org.onap.so.adapters.tenant.exceptions.TenantException;
+import org.onap.so.adapters.tenantrest.TenantRollback;
+import org.onap.so.entity.MsoRequest;
+
+@WebService (name="TenantAdapter", targetNamespace="http://org.onap.so/tenant")
+public interface MsoTenantAdapter
+{
+ /**
+ * This is the "Create Tenant" Web Service Endpoint definition.
+ */
+ @WebMethod
+ public void createTenant (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantName") @XmlElement(required=true) String tenantName,
+ @WebParam(name="metadata") Map<String,String> metadata,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="tenantId", mode=Mode.OUT) Holder<String> tenantId,
+ @WebParam(name="rollback", mode=Mode.OUT) Holder<TenantRollback> rollback )
+ throws TenantException, TenantAlreadyExists;
+
+ @WebMethod
+ public void queryTenant (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantNameOrId") @XmlElement(required=true) String tenantNameOrId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="tenantId", mode=Mode.OUT) Holder<String> tenantId,
+ @WebParam(name="tenantName", mode=Mode.OUT) Holder<String> tenantName,
+ @WebParam(name="metadata", mode=Mode.OUT) Holder<Map<String,String>> metadata )
+ throws TenantException;
+
+ @WebMethod
+ public void deleteTenant (@WebParam(name="cloudSiteId") @XmlElement(required=true) String cloudSiteId,
+ @WebParam(name="tenantId") @XmlElement(required=true) String tenantId,
+ @WebParam(name="request") MsoRequest msoRequest,
+ @WebParam(name="tenantDeleted", mode=Mode.OUT) Holder<Boolean> tenantDeleted)
+ throws TenantException;
+
+ @WebMethod
+ public void rollbackTenant (@WebParam(name="rollback") @XmlElement(required=true) TenantRollback rollback)
+ throws TenantException;
+
+ @WebMethod
+ public void healthCheck ();
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapterImpl.java
new file mode 100644
index 0000000000..f58382f53c
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/MsoTenantAdapterImpl.java
@@ -0,0 +1,295 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant;
+
+
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+import javax.xml.ws.WebServiceContext;
+
+import org.onap.so.adapters.tenant.exceptions.TenantAlreadyExists;
+import org.onap.so.adapters.tenant.exceptions.TenantException;
+import org.onap.so.adapters.tenantrest.TenantRollback;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.MsoTenant;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.utils.MsoTenantUtils;
+import org.onap.so.openstack.utils.MsoTenantUtilsFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@WebService(serviceName = "TenantAdapter", endpointInterface = "org.onap.so.adapters.tenant.MsoTenantAdapter", targetNamespace = "http://org.onap.so/tenant")
+@Component
+public class MsoTenantAdapterImpl implements MsoTenantAdapter {
+ public static final String CREATE_TENANT = "CreateTenant";
+ public static final String OPENSTACK = "OpenStack";
+ public static final String QUERY_TENANT = "QueryTenant";
+ public static final String DELETE_TENANT = "DeleteTenant";
+ public static final String ROLLBACK_TENANT = "RollbackTenant";
+
+ @Resource
+ private WebServiceContext wsContext;
+
+ @Autowired
+ private MsoTenantUtilsFactory tFactory;
+ private static MsoLogger logger = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoTenantAdapterImpl.class);
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheck () {
+ logger.debug ("Health check call in Tenant Adapter");
+ }
+
+ /**
+ * This is the "Create Tenant" web service implementation. It will create
+ * a new Tenant in the specified cloud. If the tenant already exists, this
+ * can be considered a success or failure, depending on the value of the
+ * 'failIfExists' parameter.
+ *
+ * The method returns the tenantId (the Openstack ID), and a TenantRollback
+ * object. This last object can be passed as-is to the rollbackTenant method
+ * to undo what (if anything) was created. This is useful if a Tenant is
+ * successfully created but the orchestrator fails on a subsequent operation.
+ */
+ @Override
+ public void createTenant (String cloudSiteId,
+ String tenantName,
+ Map <String, String> metadata,
+ Boolean failIfExists,
+ Boolean backout,
+ MsoRequest msoRequest,
+ Holder <String> tenantId,
+ Holder <TenantRollback> rollback) throws TenantException, TenantAlreadyExists {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName (CREATE_TENANT);
+
+ logger.debug ("Call to MSO createTenant adapter. Creating Tenant: " + tenantName
+ + "in "
+ + cloudSiteId);
+
+ // Will capture total time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Start building up rollback object
+ TenantRollback tenantRollback = new TenantRollback ();
+ tenantRollback.setCloudId (cloudSiteId);
+ tenantRollback.setMsoRequest (msoRequest);
+
+ MsoTenantUtils tUtils;
+ try {
+ tUtils = tFactory.getTenantUtils (cloudSiteId);
+ } catch (MsoCloudSiteNotFound me) {
+ logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "no implementation found for " + cloudSiteId, me);
+ throw new TenantException (me);
+ }
+
+ MsoTenant newTenant = null;
+ String newTenantId;
+ long queryTenantStartTime = System.currentTimeMillis ();
+ try {
+ newTenant = tUtils.queryTenantByName (tenantName, cloudSiteId);
+ logger.recordMetricEvent (queryTenantStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, QUERY_TENANT, null);
+ } catch (MsoException me) {
+ logger.recordMetricEvent (queryTenantStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with Open Stack", OPENSTACK, QUERY_TENANT, null);
+ String error = "Create Tenant " + tenantName + ": " + me;
+ logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "Exception while communicate with Open Stack", me);
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new TenantException (me);
+ }
+ if (newTenant == null) {
+ if (backout == null)
+ backout = true;
+ long createTenantStartTime = System.currentTimeMillis ();
+ try {
+ newTenantId = tUtils.createTenant (tenantName, cloudSiteId, metadata, backout.booleanValue ());
+ logger.recordMetricEvent (createTenantStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, CREATE_TENANT, null);
+ } catch (MsoException me) {
+ logger.recordMetricEvent (createTenantStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with Open Stack", OPENSTACK, CREATE_TENANT, null);
+ String error = "Create Tenant " + tenantName + ": " + me;
+ logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "Exception while communicate with Open Stack", me);
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new TenantException (me);
+ }
+ tenantRollback.setTenantId (newTenantId);
+ tenantRollback.setTenantCreated (true);
+ logger.debug ("Tenant " + tenantName + " successfully created with ID " + newTenantId);
+ } else {
+ if (failIfExists != null && failIfExists) {
+ String error = CREATE_TENANT + ": Tenant " + tenantName + " already exists in " + cloudSiteId;
+ logger.error (MessageEnum.RA_TENANT_ALREADY_EXIST, tenantName, cloudSiteId, OPENSTACK, "", MsoLogger.ErrorCode.DataError, CREATE_TENANT + ", Tenant already exists");
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
+ throw new TenantAlreadyExists (tenantName, cloudSiteId, newTenant.getTenantId ());
+ }
+
+ newTenantId = newTenant.getTenantId ();
+ tenantRollback.setTenantCreated (false);
+ logger.debug ("Tenant " + tenantName + " already exists with ID " + newTenantId);
+ }
+
+
+ tenantId.value = newTenantId;
+ rollback.value = tenantRollback;
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create tenant");
+ return;
+ }
+
+ @Override
+ public void queryTenant (String cloudSiteId,
+ String tenantNameOrId,
+ MsoRequest msoRequest,
+ Holder <String> tenantId,
+ Holder <String> tenantName,
+ Holder <Map <String, String>> metadata) throws TenantException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName (QUERY_TENANT);
+ logger.debug ("Querying Tenant " + tenantNameOrId + " in " + cloudSiteId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoTenantUtils tUtils;
+ try {
+ tUtils = tFactory.getTenantUtils (cloudSiteId);
+ } catch (MsoCloudSiteNotFound me) {
+ logger.error (MessageEnum.RA_CREATE_TENANT_ERR, me.getMessage(), OPENSTACK, "createTenant", MsoLogger.ErrorCode.DataError, "no implementation found for " + cloudSiteId, me);
+ throw new TenantException (me);
+ }
+
+ MsoTenant qTenant = null;
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ qTenant = tUtils.queryTenant (tenantNameOrId, cloudSiteId);
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", OPENSTACK, QUERY_TENANT, null);
+ if (qTenant == null) {
+ // Not found by ID, Try by name.
+ qTenant = tUtils.queryTenantByName (tenantNameOrId, cloudSiteId);
+ }
+
+ if (qTenant == null) {
+ logger.debug ("QueryTenant: Tenant " + tenantNameOrId + " not found");
+ tenantId.value = null;
+ tenantName.value = null;
+ metadata.value = null;
+ } else {
+ logger.debug ("QueryTenant: Tenant " + tenantNameOrId + " found with ID " + qTenant.getTenantId ());
+ tenantId.value = qTenant.getTenantId ();
+ tenantName.value = qTenant.getTenantName ();
+ metadata.value = qTenant.getMetadata ();
+ }
+ } catch (MsoException me) {
+ String error = "Query Tenant " + tenantNameOrId + ": " + me;
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, QUERY_TENANT, null);
+ logger.error (MessageEnum.RA_GENERAL_EXCEPTION, me.getMessage(), OPENSTACK, "", MsoLogger.ErrorCode.DataError, "Exception in queryTenant", me);
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new TenantException (me);
+ }
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query tenant");
+ return;
+ }
+
+ @Override
+ public void deleteTenant (String cloudSiteId,
+ String tenantId,
+ MsoRequest msoRequest,
+ Holder <Boolean> tenantDeleted) throws TenantException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName (DELETE_TENANT);
+
+ logger.debug ("Deleting Tenant " + tenantId + " in " + cloudSiteId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Delete the Tenant.
+ long subStartTime = System.currentTimeMillis ();
+ try {
+
+ MsoTenantUtils tUtils = tFactory.getTenantUtils (cloudSiteId);
+ boolean deleted = tUtils.deleteTenant (tenantId, cloudSiteId);
+ tenantDeleted.value = deleted;
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully communicate with Open Stack", OPENSTACK, DELETE_TENANT, null);
+ } catch (MsoException me) {
+ String error = "Delete Tenant " + tenantId + ": " + me;
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, DELETE_TENANT, null);
+ logger.error (MessageEnum.RA_DELETE_TEMAMT_ERR, me.getMessage(), OPENSTACK, "", MsoLogger.ErrorCode.DataError, "Exception - DeleteTenant", me);
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new TenantException (me);
+ }
+
+ // On success, nothing is returned.
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete tenant");
+ 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.
+ *
+ * The rollback includes removing the VNF and deleting the tenant if the
+ * tenant did not exist prior to the VNF creation.
+ */
+ @Override
+ public void rollbackTenant (TenantRollback rollback) throws TenantException {
+ long startTime = System.currentTimeMillis ();
+ MsoLogger.setServiceName (ROLLBACK_TENANT);
+ // rollback may be null (e.g. if stack already existed when Create was called)
+ if (rollback == null) {
+ logger.warn (MessageEnum.RA_ROLLBACK_NULL, OPENSTACK, "rollbackTenant", MsoLogger.ErrorCode.DataError, "rollbackTenant, rollback is null");
+ return;
+ }
+
+ // Get the elements of the VnfRollback object for easier access
+ String cloudSiteId = rollback.getCloudId ();
+ String tenantId = rollback.getTenantId ();
+
+ MsoLogger.setLogContext (rollback.getMsoRequest ());
+ logger.debug ("Rolling Back Tenant " + rollback.getTenantId () + " in " + cloudSiteId);
+
+ long subStartTime = System.currentTimeMillis ();
+ if (rollback.getTenantCreated ()) {
+ try {
+
+ MsoTenantUtils tUtils = tFactory.getTenantUtils (cloudSiteId);
+ tUtils.deleteTenant (tenantId, cloudSiteId);
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully communicate with Open Stack", OPENSTACK, ROLLBACK_TENANT, null);
+ } catch (MsoException me) {
+ me.addContext (ROLLBACK_TENANT);
+ // Failed to delete the tenant.
+ String error = "Rollback Tenant " + tenantId + ": " + me;
+ logger.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, OPENSTACK, ROLLBACK_TENANT, null);
+ logger.error (MessageEnum.RA_ROLLBACK_TENANT_ERR, me.getMessage(), OPENSTACK, "rollbackTenant", MsoLogger.ErrorCode.DataError, "Exception - rollbackTenant", me);
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new TenantException (me);
+ }
+ }
+ logger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully roll back tenant");
+ return;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/TenantAdapterRest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/TenantAdapterRest.java
new file mode 100644
index 0000000000..2bba3f559e
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/TenantAdapterRest.java
@@ -0,0 +1,345 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant;
+
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+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.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.ws.Holder;
+
+import org.onap.so.adapters.tenant.exceptions.TenantAlreadyExists;
+import org.onap.so.adapters.tenant.exceptions.TenantException;
+import org.onap.so.adapters.tenantrest.CreateTenantError;
+import org.onap.so.adapters.tenantrest.CreateTenantRequest;
+import org.onap.so.adapters.tenantrest.CreateTenantResponse;
+import org.onap.so.adapters.tenantrest.DeleteTenantError;
+import org.onap.so.adapters.tenantrest.DeleteTenantRequest;
+import org.onap.so.adapters.tenantrest.DeleteTenantResponse;
+import org.onap.so.adapters.tenantrest.QueryTenantError;
+import org.onap.so.adapters.tenantrest.QueryTenantResponse;
+import org.onap.so.adapters.tenantrest.RollbackTenantError;
+import org.onap.so.adapters.tenantrest.RollbackTenantRequest;
+import org.onap.so.adapters.tenantrest.RollbackTenantResponse;
+import org.onap.so.adapters.tenantrest.TenantRollback;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.MsoTenant;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * This class services calls to the REST interface for Tenants (http://host:port/vnfs/rest/v1/tenants)
+ * Both XML and JSON can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default.
+ */
+@Path("/v1/tenants")
+@Api(value = "/v1/tenants", description = "root of tenant adapters restful web service")
+@Component
+public class TenantAdapterRest {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, TenantAdapterRest.class);
+
+ //RAA? No logging in wrappers
+ @Autowired
+ private MsoTenantAdapterImpl tenantImpl;
+
+
+
+ /*
+ URL:
+ EP: http://host:8080/tenants/rest
+ Resource: v1/tenants
+ REQ - metadata?
+ {
+ "cloudSiteId": "DAN",
+ "tenantName": "RAA_1",
+ "failIfExists": true,
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }}
+ RESP-
+ {
+ "cloudSiteId": "DAN",
+ "tenantId": "128e10b9996d43a7874f19bbc4eb6749",
+ "tenantCreated": true,
+ "tenantRollback": {
+ "tenantId": "128e10b9996d43a7874f19bbc4eb6749",
+ "cloudId": "DAN", // RAA? cloudId instead of cloudSiteId
+ "tenantCreated": true,
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }
+ }
+ }
+ */
+ @POST
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "CreateTenant",
+ response = Response.class,
+ notes = "Creates a new tenant, CreateTenantRequest data is required")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "tenant has been successfully created"),
+ @ApiResponse(code = 500, message = "create tenant failed") })
+ public Response createTenant(
+ @ApiParam(value = "details of tenant being created", required = true)
+ CreateTenantRequest req) {
+ LOGGER.debug("createTenant enter: " + req.toJsonString());
+
+ String newTenantId = null;
+ TenantRollback tenantRollback = new TenantRollback ();
+
+ try {
+ Holder<String> htenant = new Holder<>();
+ Holder<TenantRollback> hrollback = new Holder<>();
+ MsoTenantAdapter impl = tenantImpl;
+ impl.createTenant(
+ req.getCloudSiteId(),
+ req.getTenantName(),
+ req.getMetadata(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getMsoRequest(),
+ htenant,
+ hrollback);
+ newTenantId = htenant.value;
+ tenantRollback = hrollback.value;
+// TenantAdapterCore TAImpl = new TenantAdapterCore();
+// newTenantId = TAImpl.createTenant (req.getCloudSiteId(),
+// req.getTenantName(),
+// req.getFailIfExists(),
+// req.getBackout(),
+// req.getMetadata(),
+// req.getMsoRequest(),
+// tenantRollback);
+ }
+ catch (TenantAlreadyExists tae) {
+ LOGGER.debug("Exception :",tae);
+ CreateTenantError exc = new CreateTenantError(tae.getMessage(), tae.getFaultInfo().getCategory(), Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).entity(exc).build();
+ }
+ catch (TenantException te) {
+ LOGGER.debug("Exception :",te);
+ CreateTenantError exc = new CreateTenantError(te.getFaultInfo().getMessage(), te.getFaultInfo().getCategory(), Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ catch (Exception e) {
+ LOGGER.debug("Exception :",e);
+ CreateTenantError exc = new CreateTenantError(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+
+ CreateTenantResponse resp = new CreateTenantResponse (req.getCloudSiteId(), newTenantId, tenantRollback.getTenantCreated(), tenantRollback);
+ return Response.status(HttpServletResponse.SC_OK).entity(resp).build();
+ }
+
+ /*
+ URL:
+ http://host:8080/tenants/rest
+ Resource: v1/tenant/tennatId
+ REQ:
+ {"cloudSiteId": "DAN",
+ "tenantId": "ca84cd3d3df44272845da554656b3ace",
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }
+ }
+ RESP:
+ {"tenantDeleted": true}
+ */
+ @DELETE
+ @Path("{tenantId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "DeleteTenant",
+ response = Response.class,
+ notes = "Delete an existing tenant")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "tenant has been successfully deleted"),
+ @ApiResponse(code = 500, message = "delete tenant failed") })
+ public Response deleteTenant(
+ @ApiParam(value = "tenantId of tenant being deleted", required = true)
+ @PathParam("tenantId") String tenantId,
+ @ApiParam(value = "DeleteTenantRequest object containing additional information of tenant being deleted", required = false)
+ DeleteTenantRequest req)
+ {
+ boolean tenantDeleted = false;
+
+ try {
+ Holder<Boolean> deleted = new Holder<>();
+ MsoTenantAdapter impl = tenantImpl;
+ impl.deleteTenant(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getMsoRequest(),
+ deleted);
+ tenantDeleted = deleted.value;
+ }
+ catch (TenantException te) {
+ LOGGER.debug("Exception :",te);
+ DeleteTenantError exc = new DeleteTenantError(te.getFaultInfo().getMessage(), te.getFaultInfo().getCategory(), Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ catch (Exception e) {
+ LOGGER.debug("Exception :",e);
+ DeleteTenantError exc = new DeleteTenantError(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ DeleteTenantResponse resp = new DeleteTenantResponse();
+ resp.setTenantDeleted(tenantDeleted);
+ return Response.status(HttpServletResponse.SC_OK).entity(resp).build();
+ }
+
+ /*
+ URL
+ EP://http://host:8080/tenants/rest
+ Resource: /v1/tenants
+ Params:?tenantNameOrId=RAA_1&cloudSiteId=DAN
+ RESP
+ {
+ "tenantId": "214b428a1f554c02935e66330f6a5409",
+ "tenantName": "RAA_1",
+ "metadata": {}
+ }
+ */
+ @GET
+ @Path("{tenantId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "QueryTenant",
+ response = Response.class,
+ notes = "Query an existing tenant")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "tenant has been successfully queried"),
+ @ApiResponse(code = 500, message = "query tenant failed") })
+ public Response queryTenant(
+ @ApiParam(value = "tenantId", required = true)
+ @PathParam("tenantId") String tenantId,
+// @QueryParam("tenantNameOrId") String tenantNameOrId, //RAA? diff from doc
+ @ApiParam(value = "cloudSiteId", required = true)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "msoRequest.requestId", required = true)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = true)
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId)
+ {
+ MsoTenant tenant = null;
+ try {
+ Holder<String> htenant = new Holder<>();
+ Holder<String> tenantName = new Holder<>();
+ Holder<Map<String,String>> metadata = new Holder<>();
+ MsoTenantAdapter impl = tenantImpl;
+ impl.queryTenant(
+ cloudSiteId,
+ tenantId,
+ null,
+ htenant,
+ tenantName,
+ metadata
+ );
+ tenant = new MsoTenant(htenant.value, tenantName.value, metadata.value);
+// TenantAdapterCore TAImpl = new TenantAdapterCore();
+// MsoRequest msoReq = new MsoRequest();
+// tenant = TAImpl.queryTenant (cloudSiteId, tenantId, msoReq);
+ }
+ catch (TenantException te) {
+ LOGGER.debug("Exception :",te);
+ QueryTenantError exc = new QueryTenantError(te.getFaultInfo().getMessage(), te.getFaultInfo().getCategory());
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ catch (Exception e) {
+ LOGGER.debug("Exception :",e);
+ QueryTenantError exc = new QueryTenantError(e.getMessage(), MsoExceptionCategory.INTERNAL);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ QueryTenantResponse resp = new QueryTenantResponse(tenant.getTenantId(), tenant.getTenantName(), tenant.getMetadata());
+ return Response.status(HttpServletResponse.SC_OK).entity(resp).build();
+ }
+
+ /*
+ URL
+ EP: //http://host:8080/tenants/rest
+ Resource: /v1/tenants/rollback
+ REQ
+ {"cloudSiteId": "DAN",
+ "tenantId": "f58abb05041d4ff384d4d22d1ccd2a6c",
+ "msoRequest": {
+ "requestId": "ra1",
+ "serviceInstanceId": "sa1"
+ }
+ }
+ RESP:
+ {"tenantDeleted": true}
+ */
+ @DELETE
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "RollbackTenant",
+ response = Response.class,
+ notes = "Rollback an existing tenant")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "tenant has been successfully rolledback"),
+ @ApiResponse(code = 500, message = "rollback tenant failed") })
+ public Response rollbackTenant(
+ @ApiParam(value = "rollback, command action", required = true)
+ @QueryParam("rollback") String action, // WTF?
+ @ApiParam(value = "RollbackTenantRequest", required = true)
+ RollbackTenantRequest req)
+ {
+ try {
+ MsoTenantAdapter impl = tenantImpl;
+ impl.rollbackTenant(req.getTenantRollback());
+ }
+ catch (TenantException te) {
+ LOGGER.debug("Exception :",te);
+ RollbackTenantError exc = new RollbackTenantError(te.getFaultInfo().getMessage(), te.getFaultInfo().getCategory(), Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+ catch (Exception e) {
+ LOGGER.debug("Exception :",e);
+ RollbackTenantError exc = new RollbackTenantError(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE);
+ return Response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).entity(exc).build();
+ }
+
+ RollbackTenantResponse resp = new RollbackTenantResponse ();
+ resp.setTenantRolledback(req != null);
+ return Response.status(HttpServletResponse.SC_OK).entity(resp).build();
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantAlreadyExists.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantAlreadyExists.java
new file mode 100644
index 0000000000..5b8e7c7294
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantAlreadyExists.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+
+
+/**
+ * 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="TenantAlreadyExists", faultBean="org.onap.so.adapters.tenant.exceptions.TenantExceptionBean", targetNamespace="http://org.onap.so/tenant")
+public class TenantAlreadyExists extends TenantException {
+
+ private static final long serialVersionUID = 1L;
+
+ public TenantAlreadyExists (String name, String cloudId, String tenantId) {
+ super("Tenant " + name + " already exists in " + cloudId + " with ID " + tenantId, MsoExceptionCategory.USERDATA);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantException.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantException.java
new file mode 100644
index 0000000000..b8074ef7fc
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantException.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * This class simply extends Exception (without addition additional functionality)
+ * to provide an identifier for Tenant related exceptions on create, delete, query.
+ *
+ *
+ */
+@WebFault (name="TenantException", faultBean="org.onap.so.adapters.tenant.exceptions.TenantExceptionBean", targetNamespace="http://org.onap.so/tenant")
+public class TenantException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private TenantExceptionBean faultInfo;
+
+ public TenantException (String msg) {
+ super(msg);
+ faultInfo = new TenantExceptionBean (msg);
+ }
+
+ public TenantException (String msg, Throwable e) {
+ super (msg, e);
+ faultInfo = new TenantExceptionBean (msg);
+ }
+
+ public TenantException (String msg, MsoExceptionCategory category) {
+ super(msg);
+ faultInfo = new TenantExceptionBean (msg, category);
+ }
+
+ public TenantException (String msg, MsoExceptionCategory category, Throwable e) {
+ super (msg, e);
+ faultInfo = new TenantExceptionBean (msg, category);
+ }
+
+ public TenantException (MsoException e) {
+ super (e);
+ faultInfo = new TenantExceptionBean (e.getContextMessage(), e.getCategory());
+ }
+
+ public TenantExceptionBean getFaultInfo() {
+ return faultInfo;
+ }
+
+ public void setFaultInfo(TenantExceptionBean faultInfo) {
+ this.faultInfo = faultInfo;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantExceptionBean.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantExceptionBean.java
new file mode 100644
index 0000000000..1dada60e93
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tenant/exceptions/TenantExceptionBean.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.tenant.exceptions;
+
+
+import java.io.Serializable;
+
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * Jax-WS Fault Bean for Network Exceptions
+ */
+public class TenantExceptionBean implements Serializable {
+
+ private static final long serialVersionUID = -9062290006520066109L;
+
+ private String message;
+ private MsoExceptionCategory category;
+
+ public TenantExceptionBean () {}
+
+ public TenantExceptionBean (String message) {
+ this.message = message;
+ }
+
+ public TenantExceptionBean (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;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/GenericValetResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/GenericValetResponse.java
new file mode 100644
index 0000000000..344895f8f3
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/GenericValetResponse.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/*
+ * The purpose of this class is to encapsulate the possible responses from Valet in to one generic class
+ * that the vnf adapter can more easily utilize. This will ensure we get an object back. Any status
+ * code other than 200 will be treated as a failure. We may still get a 200 back - but the
+ * ValetStatus.status is "failed" - which will also be treated as a failure. The T class is
+ * expected to be one of the Valet*Response pojos.
+ */
+public class GenericValetResponse<T> {
+ private int statusCode;
+ private String errorMessage;
+ private T returnObject;
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append("statusCode", statusCode).append("errorMessage", errorMessage)
+ .append("returnObject", returnObject).toString();
+ }
+ public GenericValetResponse(int statusCode, String errorMessage, T obj) {
+ super();
+ this.statusCode = statusCode;
+ this.errorMessage = errorMessage;
+ this.returnObject = obj;
+ }
+ public GenericValetResponse() {
+ this(-1, "not set", null);
+ }
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+ public String getErrorMessage() {
+ return this.errorMessage;
+ }
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+ public int getStatusCode() {
+ return this.statusCode;
+ }
+ public void setReturnObject(T obj) {
+ this.returnObject = obj;
+ }
+ public T getReturnObject() {
+ return this.returnObject;
+ }
+
+}
+
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/ValetClient.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/ValetClient.java
new file mode 100644
index 0000000000..f4bda4aaa0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/ValetClient.java
@@ -0,0 +1,326 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet;
+
+import org.onap.so.adapters.valet.beans.HeatRequest;
+import org.onap.so.adapters.valet.beans.ValetConfirmRequest;
+import org.onap.so.adapters.valet.beans.ValetConfirmResponse;
+import org.onap.so.adapters.valet.beans.ValetCreateRequest;
+import org.onap.so.adapters.valet.beans.ValetCreateResponse;
+import org.onap.so.adapters.valet.beans.ValetDeleteRequest;
+import org.onap.so.adapters.valet.beans.ValetDeleteResponse;
+import org.onap.so.adapters.valet.beans.ValetRollbackRequest;
+import org.onap.so.adapters.valet.beans.ValetRollbackResponse;
+import org.onap.so.adapters.valet.beans.ValetUpdateRequest;
+import org.onap.so.adapters.valet.beans.ValetUpdateResponse;
+
+import java.net.URI;
+
+import javax.annotation.PostConstruct;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.onap.so.adapters.valet.GenericValetResponse;
+
+import org.onap.so.logger.MsoLogger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Component
+public class ValetClient {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA, ValetClient.class);
+
+ @Autowired
+ private Environment environment;
+
+ private static final String VALET_BASE_URL = "org.onap.so.adapters.valet.base_url";
+ private static final String VALET_BASE_PATH = "org.onap.so.adapters.valet.base_path";
+ private static final String VALET_AUTH = "org.onap.so.adapters.valet.basic_auth";
+ private static final String REQ_ID_HEADER_NAME = "X-RequestID";
+ protected static final String NO_STATUS_RETURNED = "no status returned from Valet";
+
+ private static final String DEFAULT_BASE_URL = "http://localhost:8080/";
+ private static final String DEFAULT_BASE_PATH = "api/valet/placement/v1";
+ private static final String DEFAULT_AUTH_STRING = "";
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ protected String baseUrl;
+ protected String basePath;
+ protected String authString;
+
+ /*
+ * Setup the properties needed from properties file. Each will fall to a default
+ */
+ @PostConstruct
+ private void setupParams() {
+ try {
+ this.baseUrl = this.environment.getProperty(ValetClient.VALET_BASE_URL, ValetClient.DEFAULT_BASE_URL);
+ this.basePath = this.environment.getProperty(ValetClient.VALET_BASE_PATH, ValetClient.DEFAULT_BASE_PATH);
+ this.authString = this.environment.getProperty(ValetClient.VALET_AUTH, ValetClient.DEFAULT_AUTH_STRING);
+ } catch (Exception e) {
+ LOGGER.debug("Error retrieving valet properties. " + e.getMessage());
+ }
+ }
+
+ /*
+ * This method will be invoked to send a Create request to Valet.
+ */
+ public GenericValetResponse<ValetCreateResponse> callValetCreateRequest(String requestId, String regionId, String tenantId, String serviceInstanceId,
+ String vnfId, String vnfName, String vfModuleId, String vfModuleName, String keystoneUrl, HeatRequest heatRequest) throws Exception {
+ ResponseEntity<ValetCreateResponse> response = null;
+ GenericValetResponse<ValetCreateResponse> gvr = null;
+
+ try {
+ UriBuilder builder = UriBuilder.fromPath(baseUrl).path(basePath).queryParam("requestId", requestId);
+ URI uri = builder.build();
+
+ ValetCreateRequest vcr = this.createValetCreateRequest(regionId, tenantId, serviceInstanceId, vnfId, vnfName, vfModuleId, vfModuleName, keystoneUrl, heatRequest);
+ RestTemplate restTemplate = new RestTemplate();
+ String body = mapper.writeValueAsString(vcr);
+ HttpHeaders headers = generateHeaders(requestId);
+ HttpEntity<String> entity = new HttpEntity<>(body, headers);
+ LOGGER.debug("valet create req: " + uri.toString() + ", headers=" + headers.toString() + ", body=" + body.toString());
+
+ response = restTemplate.exchange(uri, HttpMethod.POST, entity, ValetCreateResponse.class);
+ gvr = this.getGVRFromResponse(response);
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred in callValetCreateRequest", e);
+ throw e;
+ }
+ return gvr;
+ }
+
+ /*
+ * This method will be invoked to send an Update request to Valet.
+ */
+ public GenericValetResponse<ValetUpdateResponse> callValetUpdateRequest(String requestId, String regionId, String tenantId, String serviceInstanceId,
+ String vnfId, String vnfName, String vfModuleId, String vfModuleName, String keystoneUrl, HeatRequest heatRequest) throws Exception {
+ ResponseEntity<ValetUpdateResponse> response = null;
+ GenericValetResponse<ValetUpdateResponse> gvr = null;
+
+ try {
+ UriBuilder builder = UriBuilder.fromPath(baseUrl).path(basePath).queryParam("requestId", requestId);
+ URI uri = builder.build();
+
+ ValetUpdateRequest vur = this.createValetUpdateRequest(regionId, tenantId, serviceInstanceId, vnfId, vnfName, vfModuleId, vfModuleName, keystoneUrl, heatRequest);
+ RestTemplate restTemplate = new RestTemplate();
+ String body = mapper.writeValueAsString(vur);
+ HttpHeaders headers = generateHeaders(requestId);
+ HttpEntity<String> entity = new HttpEntity<>(body, headers);
+ LOGGER.debug("valet update req: " + uri.toString() + ", headers=" + headers.toString() + ", body=" + body.toString());
+
+ response = restTemplate.exchange(uri, HttpMethod.PUT, entity, ValetUpdateResponse.class);
+ gvr = this.getGVRFromResponse(response);
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred in callValetUpdateRequest", e);
+ throw e;
+ }
+ return gvr;
+ }
+
+ /*
+ * This method will be invoked to send a Delete request to Valet.
+ */
+ public GenericValetResponse<ValetDeleteResponse> callValetDeleteRequest(String requestId, String regionId, String tenantId, String vfModuleId, String vfModuleName) throws Exception {
+ ResponseEntity<ValetDeleteResponse> response = null;
+ GenericValetResponse<ValetDeleteResponse> gvr = null;
+
+ try {
+ UriBuilder builder = UriBuilder.fromPath(baseUrl).path(basePath).queryParam("requestId", requestId);
+ URI uri = builder.build();
+
+ ValetDeleteRequest vdr = this.createValetDeleteRequest(regionId, tenantId, vfModuleId, vfModuleName);
+ RestTemplate restTemplate = new RestTemplate();
+ String body = mapper.writeValueAsString(vdr);
+ HttpHeaders headers = generateHeaders(requestId);
+ HttpEntity<String> entity = new HttpEntity<>(body, headers);
+ LOGGER.debug("valet delete req: " + uri.toString() + ", headers=" + headers.toString() + ", body=" + body.toString());
+
+ response = restTemplate.exchange(uri, HttpMethod.DELETE, entity, ValetDeleteResponse.class);
+ gvr = this.getGVRFromResponse(response);
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred in callValetDeleteRequest", e);
+ throw e;
+ }
+ return gvr;
+ }
+
+ /*
+ * This method is called to invoke a Confirm request to Valet.
+ */
+ public GenericValetResponse<ValetConfirmResponse> callValetConfirmRequest(String requestId, String stackId) throws Exception {
+ ResponseEntity<ValetConfirmResponse> response = null;
+ GenericValetResponse<ValetConfirmResponse> gvr = null;
+
+ try {
+ UriBuilder builder = UriBuilder.fromPath(this.baseUrl).path(this.basePath).path("{requestId}/confirm/");
+ URI uri = builder.build(requestId);
+
+ ValetConfirmRequest vcr = this.createValetConfirmRequest(stackId);
+ RestTemplate restTemplate = new RestTemplate();
+ String body = mapper.writeValueAsString(vcr);
+ HttpHeaders headers = generateHeaders(requestId);
+ HttpEntity<String> entity = new HttpEntity<>(body, headers);
+ LOGGER.debug("valet confirm req: " + uri.toString() + ", headers=" + headers.toString() + ", body=" + body);
+
+ response = restTemplate.exchange(uri, HttpMethod.PUT, entity, ValetConfirmResponse.class);
+ gvr = this.getGVRFromResponse(response);
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred in callValetConfirmRequest", e);
+ throw e;
+ }
+ return gvr;
+ }
+
+ /*
+ * This method is called to invoke a Rollback request to Valet.
+ */
+ public GenericValetResponse<ValetRollbackResponse> callValetRollbackRequest(String requestId, String stackId, Boolean suppressRollback, String errorMessage) throws Exception {
+ ResponseEntity<ValetRollbackResponse> response = null;
+ GenericValetResponse<ValetRollbackResponse> gvr = null;
+
+ try {
+ UriBuilder builder = UriBuilder.fromPath(this.baseUrl).path(this.basePath).path("{requestId}/rollback/");
+ URI uri = builder.build(requestId);
+
+ ValetRollbackRequest vrr = this.createValetRollbackRequest(stackId, suppressRollback, errorMessage);
+ RestTemplate restTemplate = new RestTemplate();
+ String body = mapper.writeValueAsString(vrr);
+ HttpHeaders headers = generateHeaders(requestId);
+ HttpEntity<String> entity = new HttpEntity<>(body, headers);
+ LOGGER.debug("valet rollback req: " + uri.toString() + ", headers=" + headers.toString() + ", body=" + body.toString());
+
+ response = restTemplate.exchange(uri, HttpMethod.PUT, entity, ValetRollbackResponse.class);
+ gvr = this.getGVRFromResponse(response);
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred in callValetRollbackRequest", e);
+ throw e;
+ }
+ return gvr;
+ }
+
+ /*
+ * This method is to construct the ValetCreateRequest pojo
+ */
+ private ValetCreateRequest createValetCreateRequest(String regionId, String tenantId, String serviceInstanceId,
+ String vnfId, String vnfName, String vfModuleId, String vfModuleName, String keystoneUrl, HeatRequest heatRequest) {
+ ValetCreateRequest vcr = new ValetCreateRequest();
+ vcr.setHeatRequest(heatRequest);
+ vcr.setKeystoneUrl(keystoneUrl);
+ vcr.setRegionId(regionId);
+ vcr.setServiceInstanceId(serviceInstanceId);
+ vcr.setTenantId(tenantId);
+ vcr.setVfModuleId(vfModuleId);
+ vcr.setVfModuleName(vfModuleName);
+ vcr.setVnfId(vnfId);
+ vcr.setVnfName(vnfName);
+
+ return vcr;
+ }
+
+ /*
+ * This method is to construct the ValetUpdateRequest pojo
+ */
+ private ValetUpdateRequest createValetUpdateRequest(String regionId, String tenantId, String serviceInstanceId,
+ String vnfId, String vnfName, String vfModuleId, String vfModuleName, String keystoneUrl, HeatRequest heatRequest) {
+ ValetUpdateRequest vur = new ValetUpdateRequest();
+ vur.setHeatRequest(heatRequest);
+ vur.setKeystoneUrl(keystoneUrl);
+ vur.setRegionId(regionId == null ? "" : regionId);
+ vur.setServiceInstanceId(serviceInstanceId == null ? "" : serviceInstanceId);
+ vur.setTenantId(tenantId == null ? "" : tenantId);
+ vur.setVfModuleId(vfModuleId == null ? "" : vfModuleId);
+ vur.setVfModuleName(vfModuleName == null ? "" : vfModuleName);
+ vur.setVnfId(vnfId == null ? "" : vnfId);
+ vur.setVnfName(vnfName == null ? "" : vnfName);
+
+ return vur;
+ }
+
+ /*
+ * This method is to construct the ValetDeleteRequest pojo
+ */
+ private ValetDeleteRequest createValetDeleteRequest(String regionId, String tenantId, String vfModuleId, String vfModuleName) {
+ ValetDeleteRequest vdr = new ValetDeleteRequest();
+ vdr.setRegionId(regionId == null ? "" : regionId);
+ vdr.setTenantId(tenantId == null ? "" : tenantId);
+ vdr.setVfModuleId(vfModuleId == null ? "" : vfModuleId);
+ vdr.setVfModuleName(vfModuleName == null ? "" : vfModuleName);
+
+ return vdr;
+ }
+
+ /*
+ * This method is to construct the ValetDeleteRequest pojo
+ */
+ private ValetConfirmRequest createValetConfirmRequest(String stackId) {
+ ValetConfirmRequest vcr = new ValetConfirmRequest();
+ vcr.setStackId(stackId);
+
+ return vcr;
+ }
+
+ /*
+ * This method is to construct the ValetRollbackRequest pojo
+ */
+ private ValetRollbackRequest createValetRollbackRequest(String stackId, Boolean suppressRollback, String errorMessage) {
+ ValetRollbackRequest vrr = new ValetRollbackRequest();
+ vrr.setStackId(stackId);
+ vrr.setSuppressRollback(suppressRollback);
+ vrr.setErrorMessage(errorMessage);
+
+ return vrr;
+ }
+
+ private HttpHeaders generateHeaders(String requestId) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ if (!(this.authString == null || this.authString.isEmpty())) {
+ headers.add("Authorization", "Basic " + this.authString);
+ }
+ headers.add(ValetClient.REQ_ID_HEADER_NAME, requestId);
+
+ return headers;
+ }
+
+ private <T> GenericValetResponse<T> getGVRFromResponse(ResponseEntity<T> response) {
+ GenericValetResponse<T> gvr = null;
+ if (response != null) {
+ T responseObj = response.getBody();
+ gvr = new GenericValetResponse<>(response.getStatusCodeValue(), ValetClient.NO_STATUS_RETURNED, responseObj);
+
+ } else {
+ gvr = new GenericValetResponse<>(-1, ValetClient.NO_STATUS_RETURNED, null);
+ }
+ return gvr;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/HeatRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/HeatRequest.java
new file mode 100644
index 0000000000..dfd257b06b
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/HeatRequest.java
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.woorea.openstack.heat.model.CreateStackParam;
+
+/*
+ * This class represents the heat request as sent to OpenStack as defined in the
+ * Valet Placement Operations API
+ */
+public class HeatRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+ @JsonProperty("stack_name")
+ private String stackName;
+ @JsonProperty("disable_rollback")
+ private Boolean disableRollback;
+ @JsonProperty("timeout_mins")
+ private Integer timeoutMins;
+ @JsonProperty("template")
+ private String template;
+ @JsonProperty("environment")
+ private String environment;
+ @JsonProperty("files")
+ private Map<String, Object> files = new HashMap<String, Object>();
+ @JsonProperty("parameters")
+ private Map<String, Object> parameters = new HashMap<String, Object>();
+
+ public HeatRequest(String stackName, boolean disableRollback, int timeoutMins, String template, String environment, Map<String, Object> files, Map<String, Object> parameters) {
+ super();
+ this.stackName = stackName;
+ this.disableRollback = disableRollback;
+ this.timeoutMins = timeoutMins;
+ this.template = template;
+ this.environment = environment;
+ this.files = files;
+ this.parameters = parameters;
+ }
+
+ public String getStackName() {
+ return this.stackName;
+ }
+ public void setStackName(String stackName) {
+ this.stackName = stackName;
+ }
+ public Boolean getDisableRollback() {
+ return this.disableRollback;
+ }
+ public void setDisableRollback(Boolean disableRollback) {
+ this.disableRollback = disableRollback;
+ }
+ public Integer getTimeoutMins() {
+ return this.timeoutMins;
+ }
+ public void setTimeoutMins(Integer timeoutMins) {
+ this.timeoutMins = timeoutMins;
+ }
+ public String getTemplate() {
+ return this.template;
+ }
+ public void setTemplate(String template) {
+ this.template = template;
+ }
+ public String getEnvironment() {
+ return this.environment;
+ }
+ public void setEnvironment(String environment) {
+ this.environment = environment;
+ }
+ public Map<String, Object> getFiles() {
+ return this.files;
+ }
+ public void setFiles(Map<String, Object> files) {
+ this.files = files;
+ }
+ public Map<String, Object> getParameters() {
+ return this.parameters;
+ }
+ public void setParameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hash(stackName, disableRollback, timeoutMins, template, environment, files, parameters);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof HeatRequest)) {
+ return false;
+ }
+ HeatRequest hr = (HeatRequest) o;
+ return Objects.equals(stackName, hr.stackName)
+ && Objects.equals(disableRollback, hr.disableRollback)
+ && Objects.equals(timeoutMins, hr.timeoutMins)
+ && Objects.equals(template, hr.template)
+ && Objects.equals(environment, hr.environment)
+ && Objects.equals(files, hr.files)
+ && Objects.equals(parameters, hr.parameters);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmRequest.java
new file mode 100644
index 0000000000..36083e8be6
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmRequest.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+/*
+ * This class represents the body of a Confirm operation on a Valet Placement API call
+ */
+public class ValetConfirmRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("stack_id")
+ private String stackId;
+
+ public ValetConfirmRequest() {
+ super();
+ }
+ public ValetConfirmRequest(String stackId) {
+ super();
+ this.stackId = stackId;
+ }
+
+ public String getStackId() {
+ return this.stackId;
+ }
+ public void setStackId(String stackId) {
+ this.stackId = stackId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(stackId);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetConfirmRequest)) {
+ return false;
+ }
+ ValetConfirmRequest vcr = (ValetConfirmRequest) o;
+ return Objects.equals(stackId, vcr.stackId);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmResponse.java
new file mode 100644
index 0000000000..c009da9608
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetConfirmResponse.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+
+/* This class has no body - placeholder if needed - for the response to a Confirm operation */
+
+public class ValetConfirmResponse implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateRequest.java
new file mode 100644
index 0000000000..d692416ea1
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateRequest.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of a Create request operation on a Valet Placement API call
+ */
+public class ValetCreateRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("region_id")
+ private String regionId;
+ @JsonProperty("tenant_id")
+ private String tenantId;
+ @JsonProperty("service_instance_id")
+ private String serviceInstanceId;
+ @JsonProperty("vnf_id")
+ private String vnfId;
+ @JsonProperty("vnf_name")
+ private String vnfName;
+ @JsonProperty("vf_module_id")
+ private String vfModuleId;
+ @JsonProperty("vf_module_name")
+ private String vfModuleName;
+ @JsonProperty("keystone_url")
+ private String keystoneUrl;
+ @JsonProperty("heat_request")
+ private HeatRequest heatRequest;
+
+ public ValetCreateRequest() {
+ super();
+ }
+
+ public String getRegionId() {
+ return this.regionId;
+ }
+ public void setRegionId(String regionId) {
+ this.regionId = regionId;
+ }
+ public String getTenantId() {
+ return this.tenantId;
+ }
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+ public String getServiceInstanceId() {
+ return this.serviceInstanceId;
+ }
+ public void setServiceInstanceId(String serviceInstanceId) {
+ this.serviceInstanceId = serviceInstanceId;
+ }
+ public String getVnfId() {
+ return this.vnfId;
+ }
+ public void setVnfId(String vnfId) {
+ this.vnfId = vnfId;
+ }
+ public String getVnfName() {
+ return this.vnfName;
+ }
+ public void setVnfName(String vnfName) {
+ this.vnfName = vnfName;
+ }
+ public String getVfModuleId() {
+ return this.vfModuleId;
+ }
+ public void setVfModuleId(String vfModuleId) {
+ this.vfModuleId = vfModuleId;
+ }
+ public String getVfModuleName() {
+ return this.vfModuleName;
+ }
+ public void setVfModuleName(String vfModuleName) {
+ this.vfModuleName = vfModuleName;
+ }
+ public String getKeystoneUrl() {
+ return this.keystoneUrl;
+ }
+ public void setKeystoneUrl(String keystoneUrl) {
+ this.keystoneUrl = keystoneUrl;
+ }
+ public HeatRequest getHeatRequest() {
+ return this.heatRequest;
+ }
+ public void setHeatRequest(HeatRequest heatRequest) {
+ this.heatRequest = heatRequest;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(regionId, tenantId, serviceInstanceId, vnfId, vnfName, vfModuleId, vfModuleName, keystoneUrl, heatRequest);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetCreateRequest)) {
+ return false;
+ }
+ ValetCreateRequest vcr = (ValetCreateRequest) o;
+ return Objects.equals(regionId, vcr.regionId)
+ && Objects.equals(tenantId, vcr.tenantId)
+ && Objects.equals(serviceInstanceId, vcr.serviceInstanceId)
+ && Objects.equals(vnfId, vcr.vnfId)
+ && Objects.equals(vnfName, vcr.vnfName)
+ && Objects.equals(vfModuleId, vcr.vfModuleId)
+ && Objects.equals(vfModuleName, vcr.vfModuleName)
+ && Objects.equals(keystoneUrl, vcr.keystoneUrl)
+ && Objects.equals(heatRequest, vcr.heatRequest);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateResponse.java
new file mode 100644
index 0000000000..e0c750e79f
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetCreateResponse.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import java.util.Objects;
+import java.io.Serializable;
+/*
+ * This class represents the body of a Create response on a Valet Placement API call
+ */
+public class ValetCreateResponse implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("status")
+ private ValetStatus status;
+ @JsonProperty("parameters")
+ private Map<String, Object> parameters;
+
+ public ValetCreateResponse() {
+ super();
+ }
+
+ public ValetStatus getStatus() {
+ return this.status;
+ }
+ public void setStatus(ValetStatus status) {
+ this.status = status;
+ }
+ public Map<String, Object> getParameters() {
+ return this.parameters;
+ }
+ public void setParameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status, parameters);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetCreateResponse)) {
+ return false;
+ }
+ ValetCreateResponse vcr = (ValetCreateResponse) o;
+ return Objects.equals(status, vcr.status)
+ && Objects.equals(parameters, vcr.parameters);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteRequest.java
new file mode 100644
index 0000000000..7bd5855d0e
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteRequest.java
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of a Delete request on a Valet Placement API call
+ */
+public class ValetDeleteRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("region_id")
+ private String regionId;
+ @JsonProperty("tenant_id")
+ private String tenantId;
+ @JsonProperty("vf_module_id")
+ private String vfModuleId;
+ @JsonProperty("vf_module_name")
+ private String vfModuleName;
+
+ public String getRegionId() {
+ return this.regionId;
+ }
+ public void setRegionId(String regionId) {
+ this.regionId = regionId;
+ }
+ public String getTenantId() {
+ return this.tenantId;
+ }
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+ public String getVfModuleId() {
+ return this.vfModuleId;
+ }
+ public void setVfModuleId(String vfModuleId) {
+ this.vfModuleId = vfModuleId;
+ }
+ public String getVfModuleName() {
+ return this.vfModuleName;
+ }
+ public void setVfModuleName(String vfModuleName) {
+ this.vfModuleName = vfModuleName;
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hash(regionId, tenantId, vfModuleId, vfModuleName);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetDeleteRequest)) {
+ return false;
+ }
+ ValetDeleteRequest vdr = (ValetDeleteRequest) o;
+ return Objects.equals(regionId, vdr.regionId)
+ && Objects.equals(tenantId, vdr.tenantId)
+ && Objects.equals(vfModuleId, vdr.vfModuleId)
+ && Objects.equals(vfModuleName, vdr.vfModuleName);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteResponse.java
new file mode 100644
index 0000000000..fa58752d61
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetDeleteResponse.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of a Delete response on a Valet Placement API call
+ */
+public class ValetDeleteResponse implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+ @JsonProperty("status")
+ private ValetStatus status;
+
+ public ValetDeleteResponse() {
+ super();
+ }
+ public ValetDeleteResponse(ValetStatus status) {
+ super();
+ this.status = status;
+ }
+
+ public ValetStatus getStatus() {
+ return this.status;
+ }
+ public void setStatus(ValetStatus status) {
+ this.status = status;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetDeleteResponse)) {
+ return false;
+ }
+ ValetDeleteResponse vdr = (ValetDeleteResponse) o;
+ return Objects.equals(status, vdr.status);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackRequest.java
new file mode 100644
index 0000000000..ae0af67f80
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackRequest.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of a Rollback request on a Valet Placement API call
+ */
+public class ValetRollbackRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("stack_id")
+ private String stackId;
+ @JsonProperty("suppress_rollback")
+ private Boolean suppressRollback = false;
+ @JsonProperty("error_message")
+ private String errorMessage;
+
+ public ValetRollbackRequest() {
+ super();
+ }
+
+ public String getStackId() {
+ return this.stackId;
+ }
+ public void setStackId(String stackId) {
+ this.stackId = stackId;
+ }
+ public Boolean getSuppressRollback() {
+ return this.suppressRollback;
+ }
+ public void setSuppressRollback(Boolean suppressRollback) {
+ this.suppressRollback = suppressRollback;
+ }
+ public String getErrorMessage() {
+ return this.errorMessage;
+ }
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(stackId, suppressRollback, errorMessage);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetRollbackRequest)) {
+ return false;
+ }
+ ValetRollbackRequest vrr = (ValetRollbackRequest) o;
+ return Objects.equals(stackId, vrr.stackId)
+ && Objects.equals(suppressRollback, vrr.suppressRollback)
+ && Objects.equals(errorMessage, vrr.errorMessage);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackResponse.java
new file mode 100644
index 0000000000..429aa95af0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetRollbackResponse.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+/* This class has no body - placeholder - body of a Rollback response on a Valet Placement Operation */
+
+public class ValetRollbackResponse implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetStatus.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetStatus.java
new file mode 100644
index 0000000000..067a6727c1
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetStatus.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 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.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/*
+ * This class represents the status object as defined in the Valet Placement Operations API - part of Response objects
+ */
+public class ValetStatus implements Serializable {
+ private static final long serialVersionUID = 1L;
+ @JsonProperty("status")
+ private String status;
+ @JsonProperty("message")
+ private String message;
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append("status", status).append("message", message).toString();
+ }
+
+ public ValetStatus() {
+ super();
+ }
+
+ public ValetStatus(String statusCode, String statusMessage) {
+ super();
+ this.status = statusCode;
+ this.message = statusMessage;
+ }
+
+ public String getStatus() {
+ return this.status;
+ }
+ public void setStatus(String statusCode) {
+ this.status = statusCode;
+ }
+ public String getMessage() {
+ return this.message;
+ }
+ public void setMessage(String statusMessage) {
+ this.message = statusMessage;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status, message);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetStatus)) {
+ return false;
+ }
+ ValetStatus vs = (ValetStatus) o;
+ return Objects.equals(status, vs.status) && Objects.equals(message, vs.message);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateRequest.java
new file mode 100644
index 0000000000..360c07b225
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateRequest.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of an Update request on a Valet Placement API call
+ */
+public class ValetUpdateRequest implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+
+ @JsonProperty("region_id")
+ private String regionId;
+ @JsonProperty("tenant_id")
+ private String tenantId;
+ @JsonProperty("service_instance_id")
+ private String serviceInstanceId;
+ @JsonProperty("vnf_id")
+ private String vnfId;
+ @JsonProperty("vnf_name")
+ private String vnfName;
+ @JsonProperty("vf_module_id")
+ private String vfModuleId;
+ @JsonProperty("vf_module_name")
+ private String vfModuleName;
+ @JsonProperty("keystone_url")
+ private String keystoneUrl;
+ @JsonProperty("heat_request")
+ private HeatRequest heatRequest;
+
+ public ValetUpdateRequest() {
+ super();
+ }
+
+ public String getRegionId() {
+ return this.regionId;
+ }
+ public void setRegionId(String regionId) {
+ this.regionId = regionId;
+ }
+ public String getTenantId() {
+ return this.tenantId;
+ }
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+ public String getServiceInstanceId() {
+ return this.serviceInstanceId;
+ }
+ public void setServiceInstanceId(String serviceInstanceId) {
+ this.serviceInstanceId = serviceInstanceId;
+ }
+ public String getVnfId() {
+ return this.vnfId;
+ }
+ public void setVnfId(String vnfId) {
+ this.vnfId = vnfId;
+ }
+ public String getVnfName() {
+ return this.vnfName;
+ }
+ public void setVnfName(String vnfName) {
+ this.vnfName = vnfName;
+ }
+ public String getVfModuleId() {
+ return this.vfModuleId;
+ }
+ public void setVfModuleId(String vfModuleId) {
+ this.vfModuleId = vfModuleId;
+ }
+ public String getVfModuleName() {
+ return this.vfModuleName;
+ }
+ public void setVfModuleName(String vfModuleName) {
+ this.vfModuleName = vfModuleName;
+ }
+ public String getKeystoneUrl() {
+ return this.keystoneUrl;
+ }
+ public void setKeystoneUrl(String keystoneUrl) {
+ this.keystoneUrl = keystoneUrl;
+ }
+ public HeatRequest getHeatRequest() {
+ return this.heatRequest;
+ }
+ public void setHeatRequest(HeatRequest heatRequest) {
+ this.heatRequest = heatRequest;
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hash(regionId, tenantId, serviceInstanceId, vnfId, vnfName, vfModuleId, vfModuleName, keystoneUrl, heatRequest);
+
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetUpdateRequest)) {
+ return false;
+ }
+ ValetUpdateRequest vur = (ValetUpdateRequest) o;
+ return Objects.equals(regionId, vur.regionId)
+ && Objects.equals(tenantId, vur.tenantId)
+ && Objects.equals(serviceInstanceId, vur.serviceInstanceId)
+ && Objects.equals(vnfId, vur.vnfId)
+ && Objects.equals(vnfName, vur.vnfName)
+ && Objects.equals(vfModuleId, vur.vfModuleId)
+ && Objects.equals(vfModuleName, vur.vfModuleName)
+ && Objects.equals(keystoneUrl, vur.keystoneUrl)
+ && Objects.equals(heatRequest, vur.heatRequest);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateResponse.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateResponse.java
new file mode 100644
index 0000000000..36f11d30c0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/valet/beans/ValetUpdateResponse.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.valet.beans;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * This class represents the body of an Update response on a Valet Placement API call
+ */
+public class ValetUpdateResponse implements Serializable {
+ private static final long serialVersionUID = 768026109321305392L;
+ @JsonProperty("status")
+ private ValetStatus status;
+ @JsonProperty("parameters")
+ private Map<String, Object> parameters;
+
+ public ValetUpdateResponse() {
+ super();
+ }
+
+ public ValetStatus getStatus() {
+ return this.status;
+ }
+ public void setStatus(ValetStatus status) {
+ this.status = status;
+ }
+ public Map<String, Object> getParameters() {
+ return this.parameters;
+ }
+ public void setParameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(status, parameters);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof ValetUpdateResponse)) {
+ return false;
+ }
+ ValetUpdateResponse vur = (ValetUpdateResponse) o;
+ return Objects.equals(status, vur.status)
+ && Objects.equals(parameters, vur.parameters);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vdu/mapper/VfModuleCustomizationToVduMapper.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vdu/mapper/VfModuleCustomizationToVduMapper.java
new file mode 100644
index 0000000000..f6442b6252
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vdu/mapper/VfModuleCustomizationToVduMapper.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.so.adapters.vdu.mapper;
+
+import java.util.List;
+
+import org.onap.so.adapters.vdu.VduModelInfo;
+import org.onap.so.adapters.vdu.VduArtifact;
+import org.onap.so.adapters.vdu.VduArtifact.ArtifactType;
+import org.onap.so.db.catalog.beans.HeatEnvironment;
+import org.onap.so.db.catalog.beans.HeatFiles;
+import org.onap.so.db.catalog.beans.HeatTemplate;
+import org.onap.so.db.catalog.beans.VfModuleCustomization;
+import org.springframework.stereotype.Component;
+
+@Component
+public class VfModuleCustomizationToVduMapper {
+
+ public VduModelInfo mapVfModuleCustomizationToVdu(VfModuleCustomization vfModuleCustom)
+ {
+ VduModelInfo vduModel = new VduModelInfo();
+ vduModel.setModelCustomizationUUID(vfModuleCustom.getModelCustomizationUUID());
+
+ // Map the cloud templates, attached files, and environment file
+ mapCloudTemplates(vfModuleCustom.getVfModule().getModuleHeatTemplate(), vduModel);
+ mapCloudFiles(vfModuleCustom,vduModel);
+ mapEnvironment(vfModuleCustom.getHeatEnvironment(), vduModel);
+
+ return vduModel;
+ }
+
+ public VduModelInfo mapVfModuleCustVolumeToVdu(VfModuleCustomization vfModuleCustom)
+ {
+ VduModelInfo vduModel = new VduModelInfo();
+ vduModel.setModelCustomizationUUID(vfModuleCustom.getModelCustomizationUUID());
+
+ // Map the cloud templates, attached files, and environment file
+ mapCloudTemplates(vfModuleCustom.getVfModule().getVolumeHeatTemplate(), vduModel);
+ mapCloudFiles(vfModuleCustom,vduModel);
+ mapEnvironment(vfModuleCustom.getVolumeHeatEnv(), vduModel);
+
+ return vduModel;
+ }
+
+ private void mapCloudTemplates(HeatTemplate heatTemplate, VduModelInfo vduModel) {
+ // TODO: These catalog objects will be refactored to be non-Heat-specific
+
+ List<VduArtifact> vduArtifacts = vduModel.getArtifacts();
+
+ // Main template. Also set the VDU timeout based on the main template.
+ vduArtifacts.add(mapHeatTemplateToVduArtifact(heatTemplate, ArtifactType.MAIN_TEMPLATE));
+ vduModel.setTimeoutMinutes(heatTemplate.getTimeoutMinutes());
+
+ // Nested templates
+ List<HeatTemplate> childTemplates = heatTemplate.getChildTemplates();
+ if (childTemplates != null) {
+ for(HeatTemplate childTemplate : childTemplates){
+ vduArtifacts.add(mapHeatTemplateToVduArtifact(childTemplate, ArtifactType.NESTED_TEMPLATE));
+ }
+ }
+ }
+
+ private VduArtifact mapHeatTemplateToVduArtifact(HeatTemplate heatTemplate, ArtifactType artifactType) {
+ VduArtifact vduArtifact = new VduArtifact();
+ vduArtifact.setName(heatTemplate.getTemplateName());
+ vduArtifact.setContent(heatTemplate.getHeatTemplate().getBytes());
+ vduArtifact.setType(artifactType);
+ return vduArtifact;
+ }
+
+ private void mapCloudFiles(VfModuleCustomization vfModuleCustom, VduModelInfo vduModel) {
+ // TODO: These catalog objects will be refactored to be non-Heat-specific
+
+ List<VduArtifact> vduArtifacts = vduModel.getArtifacts();
+
+ // Attached Files
+ List<HeatFiles> heatFiles = vfModuleCustom.getVfModule().getHeatFiles();
+ if (heatFiles != null) {
+ for(HeatFiles file : heatFiles){
+ vduArtifacts.add(mapCloudFileToVduArtifact(file, ArtifactType.TEXT_FILE));
+ }
+ }
+ }
+
+ private VduArtifact mapCloudFileToVduArtifact(HeatFiles heatFile, ArtifactType artifactType) {
+ VduArtifact vduArtifact = new VduArtifact();
+ vduArtifact.setName(heatFile.getFileName());
+ vduArtifact.setContent(heatFile.getFileBody().getBytes());
+ vduArtifact.setType(artifactType);
+ return vduArtifact;
+ }
+
+ private void mapEnvironment(HeatEnvironment heatEnvironment, VduModelInfo vduModel) {
+ // TODO: These catalog objects will be refactored to be non-Heat-specific
+ if (heatEnvironment != null) {
+ List<VduArtifact> vduArtifacts = vduModel.getArtifacts();
+ vduArtifacts.add(mapEnvironmentFileToVduArtifact(heatEnvironment));
+ }
+ }
+
+ private VduArtifact mapEnvironmentFileToVduArtifact(HeatEnvironment heatEnv) {
+ VduArtifact vduArtifact = new VduArtifact();
+ vduArtifact.setName(heatEnv.getName());
+ vduArtifact.setContent(heatEnv.getEnvironment().getBytes());
+ vduArtifact.setType(ArtifactType.ENVIRONMENT);
+ return vduArtifact;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/BpelRestClient.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/BpelRestClient.java
new file mode 100644
index 0000000000..6383f57693
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/BpelRestClient.java
@@ -0,0 +1,296 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.security.GeneralSecurityException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.annotation.PostConstruct;
+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.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.utils.CryptoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+/**
+ * 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.onap.so.adapters.vnf.bpelauth encrypted authorization string to send to BEPL engine
+ * org.onap.so.adapters.vnf.sockettimeout socket timeout value
+ * org.onap.so.adapters.vnf.connecttimeout connect timeout value
+ * org.onap.so.adapters.vnf.retrycount number of times to retry failed connections
+ * org.onap.so.adapters.vnf.retryinterval interval (in seconds) between retries
+ * org.onap.so.adapters.vnf.retrylist list of response codes that will trigger a retry (the special code
+ * 900 means "connection was not established")
+ */
+@Component("VnfBpel")
+@Scope("prototype")
+public class BpelRestClient {
+ public static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
+ private static final String PROPERTY_DOMAIN = "org.onap.so.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, BpelRestClient.class);
+
+ /** 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 = "";
+
+ @Autowired
+ private Environment env;
+ // 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 = "";
+
+ }
+
+ @PostConstruct
+ protected void init() {
+
+ socketTimeout = env.getProperty(SOCKET_TIMEOUT_PROPERTY, Integer.class, DEFAULT_SOCKET_TIMEOUT);
+ connectTimeout = env.getProperty(CONN_TIMEOUT_PROPERTY, Integer.class, DEFAULT_CONNECT_TIMEOUT);
+ retryCount = env.getProperty(RETRY_COUNT_PROPERTY, Integer.class, DEFAULT_RETRY_COUNT);
+ retryInterval = env.getProperty(RETRY_INTERVAL_PROPERTY, Integer.class, DEFAULT_RETRY_INTERVAL);
+ setRetryList(env.getProperty(RETRY_LIST_PROPERTY, DEFAULT_RETRY_LIST));
+ credentials = getEncryptedProperty(BPEL_AUTH_PROPERTY, DEFAULT_CREDENTIALS, ENCRYPTION_KEY);
+ }
+
+ 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) {
+ int newRetryCount = retryCount;
+ if (newRetryCount < 0)
+ newRetryCount = DEFAULT_RETRY_COUNT;
+ this.retryCount = newRetryCount;
+ }
+
+ 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.isEmpty())
+ return "";
+ String t = retryList.toString();
+ return t.substring(1, t.length()-1);
+ }
+
+ public void setRetryList(String retryList) {
+ Set<Integer> s = new TreeSet<>();
+ 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) {
+ LOGGER.debug("Exception while Thread sleep", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ private void debug(String m) {
+ LOGGER.debug(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);
+
+ 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);
+ }
+
+ private String getEncryptedProperty(String key, String defaultValue, String encryptionKey) {
+ if (env.getProperty(key) != null) {
+ try {
+ return CryptoUtils.decrypt(env.getProperty(key), encryptionKey);
+ } catch (GeneralSecurityException e) {
+ LOGGER.debug("Exception while decrypting property: " + env.getProperty(key), e);
+ }
+ }
+ return defaultValue;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/CSAR.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/CSAR.java
new file mode 100644
index 0000000000..bbfcef02e2
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/CSAR.java
@@ -0,0 +1,192 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 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.onap.so.adapters.vnf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.onap.so.adapters.vdu.VduArtifact;
+import org.onap.so.adapters.vdu.VduArtifact.ArtifactType;
+import org.onap.so.adapters.vdu.VduModelInfo;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+
+import com.google.common.io.Files;
+
+/**
+ * The purpose of this class is to create a CSAR byte array from Vdu inputs for the purpose
+ * of forwarding to a TOSCA orchestrator.
+ *
+ * @author DeWayne
+ *
+ */
+public class CSAR {
+ private static final String MANIFEST_FILENAME = "MANIFEST.MF";
+ private VduModelInfo vduModel;
+
+ public CSAR(VduModelInfo model){
+ this.vduModel = model;
+ }
+
+ /**
+ * Creates a byte array representation of a CSAR corresponding to the VduBlueprint arg in the
+ * constructor.
+ *
+ * @return
+ * @throws VnfException
+ */
+ public byte[] create() {
+ File dir = Files.createTempDir();
+
+ /**
+ * Create subdir
+ */
+ File metadir = new File(dir.getAbsolutePath() + "/TOSCA-Metadata");
+ if (!metadir.mkdir()) {
+ throw new RuntimeException("CSAR TOSCA-Metadata directory create failed");
+ }
+
+ /**
+ * Organize model info for consumption
+ */
+ VduArtifact mainTemplate = null;
+ List<VduArtifact> extraFiles = new ArrayList<>();
+ for(VduArtifact artifact: vduModel.getArtifacts()) {
+ if(artifact.getType() == ArtifactType.MAIN_TEMPLATE ) {
+ mainTemplate = artifact;
+ } else{
+ extraFiles.add(artifact);
+ }
+ }
+
+ if (mainTemplate == null) { // make a dummy to avoid null pointers
+ mainTemplate = new VduArtifact("", new byte[0], null);
+ }
+
+ /**
+ * Write template files
+ */
+ try (OutputStream ofs = new FileOutputStream(new File(dir, mainTemplate.getName()));
+ PrintStream mfstream = new PrintStream(new File(metadir.getAbsolutePath() + '/' + MANIFEST_FILENAME));
+ ) {
+ ofs.write(mainTemplate.getContent());
+
+ /**
+ * Write other files
+ */
+ if (!extraFiles.isEmpty()) {
+ for (VduArtifact artifact: extraFiles){
+ try (OutputStream out = new FileOutputStream(new File(dir, artifact.getName()));) {
+ out.write(artifact.getContent());
+ }
+ }
+ }
+
+
+ /**
+ * Create manifest
+ */
+ mfstream.println("TOSCA-Meta-File-Version: 1.0");
+ mfstream.println("CSAR-Version: 1.1");
+ mfstream.println("Created-by: ONAP");
+ mfstream.println("Entry-Definitions: " + mainTemplate.getName());
+
+ /**
+ * ZIP it up
+ */
+ ByteArrayOutputStream zipbytes = new ByteArrayOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(zipbytes);
+ compressTree(zos, "", dir, dir);
+ zos.close();
+ return zipbytes.toByteArray();
+
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create CSAR: " + e.getMessage());
+ } finally {
+ /**
+ * Clean up tmpdir
+ */
+ deleteDirectory(dir);
+ }
+ }
+
+ /**
+ * Private methods
+ */
+
+ /**
+ * Compresses (ZIPs) a directory tree
+ *
+ * @param dir
+ * @throws IOException
+ */
+ private void compressTree(ZipOutputStream zos, String path, File basedir, File dir) throws IOException {
+ if (!dir.isDirectory())
+ return;
+
+ for (File f : dir.listFiles()) {
+ if (f.isDirectory()) {
+ String newpath = path + f.getName() + '/';
+ ZipEntry entry = new ZipEntry(newpath);
+ zos.putNextEntry(entry);
+ zos.closeEntry();
+ compressTree(zos, newpath, basedir, f);
+ } else {
+ ZipEntry ze = new ZipEntry(
+ f.getAbsolutePath().substring(basedir.getAbsolutePath().length() + 1).replaceAll("\\\\", "/"));
+ zos.putNextEntry(ze);
+ // read the file and write to ZipOutputStream
+ try (FileInputStream fis = new FileInputStream(f);) {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = fis.read(buffer)) > 0) {
+ zos.write(buffer, 0, len);
+ }
+ }
+ zos.closeEntry();
+ }
+ }
+ }
+
+ private boolean deleteDirectory(File directory) {
+ if (directory.exists()) {
+ File[] files = directory.listFiles();
+ if (null != files) {
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ deleteDirectory(files[i]);
+ } else {
+ files[i].delete();
+ }
+ }
+ }
+ }
+ return (directory.delete());
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapter.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapter.java
new file mode 100644
index 0000000000..5efcc2c90d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapter.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.Map;
+
+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.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+
+@WebService (name="VnfAdapter", targetNamespace="http://org.onap.so/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="enableBridge") Boolean enableBridge,
+ @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 = "modelCustomizationUuid") @XmlElement(required = false) String modelCustomizationUuid,
+ @WebParam(name="inputs") Map<String,String> inputs,
+ @WebParam(name="failIfExists") Boolean failIfExists,
+ @WebParam(name="backout") Boolean backout,
+ @WebParam(name="enableBridge") Boolean enableBridge,
+ @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,
+ @WebParam(name = "vfModuleOutputs", mode = Mode.OUT) Holder<Map<String, String>> vfModuleOutputs)
+ 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 = "modelCustomizationUuid") @XmlElement(required = false) String modelCustomizationUuid,
+ @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-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsync.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsync.java
new file mode 100644
index 0000000000..b67a412c3e
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsync.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.Map;
+
+import javax.jws.Oneway;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.openstack.beans.VnfRollback;
+
+/**
+ * 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://org.onap.so/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="enableBridge") Boolean enableBridge,
+ @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-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsyncImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsyncImpl.java
new file mode 100644
index 0000000000..95135f579d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterAsyncImpl.java
@@ -0,0 +1,666 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+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.onap.so.adapters.vnf.async.client.CreateVnfNotification;
+import org.onap.so.adapters.vnf.async.client.QueryVnfNotification;
+import org.onap.so.adapters.vnf.async.client.UpdateVnfNotification;
+import org.onap.so.adapters.vnf.async.client.VnfAdapterNotify;
+import org.onap.so.adapters.vnf.async.client.VnfAdapterNotify_Service;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.utils.CryptoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@WebService(serviceName = "VnfAdapterAsync", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapterAsync", targetNamespace = "http://org.onap.so/vnfA")
+@Component
+public class MsoVnfAdapterAsyncImpl implements MsoVnfAdapterAsync {
+
+ public static final String MSO_PROP_VNF_ADAPTER="MSO_PROP_VNF_ADAPTER";
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, MsoVnfAdapterAsyncImpl.class);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String BPEL_AUTH_PROP = "org.onap.so.adapters.vnf.bpelauth";
+ private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private MsoVnfAdapterImpl vnfImpl;
+
+ /**
+ * 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,
+ Boolean enableBridge,
+ 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");
+ // Use the synchronous method to perform the actual Create
+ MsoVnfAdapter vnfAdapter = vnfImpl;
+ // Synchronous Web Service Outputs
+ Holder <String> vnfId = new Holder <> ();
+ Holder <Map <String, String>> outputs = new Holder <> ();
+ Holder <VnfRollback> vnfRollback = new Holder <> ();
+
+ try {
+ vnfAdapter.createVnf (cloudSiteId,
+ tenantId,
+ vnfType,
+ vnfVersion,
+ vnfName,
+ requestType,
+ volumeGroupHeatStackId,
+ inputs,
+ failIfExists,
+ backout,
+ enableBridge,
+ 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.onap.so.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.onap.so.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", "");
+ 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);
+ LOGGER.info (MessageEnum.RA_ASYNC_UPDATE_VNF, vnfName, vnfType, cloudSiteId, tenantId, "UpdateVnfA");
+
+ // Use the synchronous method to perform the actual Create
+ MsoVnfAdapter vnfAdapter = vnfImpl;
+
+ // Synchronous Web Service Outputs
+ Holder <String> vnfId = new Holder <> ();
+ Holder <Map <String, String>> outputs = new Holder <> ();
+ Holder <VnfRollback> vnfRollback = new Holder <> ();
+
+ 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.onap.so.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.onap.so.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);
+ LOGGER.info (MessageEnum.RA_ASYNC_QUERY_VNF, vnfName, cloudSiteId, tenantId);
+
+ // Use the synchronous method to perform the actual query
+ MsoVnfAdapter vnfAdapter = vnfImpl;
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> vnfExists = new Holder <> ();
+ Holder <String> vnfId = new Holder <> ();
+ Holder <VnfStatus> status = new Holder <> ();
+ Holder <Map <String, String>> outputs = new Holder <> ();
+
+ 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.onap.so.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.onap.so.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.onap.so.adapters.vnf.async.client.VnfStatus vnfS = org.onap.so.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);
+ LOGGER.info (MessageEnum.RA_ASYNC_DELETE_VNF, vnfName, cloudSiteId, tenantId);
+
+ // Use the synchronous method to perform the actual delete
+ MsoVnfAdapter vnfAdapter = vnfImpl;
+
+ 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.onap.so.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.onap.so.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);
+ 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 = vnfImpl;
+
+ 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.onap.so.adapters.vnf.async.client.MsoExceptionCategory exCat = null;
+ String eMsg = null;
+ try {
+ eMsg = e.getFaultInfo ().getMessage ();
+ exCat = org.onap.so.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.onap.so.adapters.vnf.async.client.VnfRollback copyVrb (Holder <VnfRollback> hVrb) {
+ org.onap.so.adapters.vnf.async.client.VnfRollback cvrb = new org.onap.so.adapters.vnf.async.client.VnfRollback ();
+
+ if (hVrb != null && hVrb.value != null) {
+ org.onap.so.adapters.vnf.async.client.MsoRequest cmr = new org.onap.so.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 <> ();
+ 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 <> ();
+ sMap = hMap.value;
+ UpdateVnfNotification.Outputs.Entry entry = new UpdateVnfNotification.Outputs.Entry ();
+
+ for (Map.Entry<String,String> mapEntry : sMap.entrySet ()) {
+ String key = mapEntry.getKey();
+ String value = mapEntry.getValue();
+ entry.setKey (key);
+ entry.setValue (value);
+ 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 <> ();
+ sMap = hMap.value;
+
+ QueryVnfNotification.Outputs.Entry entry = new QueryVnfNotification.Outputs.Entry ();
+
+ for (Map.Entry<String,String> mapEntry : sMap.entrySet ()) {
+ String key = mapEntry.getKey();
+ String value = mapEntry.getValue();
+ entry.setKey (key);
+ entry.setValue (value);
+ 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://org.onap.so/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);
+ }
+
+ if(null != epUrl) {
+ LOGGER.debug ("Notification Endpoint URL: " + epUrl.toExternalForm ());
+ bp.getRequestContext ().put (BindingProvider.ENDPOINT_ADDRESS_PROPERTY, epUrl.toExternalForm ());
+ }
+ else {
+ LOGGER.debug ("epUrl is NULL:");
+ }
+
+ // authentication
+ try {
+ Map <String, Object> reqCtx = bp.getRequestContext ();
+ Map <String, List <String>> headers = new HashMap <> ();
+
+ String userCredentials = this.getEncryptedProperty(BPEL_AUTH_PROP, "", ENCRYPTION_KEY);
+
+ String basicAuth = "Basic " + DatatypeConverter.printBase64Binary (userCredentials.getBytes ());
+ reqCtx.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;
+ }
+
+ public String getEncryptedProperty(String key, String defaultValue, String encryptionKey) {
+ try {
+ return CryptoUtils.decrypt(this.environment.getProperty(key), encryptionKey);
+ } catch (GeneralSecurityException e) {
+ LOGGER.debug("Exception while decrypting property: " + this.environment.getProperty(key), e);
+ }
+ return defaultValue;
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java
new file mode 100644
index 0000000000..994a83c422
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java
@@ -0,0 +1,2347 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.adapters.vnf.exceptions.VnfNotFound;
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.CloudSite;
+import org.onap.so.db.catalog.beans.HeatEnvironment;
+import org.onap.so.db.catalog.beans.HeatFiles;
+import org.onap.so.db.catalog.beans.HeatTemplate;
+import org.onap.so.db.catalog.beans.HeatTemplateParam;
+import org.onap.so.db.catalog.beans.VfModule;
+import org.onap.so.db.catalog.beans.VfModuleCustomization;
+import org.onap.so.db.catalog.beans.VnfResource;
+import org.onap.so.db.catalog.data.repository.VFModuleCustomizationRepository;
+import org.onap.so.db.catalog.data.repository.VnfResourceRepository;
+import org.onap.so.db.catalog.utils.MavenLikeVersioning;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.HeatStatus;
+import org.onap.so.openstack.beans.StackInfo;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.onap.so.openstack.exceptions.MsoHeatNotFoundException;
+import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
+import org.onap.so.openstack.utils.MsoHeatUtils;
+import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
+import org.onap.so.adapters.valet.ValetClient;
+import org.onap.so.adapters.valet.beans.HeatRequest;
+import org.onap.so.adapters.valet.beans.ValetConfirmResponse;
+import org.onap.so.adapters.valet.beans.ValetCreateResponse;
+import org.onap.so.adapters.valet.beans.ValetDeleteResponse;
+import org.onap.so.adapters.valet.beans.ValetRollbackResponse;
+import org.onap.so.adapters.valet.beans.ValetStatus;
+import org.onap.so.adapters.valet.beans.ValetUpdateResponse;
+import org.onap.so.adapters.valet.GenericValetResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf")
+@Component
+@Transactional
+public class MsoVnfAdapterImpl implements MsoVnfAdapter {
+
+ @Autowired
+ private CloudConfig cloudConfig;
+
+ @Autowired
+ private Environment environment;
+
+ private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
+ private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter.";
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoVnfAdapterImpl.class);
+ private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
+ private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.onap.so.adapters.vnf.addGetFilesOnVolumeReq";
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ private static final String VALET_ENABLED = "org.onap.so.adapters.vnf.valet_enabled";
+ private static final String FAIL_REQUESTS_ON_VALET_FAILURE = "org.onap.so.adapters.vnf.fail_requests_on_valet_failure";
+
+ @Autowired
+ private VFModuleCustomizationRepository vfModuleCustomRepo;
+
+
+ @Autowired
+ private VnfResourceRepository vnfResourceRepo;
+
+ @Autowired
+ private MsoHeatUtilsWithUpdate heatU;
+ @Autowired
+ private MsoHeatUtils heat;
+ @Autowired
+ private ValetClient vci;
+ /**
+ * 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 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,
+ Boolean enableBridge,
+ 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 && 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,e);
+ }
+ this.createVfModule(cloudSiteId,
+ tenantId,
+ vnfType,
+ vnfVersion,
+ vnfName,
+ newRequestType,
+ vfVolGroupHeatStackId,
+ vfBaseHeatStackId,
+ null,
+ inputs,
+ failIfExists,
+ backout,
+ enableBridge,
+ 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,
+ null,
+ inputs,
+ failIfExists,
+ backout,
+ enableBridge,
+ 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 {
+ // As of 1707 - this method should no longer be called
+ MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
+ MsoLogger.setServiceName ("UpdateVnf");
+ LOGGER.debug("UpdateVnf called?? This should not be called any longer - update vfModule");
+ }
+
+ /**
+ * 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 ();
+
+ 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<>(); // 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 ();
+
+ // 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.toString(), "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);
+
+ // 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 <> ();
+ for (Map.Entry<String,Object> entry : stackOutputs.entrySet ()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ try {
+ stringOutputs.put(key, value.toString());
+ } catch (Exception e) {
+ StringBuilder msg = new StringBuilder("Unable to add " + key + " to outputs");
+ if (value instanceof Integer) { // nothing to add to the message
+ } else if (value instanceof JsonNode) {
+ msg.append(" - exception converting JsonNode");
+ } else if (value instanceof java.util.LinkedHashMap) {
+ msg.append(" exception converting LinkedHashMap");
+ } else {
+ msg.append(" - unable to call .toString() " + e.getMessage());
+ }
+ LOGGER.debug(msg.toString(), e);
+ }
+ }
+ return stringOutputs;
+ }
+
+ private Map <String, Object> copyStringInputs (Map <String, String> stringInputs) {
+ return new HashMap <> (stringInputs);
+ }
+
+ protected boolean callHeatbridge(String heatStackId) {
+ String executionDir = "/usr/local/lib/python2.7/dist-packages/heatbridge";
+ String openstackIdentityUrl = "", username = "", password = "", tenant = "", region = "", owner = "";
+ long waitTimeMs = 10000L;
+ try {
+ String[] cmdarray = {"/usr/bin/python", "HeatBridgeMain.py", openstackIdentityUrl, username, password, tenant, region, owner, heatStackId};
+ String[] envp = null;
+ File dir = new File(executionDir);
+ LOGGER.debug("Calling HeatBridgeMain.py in " + dir + " with arguments " + Arrays.toString(cmdarray));
+ Runtime r = Runtime.getRuntime();
+ Process p = r.exec(cmdarray, envp, dir);
+ boolean wait = p.waitFor(waitTimeMs, TimeUnit.MILLISECONDS);
+
+ LOGGER.debug(" HeatBridgeMain.py returned " + wait + " with code " + p.exitValue());
+ return wait && p.exitValue()==0;
+ } catch (IOException e) {
+ LOGGER.debug(" HeatBridgeMain.py failed with IO Exception! " + e);
+ return false;
+ } catch (InterruptedException e) {
+ LOGGER.debug(" HeatBridgeMain.py failed when interrupted! " + e);
+ return false;
+ } catch (RuntimeException e) {
+ LOGGER.debug(" HeatBridgeMain.py failed for unknown reasons!" + e);
+ return false;
+ }
+ }
+
+ private void sendMapToDebug(Map<String, Object> inputs, String optionalName) {
+ int i = 0;
+ StringBuilder sb = new StringBuilder(optionalName == null ? "\ninputs" : "\n" + optionalName);
+ if (inputs == null) {
+ sb.append("\tNULL");
+ }
+ else if (inputs.size() < 1) {
+ sb.append("\tEMPTY");
+ } else {
+ for (Map.Entry<String,Object> entry : inputs.entrySet()) {
+ String outputString;
+ String str = entry.getKey();
+ Object value = entry.getValue();
+ try {
+ outputString = value.toString();
+ } catch (Exception e) {
+ LOGGER.debug("Exception :",e);
+ outputString = "Unable to call toString() on the value for " + str;
+ }
+ sb.append("\t\nitem ").append(i++).append(": '").append(str).append("'='").append(outputString)
+ .append("'");
+ }
+ }
+ LOGGER.debug(sb.toString());
+ return;
+ }
+
+ 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 (Map.Entry<String, String> entry: inputs.entrySet()) {
+ sb.append("\titem ").append(i++).append(": ").append(entry.getKey()).append("=").append(entry.getValue());
+ }
+ }
+ LOGGER.debug(sb.toString());
+ return;
+ }
+
+ private String convertNode(final JsonNode node) {
+ try {
+ final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
+ return JSON_MAPPER.writeValueAsString(obj);
+ } catch (JsonParseException jpe) {
+ LOGGER.debug("Error converting json to string " + jpe.getMessage(),jpe);
+ } catch (Exception e) {
+ LOGGER.debug("Error converting json to string " + e.getMessage(),e);
+ }
+ return "[Error converting json to string]";
+ }
+
+ private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
+ if (objectMap == null) {
+ return null;
+ }
+ Map<String, String> stringMap = new HashMap<>();
+ for (String key : objectMap.keySet()) {
+ if (!stringMap.containsKey(key)) {
+ Object obj = objectMap.get(key);
+ if (obj instanceof String) {
+ stringMap.put(key, (String) objectMap.get(key));
+ } else if (obj instanceof JsonNode ){
+ // This is a bit of mess - but I think it's the least impacting
+ // let's convert it BACK to a string - then it will get converted back later
+ try {
+ String str = this.convertNode((JsonNode) obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key,e);
+ //okay in this instance - only string values (fqdn) are expected to be needed
+ }
+ } else if (obj instanceof java.util.LinkedHashMap) {
+ LOGGER.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
+ try {
+ String str = JSON_MAPPER.writeValueAsString(obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key,e);
+ }
+ } else if (obj instanceof Integer) {
+ try {
+ String str = "" + obj;
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key,e);
+ }
+ } else {
+ try {
+ String str = obj.toString();
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")",e);
+ }
+ }
+ }
+ }
+
+ return stringMap;
+ }
+
+ @Override
+ public void createVfModule(String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ String baseVfHeatStackId,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ Boolean enableBridge,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ String vfModuleName = vnfName;
+ String vfModuleType = vnfType;
+ String vfVersion = vnfVersion;
+ String mcu = modelCustomizationUuid;
+ boolean useMCUuid = false;
+ if (mcu != null && !mcu.isEmpty()) {
+ if ("null".equalsIgnoreCase(mcu)) {
+ LOGGER.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: " + modelCustomizationUuid);
+ useMCUuid = false;
+ mcu = "";
+ } else {
+ LOGGER.debug("Found modelCustomizationUuid! Will use that: " + mcu);
+ useMCUuid = true;
+ }
+ }
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateVfModule");
+ String requestTypeString = "";
+ if (requestType != null && !"".equals(requestType)) {
+ requestTypeString = requestType;
+ }
+ String nestedStackId = null;
+ if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
+ nestedStackId = volumeGroupHeatStackId;
+ }
+ String nestedBaseStackId = null;
+ if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
+ nestedBaseStackId = baseVfHeatStackId;
+ }
+
+ if (inputs == null) {
+ // Create an empty set of inputs
+ inputs = new HashMap<>();
+ 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);
+ vfRollback.setModelCustomizationUuid(mcu);
+
+ // Put data into A&AI through Heatstack
+ if(enableBridge != null && enableBridge) {
+ callHeatbridge(baseVfHeatStackId);
+ }
+
+ 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 ();
+ Map<String, Object> nestedVolumeOutputs = null;
+ 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 *later*");
+ //this.sendMapToDebug(inputs);
+ nestedVolumeOutputs = nestedHeatStack.getOutputs();
+ this.sendMapToDebug(nestedVolumeOutputs, "volumeStackOutputs");
+ //TODO
+ //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 ();
+ Map<String, Object> baseStackOutputs = null;
+ 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 - these values will be copied to inputs *later*");
+ //this.sendMapToDebug(inputs);
+ baseStackOutputs = nestedBaseHeatStack.getOutputs();
+ this.sendMapToDebug(baseStackOutputs, "baseStackOutputs");
+ //TODO
+ //heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
+ //this.sendMapToDebug(inputs);
+ }
+ }
+
+ // Ready to deploy the new VNF
+
+
+
+ try {
+ // Retrieve the VF
+ VfModule vf = null;
+ VnfResource vnfResource = null;
+ VfModuleCustomization vfmc = null;
+ LOGGER.debug("version: " + vfVersion);
+ if (useMCUuid) {
+ // 1707 - db refactoring
+ vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(mcu);
+ if(vfmc != null)
+ vf=vfmc.getVfModule();
+ else
+ vf=null;
+
+ // 1702 - this will be the new way going forward. We find the vf by mcu - otherwise, code is the same.
+ if (vf == null) {
+ LOGGER.debug("Unable to find vfModuleCust with modelCustomizationUuid=" + mcu);
+ String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + mcu;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module ModelCustomizationUuid", modelCustomizationUuid, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VF Module: Unable to find vfModule with modelCustomizationUuid=" + mcu);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found vfModuleCust entry " + vfmc.toString());
+ }
+ if (vf.getIsBase()) {
+ 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 { // This is to support gamma only - get info from vnf_resource table
+ if (vfVersion != null && !vfVersion.isEmpty()) {
+ vnfResource = vnfResourceRepo.findByModelNameAndModelVersion(vnfType, vnfVersion);
+ } else {
+ vnfResource = vnfResourceRepo.findByModelName(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 && vf.getVnfResources() != null) {
+ vnfResource = vf.getVnfResources();
+ if (vnfResource == null) {
+ LOGGER.debug("Unable to find vnfResource 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",e);
+ minVersionVnf = null;
+ maxVersionVnf = null;
+ }
+ if (minVersionVnf != null && "".equals(minVersionVnf)) {
+ minVersionVnf = null;
+ }
+ if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
+ maxVersionVnf = null;
+ }
+ }
+ if (minVersionVnf != null && maxVersionVnf != null) {
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+
+ // double check
+ if (this.cloudConfig != null) {
+ Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
+ if (cloudSiteOpt.isPresent()) {
+ aicV.setVersion(cloudSiteOpt.get().getAicVersion());
+ // Add code to handle unexpected values in here
+ boolean moreThanMin = true;
+ boolean equalToMin = true;
+ boolean moreThanMax = true;
+ boolean equalToMax = true;
+ boolean doNotTest = false;
+ try {
+ moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
+ equalToMin = aicV.isTheSameVersion(minVersionVnf);
+ moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
+ equalToMax = aicV.isTheSameVersion(maxVersionVnf);
+ } catch (Exception e) {
+ LOGGER.debug("An exception occured while trying to test AIC Version " + e.getMessage() + " - will default to not check",e);
+ doNotTest = true;
+ }
+ if (!doNotTest) {
+ if ((moreThanMin || equalToMin) // aic >= min
+ && (equalToMax || !(moreThanMax))) { //aic <= max
+ LOGGER.debug("VNF Resource " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getAicVersion());
+ } else {
+ // ERROR
+ String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getAicVersion();
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
+ LOGGER.debug(error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ } else {
+ LOGGER.debug("bypassing testing AIC version...");
+ }
+ } // 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;
+
+
+
+ // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
+ HeatTemplate heatTemplate = null;
+ HeatEnvironment heatEnvironment = null;
+ if (oldWay) {
+ //This will handle old Gamma BrocadeVCE VNF
+ heatTemplate = vnfResource.getHeatTemplates();
+ }
+ else {
+ if (vf != null) {
+ if (isVolumeRequest) {
+ heatTemplate = vf.getVolumeHeatTemplate();
+ heatEnvironment = vfmc.getVolumeHeatEnv();
+ } else {
+ heatTemplate = vf.getModuleHeatTemplate();
+ heatEnvironment = vfmc.getHeatEnvironment();
+ }
+ }
+ }
+
+ if (heatTemplate == 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 {
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
+ }
+
+ if (oldWay) {
+ //This will handle old Gamma BrocadeVCE VNF
+ LOGGER.debug ("No environment parameter found for this Type " + vfModuleType);
+ } else {
+ if (heatEnvironment == null) {
+ String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", "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.getEnvironment());
+ }
+ }
+ // Replace flavors in environment with those returned by OOF
+ if (!oldWay) {
+ Map<String, Object> returnMap = updateFlavorsFromOof(heatEnvironment.getEnvironment(), inputs);
+ String heatEnvironmentString = returnMap.get("heatEnvironmentString").toString();
+ LOGGER.debug("After OOF Update Heat Env String is: " + heatEnvironmentString);
+ if (returnMap.get("inputs") instanceof Map) {
+ inputs = (Map<String, String>) returnMap.get("inputs");
+ LOGGER.debug("After OOF Update inputs are: " + inputs.toString());
+ } else {
+ LOGGER.debug("inputs is not an instance of a Map: " + returnMap.get("inputs"));
+ throw new VnfException("Updating inputs using OOF info failed.", MsoExceptionCategory.INTERNAL);
+ }
+ }
+
+ LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
+ + heatTemplate.getArtifactUuid ());
+
+
+ List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
+ Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
+ if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
+ // for debugging print them out
+ LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
+ for (HeatTemplate entry : nestedTemplates) {
+ nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
+ LOGGER.debug (entry.getTemplateName() + " -> " + entry.getTemplateBody());
+ }
+ } else {
+ LOGGER.debug ("No nested templates found - nothing to do here");
+ nestedTemplatesChecked = null;
+ }
+
+ // 1510 - Also add the files: for any get_files associated with this vnf_resource_id
+ // *if* there are any
+ List<HeatFiles> heatFiles = null;
+
+ Map<String, Object> heatFilesObjects = new HashMap<>();
+
+ // Add ability to turn on adding get_files with volume requests (by property).
+ boolean addGetFilesOnVolumeReq = false;
+ try {
+ String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
+ 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, this should not happen - old way is gamma only - no heat files!");
+ } else {
+ // 1607 - now use VF_MODULE_TO_HEAT_FILES table
+ LOGGER.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
+ + vf.getModelUUID());
+ heatFiles = vf.getHeatFiles();
+ }
+ if (heatFiles != null && !heatFiles.isEmpty()) {
+ // 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(HeatFiles heatfile : heatFiles){
+ LOGGER.debug(heatfile.getFileName() + " -> "
+ + heatfile.getFileBody());
+ heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
+ }
+ } 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 <> ();
+
+ // 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 checkRequiredParameters = true;
+ try {
+ String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
+ 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 (heatEnvironment != null && heatEnvironment.getEnvironment() != null && heatEnvironment.getEnvironment().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");
+ StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
+ //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 with 1707 - all variables converted to their native object types
+ Map<String, Object> goldenInputs = null;
+
+ LOGGER.debug("Now handle the inputs....first convert");
+ ArrayList<String> parameterNames = new ArrayList<>();
+ HashMap<String, String> aliasToParam = new HashMap<>();
+ StringBuilder sb = new StringBuilder("\nTemplate Parameters:\n");
+ int cntr = 0;
+ try {
+ for (HeatTemplateParam htp : heatTemplate.getParameters()) {
+ sb.append("param[" + cntr++ + "]=" + htp.getParamName());
+ parameterNames.add(htp.getParamName());
+ if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) {
+ aliasToParam.put(htp.getParamAlias(), htp.getParamName());
+ sb.append(" ** (alias=" + htp.getParamAlias() + ")");
+ }
+ sb.append("\n");
+ }
+ LOGGER.debug(sb.toString());
+ } catch (Exception e) {
+ LOGGER.debug("??An exception occurred trying to go through Parameter Names " + e.getMessage(),e);
+ }
+ // Step 1 - convert what we got as inputs (Map<String, String>) to a
+ // Map<String, Object> - where the object matches the param type identified in the template
+ // This will also not copy over params that aren't identified in the template
+ goldenInputs = heat.convertInputMap(inputs, heatTemplate);
+ // Step 2 - now simply add the outputs as we received them - no need to convert to string
+ LOGGER.debug("Now add in the base stack outputs if applicable");
+ heat.copyBaseOutputsToInputs(goldenInputs, baseStackOutputs, parameterNames, aliasToParam);
+ // Step 3 - add the volume inputs if any
+ LOGGER.debug("Now add in the volume stack outputs if applicable");
+ heat.copyBaseOutputsToInputs(goldenInputs, nestedVolumeOutputs, parameterNames, aliasToParam);
+ this.sendMapToDebug(goldenInputs, "Final inputs sent to openstack");
+
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ LOGGER.debug ("Parameter:'" + parm.getParamName ()
+ + "', isRequired="
+ + parm.isRequired ()
+ + ", alias="
+ + parm.getParamAlias ());
+
+ if (parm.isRequired () && (goldenInputs == null || !goldenInputs.containsKey (parm.getParamName ()))) {
+ // The check for an alias was moved to the method in MsoHeatUtils - when we converted the Map<String, String> to Map<String, Object>
+ LOGGER.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...check environment");
+ 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");
+ }
+ // We can now remove the recreating of the ENV with only legit params - that check is done for us,
+ // and it causes problems with json that has arrays
+ String newEnvironmentString = null;
+ if (mhee != null) {
+ newEnvironmentString = mhee.getRawEntry().toString();
+ }
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ // Valet - 1806
+ boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
+ boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
+ LOGGER.debug("isValetEnabled=" + isValetEnabled + ", failRequestsOnValetFailure=" + failRequestOnValetFailure);
+ if (oldWay || isVolumeRequest) {
+ isValetEnabled = false;
+ LOGGER.debug("do not send to valet for volume requests or brocade");
+ }
+ boolean sendResponseToValet = false;
+ if (isValetEnabled) {
+ Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
+ sendResponseToValet = this.valetCreateRequest(cloudSiteId, tenantId, heatFilesObjects,
+ nestedTemplatesChecked, vfModuleName, backout, heatTemplate, newEnvironmentString, goldenInputs,
+ msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
+ if (sendResponseToValet) {
+ goldenInputs = valetModifiedParamsHolder.value;
+ }
+ }
+
+ // 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!!");
+
+ heatStack = heat.createStack (cloudSiteId,
+ tenantId,
+ vfModuleName,
+ template,
+ goldenInputs,
+ true,
+ heatTemplate.getTimeoutMinutes(),
+ newEnvironmentString,
+ nestedTemplatesChecked,
+ heatFilesObjects,
+ backout.booleanValue());
+ }
+ else {
+ LOGGER.debug("heat is null!");
+ throw new MsoHeatNotFoundException();
+ }
+ 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);
+ if (isValetEnabled && sendResponseToValet) {
+ LOGGER.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
+ try {
+ GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, backout, me.getMessage());
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Rollback response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Rollback to Valet ", e);
+ }
+ }
+ 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",e);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating stack with OpenStack");
+ throw new VnfException("Exception during heat.createStack! " + 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;
+ if (isValetEnabled && sendResponseToValet) {
+ LOGGER.debug("valet is enabled, the orchestration succeeded - now send confirm to valet with stack id");
+ try {
+ GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Confirm response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Confirm to Valet ", e);
+ }
+ }
+ LOGGER.debug ("VF Module " + vfModuleName + " successfully created");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module");
+ return;
+ } catch (Exception e) {
+ LOGGER.debug("unhandled exception in create VF",e);
+ throw new VnfException("Exception during create VF " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void deleteVfModule (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs) 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 ();
+
+ // 1702 capture the output parameters on a delete
+ // so we'll need to query first
+ Map<String, Object> stackOutputs = null;
+ try {
+ stackOutputs = heat.queryStackForOutputs(cloudSiteId, tenantId, vnfName);
+ } catch (MsoException me) {
+ // Failed to query the Stack due to an openstack exception.
+ // Convert to a generic VnfException
+ me.addContext ("DeleteVFModule");
+ String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (startTime, 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 - QueryStack", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
+ outputs.value = this.convertMapStringObjectToStringString(stackOutputs);
+
+ boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
+ boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
+ LOGGER.debug("isValetEnabled=" + isValetEnabled + ", failRequestsOnValetFailure=" + failRequestOnValetFailure);
+ boolean valetDeleteRequestSucceeded = false;
+ if (isValetEnabled) {
+ valetDeleteRequestSucceeded = this.valetDeleteRequest(cloudSiteId, tenantId, vnfName, msoRequest, failRequestOnValetFailure);
+ }
+
+ // 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);
+ if (isValetEnabled && valetDeleteRequestSucceeded) {
+ LOGGER.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
+ try {
+ GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), vnfName, false, me.getMessage());
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Rollback response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Rollback to Valet ", e);
+ }
+ }
+ throw new VnfException (me);
+ }
+ if (isValetEnabled && valetDeleteRequestSucceeded) {
+ // only if the original request succeeded do we send a confirm
+ LOGGER.debug("valet is enabled, the delete succeeded - now send confirm to valet");
+ try {
+ GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), vnfName);
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Confirm response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Confirm to Valet ", e);
+ }
+ }
+
+ // 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,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException {
+ String vfModuleName = vnfName;
+ String vfModuleType = vnfType;
+ String methodName = "updateVfModule";
+ MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
+ String serviceName = VNF_ADAPTER_SERVICE_NAME + methodName;
+ MsoLogger.setServiceName (serviceName);
+
+ StringBuilder sbInit = new StringBuilder();
+ sbInit.append("updateVfModule: \n");
+ sbInit.append("cloudSiteId=" + cloudSiteId + "\n");
+ sbInit.append("tenantId=" + tenantId + "\n");
+ sbInit.append("vnfType=" + vnfType + "\n");
+ sbInit.append("vnfVersion=" + vnfVersion + "\n");
+ sbInit.append("vnfName=" + vnfName + "\n");
+ sbInit.append("requestType=" + requestType + "\n");
+ sbInit.append("volumeGroupHeatStackId=" + volumeGroupHeatStackId + "\n");
+ sbInit.append("baseVfHeatStackId=" + baseVfHeatStackId + "\n");
+ sbInit.append("vfModuleStackId=" + vfModuleStackId + "\n");
+ sbInit.append("modelCustomizationUuid=" + modelCustomizationUuid + "\n");
+ LOGGER.debug(sbInit.toString());
+
+ String mcu = modelCustomizationUuid;
+ boolean useMCUuid = false;
+ if (mcu != null && !mcu.isEmpty()) {
+ if (mcu.equalsIgnoreCase("null")) {
+ LOGGER.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: " + modelCustomizationUuid);
+ useMCUuid = false;
+ mcu = "";
+ } else {
+ LOGGER.debug("Found modelCustomizationUuid! Will use that: " + mcu);
+ useMCUuid = true;
+ }
+ }
+
+ String requestTypeString = "";
+ if (requestType != null && !"".equals(requestType)) {
+ requestTypeString = requestType;
+ }
+
+ String nestedStackId = null;
+ if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
+ nestedStackId = volumeGroupHeatStackId;
+ }
+ String nestedBaseStackId = null;
+ if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
+ nestedBaseStackId = baseVfHeatStackId;
+ }
+
+ if (inputs == null) {
+ // Create an empty set of inputs
+ inputs = new HashMap<>();
+ 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 || "".equals(vfModuleName.trim())) && vfModuleStackId != null) {
+ vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
+ }
+
+ LOGGER.debug ("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudSiteId + "/" + tenantId);
+ LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedVolumeStackId = " + 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);
+ vfRollback.setModelCustomizationUuid(mcu);
+
+ 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 ();
+ Map<String, Object> nestedVolumeOutputs = null;
+ 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 *later*");
+ nestedVolumeOutputs = nestedHeatStack.getOutputs();
+ //this.sendMapToDebug(inputs);
+ this.sendMapToDebug(nestedVolumeOutputs, "volumeStackOutputs");
+ //TODO
+ 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;
+ Map<String, Object> baseStackOutputs = 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 *later*");
+ baseStackOutputs = nestedBaseHeatStack.getOutputs();
+ //this.sendMapToDebug(inputs);
+ this.sendMapToDebug(baseStackOutputs, "baseStackOutputs");
+ //TODO
+ heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
+ //this.sendMapToDebug(inputs);
+ }
+ }
+
+ // Ready to deploy the new VNF
+
+
+
+ // Retrieve the VF definition
+ VnfResource vnfResource = null;
+ VfModule vf = null;
+ VfModuleCustomization vfmc = null;
+ if (useMCUuid){
+ vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
+ vf = vfmc != null ? vfmc.getVfModule() : null;
+ if (vf == null) {
+ LOGGER.debug("Unable to find a vfModule matching modelCustomizationUuid=" + mcu);
+ }
+ } else {
+ LOGGER.debug("1707 and later - MUST PROVIDE Model Customization UUID!");
+ }
+ if (vf == null) {
+ String error = "Update VfModule: unable to find vfModule with modelCustomizationUuid=" + mcu;
+ 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 ());
+ if (vf.getIsBase()) {
+ isBaseRequest = true;
+ LOGGER.debug("This a BASE update request");
+ } else {
+ LOGGER.debug("This is *not* a BASE VF update request");
+ if (!isVolumeRequest && nestedBaseStackId == null) {
+ LOGGER.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
+ }
+ }
+
+ //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 (vf.getModelUUID() != null) {
+ String vnfResourceModelUuid = vf.getModelUUID();
+
+ vnfResource = vf.getVnfResources();
+ if (vnfResource == null) {
+ LOGGER.debug("Unable to find vnfResource at " + vnfResourceModelUuid + " 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",e);
+ minVersionVnf = null;
+ maxVersionVnf = null;
+ }
+ if (minVersionVnf != null && "".equals(minVersionVnf)) {
+ minVersionVnf = null;
+ }
+ if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
+ maxVersionVnf = null;
+ }
+ }
+ if (minVersionVnf != null && maxVersionVnf != null) {
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+
+ // double check
+ if (this.cloudConfig != null) {
+ Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
+ if (cloudSiteOpt.isPresent()) {
+ aicV.setVersion(cloudSiteOpt.get().getAicVersion());
+ boolean moreThanMin = true;
+ boolean equalToMin = true;
+ boolean moreThanMax = true;
+ boolean equalToMax = true;
+ boolean doNotTest = false;
+ try {
+ moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
+ equalToMin = aicV.isTheSameVersion(minVersionVnf);
+ moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
+ equalToMax = aicV.isTheSameVersion(maxVersionVnf);
+ } catch (Exception e) {
+ LOGGER.debug("An exception occured while trying to test AIC Version " + e.getMessage()
+ + " - will default to not check", e);
+ doNotTest = true;
+ }
+ if (!doNotTest) {
+ if ((moreThanMin || equalToMin) // aic >= min
+ && ((equalToMax) || !(moreThanMax))) { // aic <= max
+ LOGGER.debug("VNF Resource " + vnfResource.getModelName() + " VersionMin=" + minVersionVnf
+ + " VersionMax:" + maxVersionVnf + " supported on Cloud: " + cloudSiteId
+ + " with AIC_Version:" + aicV);
+ } else {
+ // ERROR
+ String error = "VNF Resource type: " + vnfResource.getModelName() + " VersionMin="
+ + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: "
+ + cloudSiteId + " with AIC_Version:" + aicV;
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
+ MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
+ LOGGER.debug(error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ } else {
+ LOGGER.debug("bypassing testing AIC version...");
+ }
+ } // 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 - do not error for now - not checked.");
+ }
+ // End Version check 1607
+
+ HeatTemplate heatTemplate = null;
+ HeatEnvironment heatEnvironment = null;
+ if (isVolumeRequest) {
+ heatTemplate = vf.getVolumeHeatTemplate();
+ heatEnvironment = vfmc.getVolumeHeatEnv();
+ } else {
+ heatTemplate = vf.getModuleHeatTemplate();
+ heatEnvironment = vfmc.getHeatEnvironment();
+ }
+
+ if (heatTemplate == 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 {
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
+ }
+
+ if (heatEnvironment == null) {
+ String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", "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.getEnvironment());
+ }
+
+ LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
+ + heatTemplate.getArtifactUuid ());
+
+
+ List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
+ Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
+ if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
+ // for debugging print them out
+ LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
+ for (HeatTemplate entry : nestedTemplates) {
+
+ nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
+ LOGGER.debug (entry.getTemplateName() + " -> " + entry.getTemplateBody());
+ }
+ } 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.getModelUUID());
+
+ List<HeatFiles> heatFiles = null;
+ Map <String, Object> heatFilesObjects = new HashMap <> ();
+
+ // Add ability to turn on adding get_files with volume requests (by property).
+ boolean addGetFilesOnVolumeReq = false;
+ try {
+ String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
+ 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) {
+ LOGGER.debug("In MsoVnfAdapterImpl updateVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
+ + vf.getModelUUID());
+
+ heatFiles = vf.getHeatFiles();
+ if (heatFiles != null && !heatFiles.isEmpty()) {
+ // 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(HeatFiles heatfile : heatFiles){
+ LOGGER.debug(heatfile.getFileName() + " -> "
+ + heatfile.getFileBody());
+ heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
+ }
+ } 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 <> ();
+
+ // 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 checkRequiredParameters = true;
+ try {
+ String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
+ 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 (heatEnvironment != null && heatEnvironment.getEnvironment().toLowerCase ().contains ("parameters:")) {
+ LOGGER.debug("Enhanced environment checking enabled - 1604");
+ StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
+ 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<>();
+ 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 || "".equals(parameterType.trim())) {
+ parameterType = "String";
+ }
+ JsonNode jsonNode = null;
+ if ("json".equalsIgnoreCase(parameterType) && 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,jpe);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(),e);
+ 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,jpe);
+ hasJson = false;
+ jsonNode = null;
+ } catch (Exception e) {
+ // or here?
+ LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(),e);
+ 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");
+ }
+
+ // Just submit the envt entry as received from the database
+ String newEnvironmentString = null;
+ if (mhee != null) {
+ newEnvironmentString = mhee.getRawEntry().toString();
+ }
+ // Remove any extraneous parameters (don't throw an error)
+ if (inputs != null) {
+ List <String> extraParams = new ArrayList <> ();
+ 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);
+ }
+ }
+ Map<String, Object> goldenInputs = copyStringInputs(inputs);
+ // 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<>();
+ for (Map.Entry<String, String> entry : inputs.entrySet()) {
+ String keyParamName = entry.getKey();
+ String value = entry.getValue();
+ if (jsonParams.containsKey(keyParamName)) {
+ inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
+ } else {
+ inputsTwo.put(keyParamName, value);
+ }
+ }
+ goldenInputs = inputsTwo;
+ }
+
+ // "Fix" the template if it has CR/LF (getting this from Oracle)
+ String template = heatTemplate.getHeatTemplate ();
+ template = template.replaceAll ("\r\n", "\n");
+
+ boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
+ boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
+ LOGGER.debug("isValetEnabled=" + isValetEnabled + ", failRequestsOnValetFailure=" + failRequestOnValetFailure);
+ if (isVolumeRequest) {
+ isValetEnabled = false;
+ LOGGER.debug("never send a volume request to valet");
+ }
+ boolean sendResponseToValet = false;
+ if (isValetEnabled) {
+ Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
+ String parsedVfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
+ // Make sure it is set to something.
+ if (parsedVfModuleName == null || parsedVfModuleName.isEmpty()) {
+ parsedVfModuleName = "unknown";
+ }
+ sendResponseToValet = this.valetUpdateRequest(cloudSiteId, tenantId, heatFilesObjects,
+ nestedTemplatesChecked, parsedVfModuleName, false, heatTemplate, newEnvironmentString, (HashMap<String, Object>) goldenInputs,
+ msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
+ if (sendResponseToValet) {
+ goldenInputs = valetModifiedParamsHolder.value;
+ }
+ }
+
+ // 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,
+ vfModuleName,
+ template,
+ goldenInputs,
+ 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);
+ if (isValetEnabled && sendResponseToValet) {
+ LOGGER.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
+ try {
+ GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, false, me.getMessage());
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Rollback response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Rollback to Valet ", e);
+ }
+ }
+ 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);
+
+ if (isValetEnabled && sendResponseToValet) {
+ LOGGER.debug("valet is enabled, the update succeeded - now send confirm to valet with stack id");
+ try {
+ GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
+ // Nothing to really do here whether it succeeded or not other than log it.
+ LOGGER.debug("Return code from Confirm response is " + gvr.getStatusCode());
+ } catch (Exception e) {
+ LOGGER.error("Exception encountered while sending Confirm to Valet ", e);
+ }
+ }
+
+ 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) {
+ LOGGER.debug("Exception", e);
+ vfModuleName = null;
+ }
+ return vfModuleName;
+ }
+
+ private Map<String, Object> updateFlavorsFromOof(String heatEnvironmentString, Map<String, String> inputs) {
+ Map<String, Object> returnMap = new HashMap<>();
+ for (Map.Entry<String, String> input : inputs.entrySet()){
+ if (heatEnvironmentString.contains("label_" + input.getKey())){
+ heatEnvironmentString = heatEnvironmentString.replace("label_" + input.getKey(),
+ input.getValue());
+ inputs.remove("label_" + input.getKey());
+ }
+ }
+ returnMap.put("heatEnvironmentString", heatEnvironmentString);
+ returnMap.put("inputs", inputs);
+ return returnMap;
+ }
+ /*
+ * Helper method to check a boolean property value - on error return provided default
+ */
+ private boolean checkBooleanProperty(String propertyName, boolean defaultValue) {
+ boolean property = defaultValue;
+ try {
+ String propertyString = this.environment.getProperty(propertyName);
+ if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
+ property = true;
+ } else if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
+ property = false;
+ }
+ } catch (Exception e) {
+ LOGGER.debug ("An exception occured trying to get property " + propertyName + " - defaulting to " + defaultValue, e);
+ property = defaultValue;
+ }
+ return property;
+ }
+
+ /*
+ * Helper method to combine getFiles and nestedTemplates in to a single Map
+ */
+ private Map<String, Object> combineGetFilesAndNestedTemplates(Map<String, Object> getFiles, Map<String, Object> nestedTemplates) {
+ boolean haveGetFiles = true;
+ boolean haveNestedTemplates = true;
+ Map<String, Object> files = new HashMap<String, Object>();
+ if (getFiles == null || getFiles.isEmpty()) {
+ haveGetFiles = false;
+ }
+ if (nestedTemplates == null || nestedTemplates.isEmpty()) {
+ haveNestedTemplates = false;
+ }
+ if (haveGetFiles && haveNestedTemplates) {
+ for (String keyString : getFiles.keySet ()) {
+ files.put (keyString, getFiles.get (keyString));
+ }
+ for (String keyString : nestedTemplates.keySet ()) {
+ files.put (keyString, nestedTemplates.get (keyString));
+ }
+ } else {
+ // Handle if we only have one or neither:
+ if (haveGetFiles) {
+ files = getFiles;
+ }
+ if (haveNestedTemplates) {
+ files = nestedTemplates;
+ }
+ }
+ return files;
+ }
+
+ /*
+ * Valet Create request
+ */
+ private boolean valetCreateRequest(String cloudSiteId, String tenantId, Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked,
+ String vfModuleName, boolean backout, HeatTemplate heatTemplate, String newEnvironmentString, Map<String, Object> goldenInputs,
+ MsoRequest msoRequest, Map<String, String> inputs, boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
+ boolean valetSucceeded = false;
+ String valetErrorMessage = "more detail not available";
+ try {
+ String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
+ Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
+ nestedTemplatesChecked);
+ HeatRequest heatRequest = new HeatRequest(vfModuleName, backout, heatTemplate.getTimeoutMinutes(),
+ heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
+ GenericValetResponse<ValetCreateResponse> createReq = this.vci.callValetCreateRequest(msoRequest.getRequestId(),
+ cloudSiteId, tenantId, msoRequest.getServiceInstanceId(), inputs.get("vnf_id"),
+ inputs.get("vnf_name"), inputs.get("vf_module_id"), inputs.get("vf_module_name"), keystoneUrl,
+ heatRequest);
+ ValetCreateResponse vcr = createReq.getReturnObject();
+ if (vcr != null && createReq.getStatusCode() == 200) {
+ ValetStatus status = vcr.getStatus();
+ if (status != null) {
+ String statusCode = status.getStatus(); // "ok" or "failed"
+ if ("ok".equalsIgnoreCase(statusCode)) {
+ Map<String, Object> newInputs = vcr.getParameters();
+ if (newInputs != null) {
+ Map<String, Object> oldGold = goldenInputs;
+ LOGGER.debug("parameters before being modified by valet:" + oldGold.toString());
+ goldenInputs = new HashMap<String, Object>();
+ for (String key : newInputs.keySet()) {
+ goldenInputs.put(key, newInputs.get(key));
+ }
+ valetModifiedParamsHolder.value = goldenInputs;
+ LOGGER.debug("parameters after being modified by valet:" + goldenInputs.toString());
+ valetSucceeded = true;
+ }
+ } else {
+ valetErrorMessage = status.getMessage();
+ }
+ }
+ } else {
+ LOGGER.debug("Got a bad response back from valet");
+ valetErrorMessage = "Bad response back from Valet";
+ valetSucceeded = false;
+ }
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred trying to call valet ...", e);
+ valetSucceeded = false;
+ valetErrorMessage = e.getMessage();
+ }
+ if (failRequestOnValetFailure && !valetSucceeded) {
+ // The valet request failed - and property says to fail the request
+ //TODO Create a new exception class for valet?
+ throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
+ }
+ return valetSucceeded;
+ }
+
+ /*
+ * Valet update request
+ */
+
+ private boolean valetUpdateRequest(String cloudSiteId, String tenantId,
+ Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked, String vfModuleName,
+ boolean backout, HeatTemplate heatTemplate, String newEnvironmentString,
+ Map<String, Object> goldenInputs, MsoRequest msoRequest, Map<String, String> inputs,
+ boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
+
+ boolean valetSucceeded = false;
+ String valetErrorMessage = "more detail not available";
+ try {
+ String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
+ Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
+ nestedTemplatesChecked);
+ HeatRequest heatRequest = new HeatRequest(vfModuleName, false, heatTemplate.getTimeoutMinutes(),
+ heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
+ // vnf name is not sent to MSO on update requests - so we will set it to the vf module name for now
+ GenericValetResponse<ValetUpdateResponse> updateReq = this.vci.callValetUpdateRequest(msoRequest.getRequestId(),
+ cloudSiteId, tenantId, msoRequest.getServiceInstanceId(), inputs.get("vnf_id"),
+ vfModuleName, inputs.get("vf_module_id"), vfModuleName, keystoneUrl,
+ heatRequest);
+ ValetUpdateResponse vur = updateReq.getReturnObject();
+ if (vur != null && updateReq.getStatusCode() == 200) {
+ ValetStatus status = vur.getStatus();
+ if (status != null) {
+ String statusCode = status.getStatus(); // "ok" or "failed"
+ if ("ok".equalsIgnoreCase(statusCode)) {
+ Map<String, Object> newInputs = vur.getParameters();
+ if (newInputs != null) {
+ Map<String, Object> oldGold = goldenInputs;
+ LOGGER.debug("parameters before being modified by valet:" + oldGold.toString());
+ goldenInputs = new HashMap<String, Object>();
+ for (String key : newInputs.keySet()) {
+ goldenInputs.put(key, newInputs.get(key));
+ }
+ valetModifiedParamsHolder.value = goldenInputs;
+ LOGGER.debug("parameters after being modified by valet:" + goldenInputs.toString());
+ valetSucceeded = true;
+ }
+ } else {
+ valetErrorMessage = status.getMessage();
+ }
+ }
+ } else {
+ LOGGER.debug("Got a bad response back from valet");
+ valetErrorMessage = "Got a bad response back from valet";
+ valetSucceeded = false;
+ }
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred trying to call valet - will continue processing for now...", e);
+ valetErrorMessage = e.getMessage();
+ valetSucceeded = false;
+ }
+ if (failRequestOnValetFailure && !valetSucceeded) {
+ // The valet request failed - and property says to fail the request
+ // TODO Create a new exception class for valet?
+ throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
+ }
+ return valetSucceeded;
+ }
+
+ /*
+ * Valet delete request
+ */
+ private boolean valetDeleteRequest(String cloudSiteId, String tenantId, String vnfName,
+ MsoRequest msoRequest, boolean failRequestOnValetFailure) {
+ boolean valetDeleteRequestSucceeded = false;
+ String valetErrorMessage = "more detail not available";
+ try {
+ String vfModuleId = vnfName;
+ String vfModuleName = vnfName;
+ try {
+ vfModuleName = vnfName.substring(0, vnfName.indexOf('/'));
+ vfModuleId = vnfName.substring(vnfName.indexOf('/') + 1);
+ } catch (Exception e) {
+ // do nothing - send what we got for vnfName for both to valet
+ }
+ GenericValetResponse<ValetDeleteResponse> deleteReq = this.vci.callValetDeleteRequest(msoRequest.getRequestId(),
+ cloudSiteId, tenantId, vfModuleId, vfModuleName);
+ ValetDeleteResponse vdr = deleteReq.getReturnObject();
+ if (vdr != null && deleteReq.getStatusCode() == 200) {
+ ValetStatus status = vdr.getStatus();
+ if (status != null) {
+ String statusCode = status.getStatus(); // "ok" or "failed"
+ if ("ok".equalsIgnoreCase(statusCode)) {
+ LOGGER.debug("delete request to valet returned success");
+ valetDeleteRequestSucceeded = true;
+ } else {
+ LOGGER.debug("delete request to valet returned failure");
+ valetDeleteRequestSucceeded = false;
+ valetErrorMessage = status.getMessage();
+ }
+ }
+ } else {
+ LOGGER.debug("Got a bad response back from valet - delete request failed");
+ valetDeleteRequestSucceeded = false;
+ valetErrorMessage = "Got a bad response back from valet - delete request failed";
+ }
+ } catch (Exception e) {
+ LOGGER.error("An exception occurred trying to call valet - valetDeleteRequest failed", e);
+ valetDeleteRequestSucceeded = false;
+ valetErrorMessage = e.getMessage();
+ }
+ if (valetDeleteRequestSucceeded == false && failRequestOnValetFailure == true) {
+ LOGGER.error("ValetDeleteRequestFailed - del req still will be sent to openstack", new VnfException("ValetDeleteRequestFailedError"));
+ }
+ return valetDeleteRequestSucceeded;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfCloudifyAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfCloudifyAdapterImpl.java
new file mode 100644
index 0000000000..0266e87523
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfCloudifyAdapterImpl.java
@@ -0,0 +1,1218 @@
+/*-
+ * ============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.onap.so.adapters.vnf;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.CloudSite;
+import org.onap.so.cloudify.beans.DeploymentInfo;
+import org.onap.so.cloudify.beans.DeploymentStatus;
+import org.onap.so.cloudify.exceptions.MsoCloudifyManagerNotFound;
+import org.onap.so.cloudify.utils.MsoCloudifyUtils;
+import org.onap.so.db.catalog.beans.HeatEnvironment;
+import org.onap.so.db.catalog.beans.HeatFiles;
+import org.onap.so.db.catalog.beans.HeatTemplate;
+import org.onap.so.db.catalog.beans.HeatTemplateParam;
+import org.onap.so.db.catalog.beans.VfModule;
+import org.onap.so.db.catalog.beans.VfModuleCustomization;
+import org.onap.so.db.catalog.beans.VnfResource;
+import org.onap.so.db.catalog.data.repository.VFModuleCustomizationRepository;
+import org.onap.so.db.catalog.utils.MavenLikeVersioning;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.MsoTenant;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
+import org.onap.so.openstack.utils.MsoHeatEnvironmentParameter;
+import org.onap.so.openstack.utils.MsoKeystoneUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Transactional
+@WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf")
+public class MsoVnfCloudifyAdapterImpl implements MsoVnfAdapter {
+
+ 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, MsoVnfCloudifyAdapterImpl.class);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
+ private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.onap.so.adapters.vnf.addGetFilesOnVolumeReq";
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+
+ @Autowired
+ protected CloudConfig cloudConfig;
+
+ @Autowired
+ private VFModuleCustomizationRepository vfModuleCustomRepo;
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ protected MsoKeystoneUtils keystoneUtils;
+
+ @Autowired
+ protected MsoCloudifyUtils cloudifyUtils;
+ /**
+ * 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 Cloudify Adapter");
+ }
+
+ /**
+ * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
+ * @see MsoVnfCloudifyAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
+ */
+ public MsoVnfCloudifyAdapterImpl() {
+
+ }
+
+ /**
+ * This is the "Create VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @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,
+ Boolean enableBridge,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback)
+ throws VnfException
+ {
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("CreateVNF command attempted but not supported");
+ throw new VnfException ("CreateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * This is the "Update VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @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
+ {
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("UpdateVNF command attempted but not supported");
+ throw new VnfException ("UpdateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * This is the "Query VNF" web service implementation.
+ *
+ * This really should be QueryVfModule, but nobody ever changed it.
+ *
+ * For Cloudify, this will look up a deployment by its deployment ID, which is really the same
+ * as deployment name, since it assigned by the client when a deployment is created.
+ * Also, the input cloudSiteId is used only to identify which Cloudify instance to query,
+ * and the tenantId is ignored (since that really only applies for Openstack/Heat).
+ *
+ * The method returns an indicator that the VNF exists, along with its status and outputs.
+ * The input "vnfName" will also be reflected back as its ID.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to query
+ * @param tenantId Openstack tenant identifier - ignored for Cloudify
+ * @param vnfName VNF Name (should match a deployment ID)
+ * @param msoRequest Request tracking information for logs
+ * @param vnfExists Flag reporting the result of the query
+ * @param vnfId Holder for output VNF ID
+ * @param outputs Holder for Map of VNF outputs from Cloudify deployment (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 ("QueryVnfCloudify");
+ LOGGER.debug ("Querying VNF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ long subStartTime = System.currentTimeMillis ();
+
+ DeploymentInfo deployment = null;
+
+ try {
+ deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Cloudify", "Cloudify", "QueryDeployment", vnfName);
+ }
+ catch (MsoCloudifyManagerNotFound e) {
+ // This site does not have a Cloudify Manager.
+ // This isn't an error, just means we won't find the VNF here.
+ deployment = null;
+ }
+ catch (MsoException me) {
+ // Failed to query the Deployment due to a cloudify exception.
+ // Convert to a generic VnfException
+ me.addContext ("QueryVNF");
+ String error = "Query VNF (Cloudify): " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "QueryDeployment", vnfName);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "Cloudify", "QueryVNF", MsoLogger.ErrorCode.DataError, "Exception - queryDeployment", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+
+ if (deployment != null && deployment.getStatus() != DeploymentStatus.NOTFOUND) {
+ vnfExists.value = Boolean.TRUE;
+ status.value = deploymentStatusToVnfStatus(deployment);
+ vnfId.value = deployment.getId();
+ outputs.value = copyStringOutputs (deployment.getOutputs ());
+
+ LOGGER.debug ("VNF " + vnfName + " found in Cloudify, ID = " + vnfId.value);
+ }
+ else {
+ 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");
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query VNF");
+ return;
+ }
+
+
+ /**
+ * This is the "Delete VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @Override
+ public void deleteVnf (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest) throws VnfException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteVnf");
+
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("DeleteVNF command attempted but not supported");
+ throw new VnfException ("DeleteVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * 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.
+ *
+ * TODO: This should be rollbackVfModule and/or rollbackVolumeGroup,
+ * but APIs were apparently never updated.
+ */
+ @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", MsoLogger.getServiceName());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "Rollback request content is null");
+ return;
+ }
+
+ // Don't rollback if nothing was done originally
+ if (!rollback.getVnfCreated()) {
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Rollback VF Module - nothing to roll back");
+ return;
+ }
+
+ // Get the elements of the VnfRollback object for easier access
+ String cloudSiteId = rollback.getCloudSiteId ();
+ String tenantId = rollback.getTenantId ();
+ String vfModuleId = rollback.getVfModuleStackId ();
+
+ MsoLogger.setLogContext (rollback.getMsoRequest());
+
+ LOGGER.debug ("Rolling Back VF Module " + vfModuleId + " in " + cloudSiteId + "/" + tenantId);
+
+ DeploymentInfo deployment = null;
+
+ // Use the MsoCloudifyUtils to delete the deployment. 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 {
+ // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
+ // Go directly to Keystone until APIs could be updated to supply the name.
+ MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
+ String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
+
+ // TODO: Get a reasonable timeout. Use a global property, or store the creation timeout in rollback object and use that.
+ deployment = cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantName, vfModuleId, 5);
+ LOGGER.debug("Rolled back deployment: " + deployment.getId());
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Cloudify", "Cloudify", "DeleteDeployment", null);
+ } catch (MsoException me) {
+ // Failed to rollback the VNF due to a cloudify exception.
+ // Convert to a generic VnfException
+ me.addContext ("RollbackVNF");
+ String error = "Rollback VF Module: " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "DeleteDeployment", null);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vfModuleId, cloudSiteId, tenantId, "Cloudify", "DeleteDeployment", MsoLogger.ErrorCode.DataError, "Exception - DeleteDeployment", 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 VF Module");
+ return;
+ }
+
+
+ private VnfStatus deploymentStatusToVnfStatus (DeploymentInfo deployment) {
+ // Determine the status based on last action & status
+ // DeploymentInfo object should be enhanced to report a better status internally.
+ DeploymentStatus status = deployment.getStatus();
+ String lastAction = deployment.getLastAction();
+
+ if (status == null || lastAction == null) {
+ return VnfStatus.UNKNOWN;
+ }
+ else if (status == DeploymentStatus.NOTFOUND) {
+ return VnfStatus.NOTFOUND;
+ }
+ else if (status == DeploymentStatus.INSTALLED) {
+ return VnfStatus.ACTIVE;
+ }
+ else if (status == DeploymentStatus.CREATED) {
+ // Should have an INACTIVE status for this case. Shouldn't really happen, but
+ // Install was never run, or Uninstall was done but deployment didn't get deleted.
+ return VnfStatus.UNKNOWN;
+ }
+ else if (status == DeploymentStatus.FAILED) {
+ return VnfStatus.FAILED;
+ }
+
+ 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));
+ } else if (stackOutputs.get(key) instanceof Integer) {
+ try {
+ String str = "" + stackOutputs.get(key);
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs");
+ }
+ } else if (stackOutputs.get(key) instanceof JsonNode) {
+ try {
+ String str = this.convertNode((JsonNode) stackOutputs.get(key));
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - exception converting JsonNode");
+ }
+ } else if (stackOutputs.get(key) instanceof java.util.LinkedHashMap) {
+ try {
+ String str = JSON_MAPPER.writeValueAsString(stackOutputs.get(key));
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - exception converting LinkedHashMap");
+ }
+ } else {
+ try {
+ String str = stackOutputs.get(key).toString();
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - unable to call .toString() " + e.getMessage());
+ }
+ }
+ }
+ return stringOutputs;
+ }
+
+
+ private void sendMapToDebug(Map<String, Object> inputs, String optionalName) {
+ int i = 0;
+ StringBuilder sb = new StringBuilder(optionalName == null ? "\ninputs" : "\n" + optionalName);
+ if (inputs == null) {
+ sb.append("\tNULL");
+ }
+ else if (inputs.size() < 1) {
+ sb.append("\tEMPTY");
+ } else {
+ for (String str : inputs.keySet()) {
+ String outputString;
+ try {
+ outputString = inputs.get(str).toString();
+ } catch (Exception e) {
+ outputString = "Unable to call toString() on the value for " + str;
+ }
+ sb.append("\t\nitem " + i++ + ": '" + str + "'='" + outputString + "'");
+ }
+ }
+ LOGGER.debug(sb.toString());
+ return;
+ }
+
+ 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;
+ }
+
+ private String convertNode(final JsonNode node) {
+ try {
+ final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
+ final String json = JSON_MAPPER.writeValueAsString(obj);
+ return json;
+ } catch (JsonParseException jpe) {
+ LOGGER.debug("Error converting json to string " + jpe.getMessage());
+ } catch (Exception e) {
+ LOGGER.debug("Error converting json to string " + e.getMessage());
+ }
+ return "[Error converting json to string]";
+ }
+
+ private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
+ if (objectMap == null) {
+ return null;
+ }
+ Map<String, String> stringMap = new HashMap<String, String>();
+ for (String key : objectMap.keySet()) {
+ if (!stringMap.containsKey(key)) {
+ Object obj = objectMap.get(key);
+ if (obj instanceof String) {
+ stringMap.put(key, (String) objectMap.get(key));
+ } else if (obj instanceof JsonNode ){
+ // This is a bit of mess - but I think it's the least impacting
+ // let's convert it BACK to a string - then it will get converted back later
+ try {
+ String str = this.convertNode((JsonNode) obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key);
+ //okay in this instance - only string values (fqdn) are expected to be needed
+ }
+ } else if (obj instanceof java.util.LinkedHashMap) {
+ LOGGER.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
+ try {
+ String str = JSON_MAPPER.writeValueAsString(obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key);
+ }
+ } else if (obj instanceof Integer) {
+ try {
+ String str = "" + obj;
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key);
+ }
+ } else {
+ try {
+ String str = obj.toString();
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")");
+ }
+ }
+ }
+ }
+
+ return stringMap;
+ }
+
+ /**
+ * This is the "Create VF Module" web service implementation.
+ * It will instantiate a new VF Module of the requested type in the specified cloud
+ * and tenant. The tenant must exist before this service is called.
+ *
+ * If a VF Module with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * All VF Modules are defined in the MSO catalog. The caller must request
+ * one of the pre-defined module types or an error will be returned. Within the
+ * catalog, each VF Module references (among other things) a cloud template
+ * which is used to deploy the required artifacts (VMs, networks, etc.)
+ * to the cloud. In this adapter implementation, that artifact is expected
+ * to be a Cloudify blueprint.
+ *
+ * Depending on the blueprint, 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 module or an error will be thrown.
+ *
+ * The method returns the vfModuleId, a Map of 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 Module. This is useful if a VF module
+ * is successfully created but the orchestration fails on a subsequent step.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
+ * @param tenantId Openstack tenant identifier
+ * @param vfModuleType VF Module type key, should match a VNF definition in catalog DB.
+ * Deprecated - should use modelCustomizationUuid
+ * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
+ * Deprecated - VF Module versions also captured by modelCustomizationUuid
+ * @param vfModuleName Name to be assigned to the new VF Module
+ * @param requestType Indicates if this is a Volume Group or Module request
+ * @param volumeGroupId Identifier (i.e. deployment ID) for a Volume Group
+ * to attach to a VF Module
+ * @param baseVfModuleId Identifier (i.e. deployment ID) of the Base Module if
+ * this is an Add-on module
+ * @param modelCustomizationUuid Unique ID for the VF Module's model. Replaces
+ * the use of vfModuleType.
+ * @param inputs Map of key=value inputs for VNF stack creation
+ * @param failIfExists Flag whether already existing VNF should be considered
+ * @param backout Flag whether to suppress automatic backout (for testing)
+ * @param msoRequest Request tracking information for logs
+ * @param vnfId Holder for output VNF Cloudify Deployment ID
+ * @param outputs Holder for Map of VNF outputs from Deployment (assigned IPs, etc)
+ * @param rollback Holder for returning VnfRollback object
+ */
+ @Override
+ public void createVfModule(String cloudSiteId,
+ String tenantId,
+ String vfModuleType,
+ String vnfVersion,
+ String vfModuleName,
+ String requestType,
+ String volumeGroupId,
+ String baseVfModuleId,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ Boolean enableBridge,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback)
+ throws VnfException
+ {
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateVfModule");
+
+ // Require a model customization ID. Every VF Module definition must have one.
+ if (modelCustomizationUuid == null || modelCustomizationUuid.isEmpty()) {
+ LOGGER.debug("Missing required input: modelCustomizationUuid");
+ String error = "Create vfModule error: Missing required input: modelCustomizationUuid";
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module ModelCustomizationUuid", "null", "Cloudify", "", MsoLogger.ErrorCode.DataError, "Create VF Module: Missing required input: modelCustomizationUuid");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Clean up some inputs to make comparisons easier
+ if (requestType == null)
+ requestType = "";
+
+ if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
+ volumeGroupId = null;
+
+ if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
+ baseVfModuleId = null;
+
+ 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);
+ }
+
+ // Check if this is for a "Volume" module
+ boolean isVolumeRequest = false;
+ if (requestType.startsWith("VOLUME")) {
+ isVolumeRequest = true;
+ }
+
+ LOGGER.debug("requestType = " + requestType + ", volumeGroupStackId = " + volumeGroupId + ", baseStackId = " + baseVfModuleId);
+
+ // Build a default rollback object (no actions performed)
+ VnfRollback vfRollback = new VnfRollback();
+ vfRollback.setCloudSiteId(cloudSiteId);
+ vfRollback.setTenantId(tenantId);
+ vfRollback.setMsoRequest(msoRequest);
+ vfRollback.setRequestType(requestType);
+ vfRollback.setIsBase(false); // Until we know better
+ vfRollback.setVolumeGroupHeatStackId(volumeGroupId);
+ vfRollback.setBaseGroupHeatStackId(baseVfModuleId);
+ vfRollback.setModelCustomizationUuid(modelCustomizationUuid);
+ vfRollback.setMode("CFY");
+
+ rollback.value = vfRollback; // Default rollback - no updates performed
+
+ // Get the VNF/VF Module definition from the Catalog DB first.
+ // There are three relevant records: VfModule, VfModuleCustomization, VnfResource
+
+ VfModule vf = null;
+ VnfResource vnfResource = null;
+ VfModuleCustomization vfmc = null;
+
+ try {
+ vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
+
+ if (vfmc == null) {
+ String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + modelCustomizationUuid;
+ LOGGER.debug(error);
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module ModelCustomizationUuid", modelCustomizationUuid, "CatalogDb", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found vfModuleCust entry " + vfmc.toString());
+ }
+
+ // Get the vfModule and vnfResource records
+ vf = vfmc.getVfModule();
+ vnfResource = vfmc.getVfModule().getVnfResources();
+ }
+ catch (Exception e) {
+
+ LOGGER.debug("unhandled exception in create VF - [Query]" + e.getMessage());
+ throw new VnfException("Exception during create VF " + e.getMessage());
+ }
+
+ // Perform a version check against cloudSite
+ // Obtain the cloud site information where we will create the VF Module
+ Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite (cloudSiteId);
+ if (!cloudSiteOp.isPresent()) {
+ throw new VnfException (new MsoCloudSiteNotFound (cloudSiteId));
+ }
+ CloudSite cloudSite = cloudSiteOp.get();
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+ aicV.setVersion(cloudSite.getAicVersion());
+
+ String vnfMin = vnfResource.getAicVersionMin();
+ String vnfMax = vnfResource.getAicVersionMax();
+
+ if ( (vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) ||
+ (vnfMax != null && aicV.isMoreRecentThan(vnfMax)))
+ {
+ // ERROR
+ String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + vnfMin + " VersionMax:" + vnfMax + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSite.getAicVersion();
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
+ LOGGER.debug(error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ // End Version check
+
+
+ DeploymentInfo cloudifyDeployment = null;
+
+ // First, look up to see if the VF already exists.
+
+ long subStartTime1 = System.currentTimeMillis ();
+ try {
+ cloudifyDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, vfModuleName);
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Cloudify", "Cloudify", "QueryDeployment", vfModuleName);
+ }
+ catch (MsoException me) {
+ // Failed to query the Deployment due to a cloudify exception.
+ String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Exception - queryDeployment", me);
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "QueryDeployment", vfModuleName);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule");
+ throw new VnfException (me);
+ }
+
+ // More precise handling/messaging if the Module already exists
+ if (cloudifyDeployment != null && !(cloudifyDeployment.getStatus () == DeploymentStatus.NOTFOUND)) {
+ // CREATED, INSTALLED, INSTALLING, FAILED, UNINSTALLING, UNKNOWN
+ DeploymentStatus status = cloudifyDeployment.getStatus();
+ LOGGER.debug ("Found Existing Deployment, status=" + status);
+
+ if (status == DeploymentStatus.INSTALLED) {
+ // fail - it exists
+ if (failIfExists != null && failIfExists) {
+ String error = "Create VF: Deployment " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Deployment " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
+ } else {
+ // Found existing deployment and client has not requested "failIfExists".
+ // Populate the outputs from the existing deployment.
+
+ vnfId.value = cloudifyDeployment.getId();
+ outputs.value = copyStringOutputs (cloudifyDeployment.getOutputs ());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module (found existing)");
+ return;
+ }
+ }
+ // Check through various detailed error cases
+ if (status == DeploymentStatus.INSTALLING || status == DeploymentStatus.UNINSTALLING) {
+ // fail - it's in progress - return meaningful error
+ String error = "Create VF: Deployment " + 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, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Deployment " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
+ }
+ else if (status == DeploymentStatus.FAILED) {
+ // fail - it exists and is in a FAILED state
+ String error = "Create VF: Deployment " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Deployment " + vfModuleName + " already exists and is in FAILED state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
+ }
+ else if (status == DeploymentStatus.UNKNOWN || status == DeploymentStatus.CREATED) {
+ // fail - it exists and is in a UNKNOWN state
+ String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Deployment " + vfModuleName + " already exists and is in " + status.toString() + " state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
+ }
+ else {
+ // Unexpected, since all known status values have been tested for
+ String error = "Create VF: Deployment " + vfModuleName + " already exists with unexpected status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "Cloudify", "queryDeployment", MsoLogger.ErrorCode.DataError, "Deployment " + vfModuleName + " already exists and is in an unknown state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
+ }
+ }
+
+
+ // Collect outputs from Base Modules and Volume Modules
+ Map<String, Object> baseModuleOutputs = null;
+ Map<String, Object> volumeGroupOutputs = null;
+
+ // If a Volume Group was provided, query its outputs for inclusion in Module input parameters
+ if (volumeGroupId != null) {
+ long subStartTime2 = System.currentTimeMillis ();
+ DeploymentInfo volumeDeployment = null;
+ try {
+ volumeDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, volumeGroupId);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Success response from Cloudify", "Cloudify", "QueryDeployment", volumeGroupId);
+ }
+ catch (MsoException me) {
+ // Failed to query the Volume GroupDeployment due to a cloudify exception.
+ String error = "Create VF Module: Query Volume Group " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, volumeGroupId, cloudSiteId, tenantId, "Cloudify", "queryDeployment(volume)", MsoLogger.ErrorCode.DataError, "Exception - queryDeployment(volume)", me);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "QueryDeployment(volume)", volumeGroupId);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule(QueryVolume)");
+ throw new VnfException (me);
+ }
+
+ if (volumeDeployment == null || volumeDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
+ String error = "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, volumeGroupId, cloudSiteId, tenantId, error, "Cloudify", "queryDeployment(volume)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached Volume Group 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 group");
+ volumeGroupOutputs = volumeDeployment.getOutputs();
+ this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
+ }
+ }
+
+ // If this is an Add-On Module, query the Base Module outputs
+ // Note: This will be performed whether or not the current request is for an
+ // Add-On Volume Group or Add-On VF Module
+
+ if (vf.getIsBase()) {
+ LOGGER.debug("This is a BASE Module request");
+ vfRollback.setIsBase(true);
+ } else {
+ LOGGER.debug("This is an Add-On Module request");
+
+ // Add-On Modules should always have a Base, but just treat as a warning if not provided.
+ // Add-on Volume requests may or may not specify a base.
+ if (!isVolumeRequest && baseVfModuleId == null) {
+ LOGGER.debug ("WARNING: Add-on Module request - no Base Module ID provided");
+ }
+
+ if (baseVfModuleId != null) {
+ long subStartTime2 = System.currentTimeMillis ();
+ DeploymentInfo baseDeployment = null;
+ try {
+ baseDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, baseVfModuleId);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Success response from Cloudify", "Cloudify", "QueryDeployment(Base)", baseVfModuleId);
+ }
+ catch (MsoException me) {
+ // Failed to query the Volume GroupDeployment due to a cloudify exception.
+ String error = "Create VF Module: Query Base " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, "Cloudify", "queryDeployment(Base)", MsoLogger.ErrorCode.DataError, "Exception - queryDeployment(Base)", me);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "QueryDeployment(Base)", baseVfModuleId);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule(QueryBase)");
+ throw new VnfException (me);
+ }
+
+ if (baseDeployment == null || baseDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
+ String error = "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, error, "Cloudify", "queryDeployment(Base)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Base Module 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 base module");
+ baseModuleOutputs = baseDeployment.getOutputs();
+ this.sendMapToDebug(baseModuleOutputs, "baseModuleOutputs");
+ }
+ }
+ }
+
+
+ // Ready to deploy the new VNF
+
+ // NOTE: For this section, heatTemplate is used for both HEAT templates and Cloudify blueprints.
+ // In final implementation (post-POC), the template object would either be generic or there would
+ // be a separate DB Table/Object for Blueprints.
+
+
+ // NOTE: The template is fixed for the VF Module. The environment is part of the customization.
+ HeatTemplate heatTemplate = null;
+ HeatEnvironment heatEnvironment = null;
+ if (isVolumeRequest) {
+ heatTemplate = vf.getVolumeHeatTemplate();
+ heatEnvironment = vfmc.getVolumeHeatEnv();
+ } else {
+ heatTemplate = vf.getModuleHeatTemplate();
+ heatEnvironment = vfmc.getHeatEnvironment();
+ }
+
+ if (heatTemplate == null) {
+ String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestType;
+ 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 {
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
+ }
+
+ if (heatEnvironment == null) {
+ String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", "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.getEnvironment());
+ }
+
+
+ try {
+ // All variables converted to their native object types
+ HashMap<String, Object> goldenInputs = new HashMap<String,Object>();
+ List<String> extraInputs = new ArrayList<String>();
+
+ // NOTE: SKIP THIS FOR CLOUDIFY for now. Just use what was passed in.
+ // This whole section needs to be rewritten.
+ Boolean skipInputChecks = false;
+
+ if (skipInputChecks) {
+ goldenInputs = new HashMap<String,Object>();
+ for (String key : inputs.keySet()) {
+ goldenInputs.put(key, inputs.get(key));
+ }
+ }
+ else {
+ // Build maps for the parameters (including aliases) to simplify checks
+ HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
+
+ Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
+ LOGGER.debug("paramSet has " + paramSet.size() + " entries");
+
+ for (HeatTemplateParam htp : paramSet) {
+ params.put(htp.getParamName(), htp);
+
+ // Include aliases.
+ String alias = htp.getParamAlias();
+ if (alias != null && !alias.equals("") && !params.containsKey(alias)) {
+ params.put(alias, htp);
+ }
+ }
+
+ // First, convert all inputs to their "template" type
+ for (String key : inputs.keySet()) {
+ if (params.containsKey(key)) {
+ Object value = cloudifyUtils.convertInputValue(inputs.get(key), params.get(key));
+ if (value != null) {
+ goldenInputs.put(key, value);
+ }
+ else {
+ LOGGER.debug("Failed to convert input " + key + "='" + inputs.get(key) + "' to " + params.get(key).getParamType());
+ }
+ } else {
+ extraInputs.add(key);
+ }
+ }
+
+ if (!extraInputs.isEmpty()) {
+ LOGGER.debug("Ignoring extra inputs: " + extraInputs);
+ }
+
+ // Next add in Volume Group Outputs if there are any. Copy directly without conversions.
+ if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
+ for (String key : volumeGroupOutputs.keySet()) {
+ if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
+ goldenInputs.put(key, volumeGroupOutputs.get(key));
+ }
+ }
+ }
+
+ // Next add in Base Module Outputs if there are any. Copy directly without conversions.
+ if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
+ for (String key : baseModuleOutputs.keySet()) {
+ if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
+ goldenInputs.put(key, baseModuleOutputs.get(key));
+ }
+ }
+ }
+
+ // Last, add in values from the "environment" file.
+ // These are added to the inputs, since Cloudify doesn't pass an environment file like Heat.
+
+ // TODO: This may take a different form for Cloudify, but for now process it
+ // with Heat environment file syntax
+ StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
+ MsoHeatEnvironmentEntry mhee = new MsoHeatEnvironmentEntry (sb);
+
+ if (mhee.getParameters() != null) {
+ for (MsoHeatEnvironmentParameter envParam : mhee.getParameters()) {
+ // If this is a template input, copy to golden inputs
+ String envKey = envParam.getName();
+ if (params.containsKey(envKey) && !goldenInputs.containsKey(envKey)) {
+ Object value = cloudifyUtils.convertInputValue(envParam.getValue(), params.get(envKey));
+ if (value != null) {
+ goldenInputs.put(envKey, value);
+ }
+ else {
+ LOGGER.debug("Failed to convert environment parameter " + envKey + "='" + envParam.getValue() + "' to " + params.get(envKey).getParamType());
+ }
+ }
+ }
+ }
+
+ this.sendMapToDebug(goldenInputs, "Final inputs sent to Cloudify");
+
+
+ // Check that required parameters have been supplied from any of the sources
+ String missingParams = null;
+ boolean checkRequiredParameters = true;
+ try {
+ String propertyString = this.environment.getProperty(MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
+ if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
+ checkRequiredParameters = false;
+ LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
+ + MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
+ }
+ } catch (Exception e) {
+ // No problem - default is true
+ LOGGER.debug ("An exception occured trying to get property " + MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS, e);
+ }
+
+
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ if (parm.isRequired () && (!goldenInputs.containsKey (parm.getParamName ()))) {
+ LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
+ if (missingParams == null) {
+ missingParams = parm.getParamName ();
+ } else {
+ missingParams += "," + 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, "Cloudify", "", 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 [" + missingParams + "] - but checkRequiredParameters is false - will not block");
+ }
+ } else {
+ LOGGER.debug ("No missing parameters found - ok to proceed");
+ }
+
+ } // NOTE: END PARAMETER CHECKING
+
+ // Ready to deploy the VF Module.
+ // *First step - make sure the blueprint is loaded into Cloudify.
+ String blueprintName = heatTemplate.getTemplateName();
+ String blueprint = heatTemplate.getTemplateBody();
+ String blueprintId = blueprintName;
+
+ // Use the main blueprint name as the blueprint ID (strip yaml extensions).
+ if (blueprintId.endsWith(".yaml"))
+ blueprintId = blueprintId.substring(0,blueprintId.lastIndexOf(".yaml"));
+
+ try {
+ if (! cloudifyUtils.isBlueprintLoaded (cloudSiteId, blueprintId)) {
+ LOGGER.debug ("Blueprint " + blueprintId + " is not loaded. Will upload it now.");
+
+ Map<String,byte[]> blueprintFiles = new HashMap<String,byte[]>();
+
+ blueprintFiles.put(blueprintName, blueprint.getBytes());
+
+ // TODO: Implement nested blueprint logic based on Cloudify structures.
+ // For now, just use the Heat structures.
+ // The query returns a map of String->Object, where the map keys provide one layer of
+ // indirection from the Heat template names. For this case, assume the map key matches
+ // the nested blueprint name.
+ List<HeatTemplate> nestedBlueprints = heatTemplate.getChildTemplates();
+ if (nestedBlueprints != null) {
+ for (HeatTemplate nestedBlueprint: nestedBlueprints) {
+ blueprintFiles.put(nestedBlueprint.getTemplateName(), nestedBlueprint.getTemplateBody().getBytes());
+ }
+ }
+
+ // TODO: Implement file artifact logic based on Cloudify structures.
+ // For now, just use the Heat structures.
+ List<HeatFiles> heatFiles = vf.getHeatFiles();
+ if (heatFiles != null) {
+ for (HeatFiles heatFile: heatFiles) {
+ blueprintFiles.put(heatFile.getFileName(), heatFile.getFileBody().getBytes());
+ }
+ }
+
+ // Upload the blueprint package
+ cloudifyUtils.uploadBlueprint(cloudSiteId, blueprintId, blueprintName, blueprintFiles, false);
+
+ }
+ }
+
+ catch (MsoException me) {
+ me.addContext ("CreateVFModule");
+ String error = "Create VF Module: Upload blueprint failed. Blueprint=" + blueprintName + ": " + me;
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "Cloudify", "", MsoLogger.ErrorCode.DataError, "MsoException - uploadBlueprint", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+
+ }
+
+ // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
+ // because we already checked for those.
+ long createDeploymentStarttime = System.currentTimeMillis ();
+ try {
+ // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
+ // Go directly to Keystone until APIs could be updated to supply the name.
+ MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
+ String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
+
+ if (backout == null) {
+ backout = true;
+ }
+
+ cloudifyDeployment = cloudifyUtils.createAndInstallDeployment (cloudSiteId,
+ tenantName,
+ vfModuleName,
+ blueprintId,
+ goldenInputs,
+ true,
+ heatTemplate.getTimeoutMinutes (),
+ backout.booleanValue());
+
+ LOGGER.recordMetricEvent (createDeploymentStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Cloudify", "Cloudify", "CreateDeployment", vfModuleName);
+ } catch (MsoException me) {
+ me.addContext ("CreateVFModule");
+ String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (createDeploymentStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "CreateDeployment", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "Cloudify", "", MsoLogger.ErrorCode.DataError, "MsoException - createDeployment", 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 (createDeploymentStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "CreateDeployment", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "Cloudify", "", MsoLogger.ErrorCode.DataError, "NullPointerException - createDeployment", npe);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ LOGGER.debug("NULL POINTER EXCEPTION at cloudify.createAndInstallDeployment");
+ //npe.addContext ("CreateVNF");
+ throw new VnfException ("NullPointerException during cloudify.createAndInstallDeployment");
+ } catch (Exception e) {
+ LOGGER.recordMetricEvent (createDeploymentStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating deployment with Cloudify", "Cloudify", "CreateDeployment", vfModuleName);
+ LOGGER.debug("unhandled exception at cloudify.createAndInstallDeployment");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating deployment with Cloudify");
+ throw new VnfException("Exception during cloudify.createAndInstallDeployment! " + 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 create is successful.
+ // Populate remaining rollback info and response parameters.
+ vfRollback.setVnfCreated (true);
+ vfRollback.setVnfId (cloudifyDeployment.getId());
+ vnfId.value = cloudifyDeployment.getId();
+ outputs.value = copyStringOutputs (cloudifyDeployment.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,
+ Holder <Map <String, String>> outputs) 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 ();
+
+ // 1702 capture the output parameters on a delete
+ // so we'll need to query first
+ DeploymentInfo deployment = null;
+ try {
+ deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
+ } catch (MsoException me) {
+ // Failed to query the deployment. Convert to a generic VnfException
+ me.addContext ("DeleteVFModule");
+ String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "Cloudify", "QueryDeployment", null);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "Cloudify", "QueryDeployment", MsoLogger.ErrorCode.DataError, "Exception - QueryDeployment", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (me);
+ }
+ // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
+ outputs.value = convertMapStringObjectToStringString(deployment.getOutputs());
+
+ // 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 {
+ cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantId, vnfName, 5);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from DeleteDeployment", "Cloudify", "DeleteDeployment", vnfName);
+ } catch (MsoException me) {
+ me.addContext ("DeleteVfModule");
+ // Convert to a generic VnfException
+ String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "DeleteDeployment", "DeleteDeployment", vnfName);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "DeleteDeployment", "DeleteDeployment", MsoLogger.ErrorCode.DataError, "Exception - DeleteDeployment: " + me.getMessage());
+ 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;
+ }
+
+ // TODO: Should Update be supported for Cloudify? What would this look like?
+ @Override
+ public void updateVfModule (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ String baseVfHeatStackId,
+ String vfModuleStackId,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException
+ {
+ // This operation is not currently supported for Cloudify-orchestrated VF Modules.
+ LOGGER.debug ("Update VF Module command attempted but not supported");
+ throw new VnfException ("UpdateVfModule: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+} \ No newline at end of file
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java
new file mode 100644
index 0000000000..0a7b30f9ca
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java
@@ -0,0 +1,1229 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * This VNF Adapter implementation is based on the VDU Plugin model. It assumes that each
+ * VF Module definition in the MSO catalog is expressed via a set of template and/or file
+ * artifacts that are appropriate for some specific sub-orchestrator that provides an
+ * implementation of the VduPlugin interface. This adapter handles all of the common
+ * VF Module logic, including:
+ * - catalog lookups for artifact retrieval
+ * - parameter filtering and validation
+ * - base and volume module queries
+ * - rollback logic
+ * - logging and error handling
+ *
+ * Then based on the orchestration mode of the VNF, it will invoke different VDU plug-ins
+ * to perform the low level instantiations, deletions, and queries. At this time, the
+ * set of available plug-ins is hard-coded, though in the future a dynamic selection
+ * is expected (e.g. via a service-provider interface).
+ */
+package org.onap.so.adapters.vnf;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.onap.so.adapters.vdu.CloudInfo;
+import org.onap.so.adapters.vdu.VduException;
+import org.onap.so.adapters.vdu.VduInstance;
+import org.onap.so.adapters.vdu.VduModelInfo;
+import org.onap.so.adapters.vdu.VduPlugin;
+import org.onap.so.adapters.vdu.VduStateType;
+import org.onap.so.adapters.vdu.VduStatus;
+import org.onap.so.adapters.vdu.mapper.VfModuleCustomizationToVduMapper;
+import org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
+import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.CloudSite;
+import org.onap.so.cloudify.utils.MsoCloudifyUtils;
+import org.onap.so.db.catalog.beans.HeatEnvironment;
+import org.onap.so.db.catalog.beans.HeatTemplate;
+import org.onap.so.db.catalog.beans.HeatTemplateParam;
+import org.onap.so.db.catalog.beans.VfModule;
+import org.onap.so.db.catalog.beans.VfModuleCustomization;
+import org.onap.so.db.catalog.beans.VnfResource;
+import org.onap.so.db.catalog.data.repository.VFModuleCustomizationRepository;
+import org.onap.so.db.catalog.utils.MavenLikeVersioning;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoAlarmLogger;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
+import org.onap.so.openstack.utils.MsoHeatUtils;
+import org.onap.so.openstack.utils.MsoKeystoneUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf")
+@Component
+@Transactional
+public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
+
+ private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, MsoVnfPluginAdapterImpl.class);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+
+ @Autowired
+ protected CloudConfig cloudConfig;
+
+ @Autowired
+ private VFModuleCustomizationRepository vfModuleCustomRepo;
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ protected MsoKeystoneUtils keystoneUtils;
+
+ @Autowired
+ protected MsoCloudifyUtils cloudifyUtils;
+
+ @Autowired
+ protected MsoHeatUtils heatUtils;
+
+ @Autowired
+ protected VfModuleCustomizationToVduMapper vduMapper;
+
+ /**
+ * 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 Plugin Adapter");
+ }
+
+ /**
+ * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
+ * @see MsoVnfPluginAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
+ */
+ public MsoVnfPluginAdapterImpl() {
+
+ }
+
+ /**
+ * This is the "Create VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @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,
+ Boolean enableBridge,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback)
+ throws VnfException
+ {
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("CreateVNF command attempted but not supported");
+ throw new VnfException ("CreateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * This is the "Update VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @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
+ {
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("UpdateVNF command attempted but not supported");
+ throw new VnfException ("UpdateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * This is the "Query VNF" web service implementation.
+ *
+ * This really should be QueryVfModule, but nobody ever changed it.
+ *
+ * The method returns an indicator that the VNF exists, along with its status and outputs.
+ * The input "vnfName" will also be reflected back as its ID.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to query
+ * @param tenantId Openstack tenant identifier
+ * @param vnfNameOrId VNF Name or ID to query
+ * @param msoRequest Request tracking information for logs
+ * @param vnfExists Flag reporting the result of the query
+ * @param vnfId Holder for output VNF ID
+ * @param outputs Holder for Map of outputs from the deployed VF Module (assigned IPs, etc)
+ */
+ @Override
+ public void queryVnf (String cloudSiteId,
+ String tenantId,
+ String vnfNameOrId,
+ 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 " + vnfNameOrId + " in " + cloudSiteId + "/" + tenantId);
+
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ long subStartTime = System.currentTimeMillis ();
+
+ VduInstance vduInstance = null;
+ CloudInfo cloudInfo = new CloudInfo(cloudSiteId, tenantId, null);
+
+ VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
+
+ try {
+ vduInstance = vduPlugin.queryVdu (cloudInfo, vnfNameOrId);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received VDU Query response", "VDU", "QueryVDU", vnfNameOrId);
+ }
+ catch (VduException e) {
+ // Failed to query the VDU due to a plugin exception.
+ // Convert to a generic VnfException
+ e.addContext ("QueryVNF");
+ String error = "Query VNF (VDU): " + vnfNameOrId + " in " + cloudSiteId + "/" + tenantId + ": " + e;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVNF", vnfNameOrId);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfNameOrId, cloudSiteId, tenantId, "VDU", "QueryVNF", MsoLogger.ErrorCode.DataError, "Exception - queryVDU", e);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (e);
+ }
+
+ if (vduInstance != null && vduInstance.getStatus().getState() != VduStateType.NOTFOUND) {
+ vnfExists.value = Boolean.TRUE;
+ status.value = vduStatusToVnfStatus(vduInstance);
+ vnfId.value = vduInstance.getVduInstanceId();
+ outputs.value = copyStringOutputs (vduInstance.getOutputs ());
+
+ LOGGER.debug ("VNF " + vnfNameOrId + " found, ID = " + vnfId.value);
+ }
+ else {
+ 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 " + vnfNameOrId + " not found");
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query VNF");
+ return;
+ }
+
+
+ /**
+ * This is the "Delete VNF" web service implementation.
+ * This function is now unsupported and will return an error.
+ *
+ */
+ @Override
+ public void deleteVnf (String cloudSiteId,
+ String tenantId,
+ String vnfName,
+ MsoRequest msoRequest) throws VnfException {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteVnf");
+
+ // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
+ LOGGER.debug ("DeleteVNF command attempted but not supported");
+ throw new VnfException ("DeleteVNF: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /**
+ * 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.
+ *
+ * TODO: This should be rollbackVfModule and/or rollbackVolumeGroup,
+ * but APIs were apparently never updated.
+ */
+ @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", MsoLogger.getServiceName());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "Rollback request content is null");
+ return;
+ }
+
+ // Don't rollback if nothing was done originally
+ if (!rollback.getVnfCreated()) {
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Rollback VF Module - nothing to roll back");
+ return;
+ }
+
+ // Get the elements of the VnfRollback object for easier access
+ String cloudSiteId = rollback.getCloudSiteId ();
+ String tenantId = rollback.getTenantId ();
+ CloudInfo cloudInfo = new CloudInfo (cloudSiteId, tenantId, null);
+
+ String vfModuleId = rollback.getVfModuleStackId ();
+
+ MsoLogger.setLogContext (rollback.getMsoRequest());
+
+ LOGGER.debug ("Rolling Back VF Module " + vfModuleId + " in " + cloudSiteId + "/" + tenantId);
+
+ VduInstance vduInstance = null;
+
+ // Use the VduPlugin to delete the VF Module.
+ VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
+
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ // TODO: Get a reasonable timeout. Use a global property, or store the creation timeout in rollback object and use that.
+ vduInstance = vduPlugin.deleteVdu(cloudInfo, vfModuleId, 5);
+
+ LOGGER.debug("Rolled back VDU instantiation: " + vduInstance.getVduInstanceId());
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from VDU Plugin", "VDU", "DeleteVdu", null);
+ }
+ catch (VduException ve) {
+ // Failed to rollback the VF Module due to a plugin exception.
+ // Convert to a generic VnfException
+ ve.addContext ("RollbackVFModule");
+ String error = "Rollback VF Module: " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + ve;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "DeleteVdu", null);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vfModuleId, cloudSiteId, tenantId, "VDU", "DeleteVdu", MsoLogger.ErrorCode.DataError, "Exception - DeleteVdu", ve);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (ve);
+ }
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully roll back VF Module");
+ return;
+ }
+
+
+ private VnfStatus vduStatusToVnfStatus (VduInstance vdu) {
+ // Determine the status based on last action & status
+ // DeploymentInfo object should be enhanced to report a better status internally.
+ VduStatus vduStatus = vdu.getStatus();
+ VduStateType status = vduStatus.getState();
+
+ if (status == null) {
+ return VnfStatus.UNKNOWN;
+ }
+ else if (status == VduStateType.NOTFOUND) {
+ return VnfStatus.NOTFOUND;
+ }
+ else if (status == VduStateType.INSTANTIATED) {
+ return VnfStatus.ACTIVE;
+ }
+ else if (status == VduStateType.FAILED) {
+ return VnfStatus.FAILED;
+ }
+
+ return VnfStatus.UNKNOWN;
+ }
+
+ /*
+ * Normalize an input value to an Object, based on the target parameter type.
+ * If the type is not recognized, it will just be returned unchanged (as a string).
+ */
+ private Object convertInputValue (String inputValue, HeatTemplateParam templateParam)
+ {
+ String type = templateParam.getParamType();
+ LOGGER.debug("Parameter: " + templateParam.getParamName() + " is of type " + type);
+
+ if (type.equalsIgnoreCase("number")) {
+ try {
+ return Integer.valueOf(inputValue);
+ }
+ catch (Exception e) {
+ LOGGER.debug("Unable to convert " + inputValue + " to an integer!" , e);
+ return null;
+ }
+ } else if (type.equalsIgnoreCase("json")) {
+ try {
+ JsonNode jsonNode = new ObjectMapper().readTree(inputValue);
+ return jsonNode;
+ }
+ catch (Exception e) {
+ LOGGER.debug("Unable to convert " + inputValue + " to a JsonNode!", e);
+ return null;
+ }
+ } else if (type.equalsIgnoreCase("boolean")) {
+ return new Boolean(inputValue);
+ }
+
+ // Nothing else matched. Return the original string
+ return inputValue;
+ }
+
+ 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));
+ } else if (stackOutputs.get(key) instanceof Integer) {
+ try {
+ String str = "" + stackOutputs.get(key);
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs", e);
+ }
+ } else if (stackOutputs.get(key) instanceof JsonNode) {
+ try {
+ String str = this.convertNode((JsonNode) stackOutputs.get(key));
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - exception converting JsonNode", e);
+ }
+ } else if (stackOutputs.get(key) instanceof java.util.LinkedHashMap) {
+ try {
+ String str = JSON_MAPPER.writeValueAsString(stackOutputs.get(key));
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - exception converting LinkedHashMap", e);
+ }
+ } else {
+ try {
+ String str = stackOutputs.get(key).toString();
+ stringOutputs.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("Unable to add " + key + " to outputs - unable to call .toString() " + e.getMessage(), e);
+ }
+ }
+ }
+ return stringOutputs;
+ }
+
+
+ private void sendMapToDebug(Map<String, Object> inputs, String optionalName) {
+ int i = 0;
+ StringBuilder sb = new StringBuilder(optionalName == null ? "\ninputs" : "\n" + optionalName);
+ if (inputs == null) {
+ sb.append("\tNULL");
+ }
+ else if (inputs.size() < 1) {
+ sb.append("\tEMPTY");
+ } else {
+ for (String str : inputs.keySet()) {
+ String outputString;
+ try {
+ outputString = inputs.get(str).toString();
+ } catch (Exception e) {
+ outputString = "Unable to call toString() on the value for " + str;
+ }
+ sb.append("\t\nitem " + i++ + ": '" + str + "'='" + outputString + "'");
+ }
+ }
+ LOGGER.debug(sb.toString());
+ return;
+ }
+
+ 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;
+ }
+
+ private String convertNode(final JsonNode node) {
+ try {
+ final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
+ final String json = JSON_MAPPER.writeValueAsString(obj);
+ return json;
+ } catch (JsonParseException jpe) {
+ LOGGER.debug("Error converting json to string " + jpe.getMessage());
+ } catch (Exception e) {
+ LOGGER.debug("Error converting json to string " + e.getMessage());
+ }
+ return "[Error converting json to string]";
+ }
+
+ private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
+ if (objectMap == null) {
+ return null;
+ }
+ Map<String, String> stringMap = new HashMap<String, String>();
+ for (String key : objectMap.keySet()) {
+ if (!stringMap.containsKey(key)) {
+ Object obj = objectMap.get(key);
+ if (obj instanceof String) {
+ stringMap.put(key, (String) objectMap.get(key));
+ } else if (obj instanceof JsonNode ){
+ // This is a bit of mess - but I think it's the least impacting
+ // let's convert it BACK to a string - then it will get converted back later
+ try {
+ String str = this.convertNode((JsonNode) obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key, e);
+ //okay in this instance - only string values (fqdn) are expected to be needed
+ }
+ } else if (obj instanceof java.util.LinkedHashMap) {
+ LOGGER.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
+ try {
+ String str = JSON_MAPPER.writeValueAsString(obj);
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key, e);
+ }
+ } else if (obj instanceof Integer) {
+ try {
+ String str = "" + obj;
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key, e);
+ }
+ } else {
+ try {
+ String str = obj.toString();
+ stringMap.put(key, str);
+ } catch (Exception e) {
+ LOGGER.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")", e);
+ }
+ }
+ }
+ }
+
+ return stringMap;
+ }
+
+ /**
+ * This is the "Create VF Module" web service implementation.
+ * It will instantiate a new VF Module of the requested type in the specified cloud
+ * and tenant. The tenant must exist before this service is called.
+ *
+ * If a VF Module with the same name already exists, this can be considered a
+ * success or failure, depending on the value of the 'failIfExists' parameter.
+ *
+ * All VF Modules are defined in the MSO catalog. The caller must request one of
+ * the pre-defined module types or an error will be returned. Within the catalog,
+ * each VF Module references (among other things) a collection of artifacts that
+ * are used to deploy the required cloud resources (VMs, networks, etc.).
+ *
+ * Depending on the module templates, 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 module or an error will be thrown.
+ *
+ * The method returns the vfModuleId, a Map of 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 Module. This is useful if a VF module
+ * is successfully created but the orchestration fails on a subsequent step.
+ *
+ * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
+ * @param tenantId Openstack tenant identifier
+ * @param vfModuleType VF Module type key, should match a VNF definition in catalog DB.
+ * Deprecated - should use modelCustomizationUuid
+ * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
+ * Deprecated - VF Module versions also captured by modelCustomizationUuid
+ * @param vfModuleName Name to be assigned to the new VF Module
+ * @param requestType Indicates if this is a Volume Group or Module request
+ * @param volumeGroupId Identifier (i.e. deployment ID) for a Volume Group
+ * to attach to a VF Module
+ * @param baseVfModuleId Identifier (i.e. deployment ID) of the Base Module if
+ * this is an Add-on module
+ * @param modelCustomizationUuid Unique ID for the VF Module's model. Replaces
+ * the use of vfModuleType.
+ * @param inputs Map of key=value inputs for VNF stack creation
+ * @param failIfExists Flag whether already existing VNF should be considered
+ * @param backout Flag whether to suppress automatic backout (for testing)
+ * @param msoRequest Request tracking information for logs
+ * @param vnfId Holder for output VF Module instance ID in the cloud
+ * @param outputs Holder for Map of VNF outputs from Deployment (assigned IPs, etc)
+ * @param rollback Holder for returning VnfRollback object
+ */
+ @Override
+ public void createVfModule(String cloudSiteId,
+ String tenantId,
+ String vfModuleType,
+ String vnfVersion,
+ String vfModuleName,
+ String requestType,
+ String volumeGroupId,
+ String baseVfModuleId,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ Boolean failIfExists,
+ Boolean backout,
+ Boolean enableBridge,
+ MsoRequest msoRequest,
+ Holder <String> vnfId,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback)
+ throws VnfException
+ {
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("CreateVfModule");
+
+ // Require a model customization ID. Every VF Module definition must have one.
+ if (modelCustomizationUuid == null || modelCustomizationUuid.isEmpty()) {
+ LOGGER.debug("Missing required input: modelCustomizationUuid");
+ String error = "Create vfModule error: Missing required input: modelCustomizationUuid";
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module ModelCustomizationUuid", "null", "VDU", "", MsoLogger.ErrorCode.DataError, "Create VF Module: Missing required input: modelCustomizationUuid");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+
+ // Clean up some inputs to make comparisons easier
+ if (requestType == null)
+ requestType = "";
+
+ if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
+ volumeGroupId = null;
+
+ if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
+ baseVfModuleId = null;
+
+ if (inputs == null) {
+ // Create an empty set of inputs
+ inputs = new HashMap<>();
+ LOGGER.debug("inputs == null - setting to empty");
+ } else {
+ this.sendMapToDebug(inputs);
+ }
+
+ // Check if this is for a "Volume" module
+ boolean isVolumeRequest = false;
+ if (requestType.startsWith("VOLUME")) {
+ isVolumeRequest = true;
+ }
+
+ LOGGER.debug("requestType = " + requestType + ", volumeGroupStackId = " + volumeGroupId + ", baseStackId = " + baseVfModuleId);
+
+ // Build a default rollback object (no actions performed)
+ VnfRollback vfRollback = new VnfRollback();
+ vfRollback.setCloudSiteId(cloudSiteId);
+ vfRollback.setTenantId(tenantId);
+ vfRollback.setMsoRequest(msoRequest);
+ vfRollback.setRequestType(requestType);
+ vfRollback.setIsBase(false); // Until we know better
+ vfRollback.setVolumeGroupHeatStackId(volumeGroupId);
+ vfRollback.setBaseGroupHeatStackId(baseVfModuleId);
+ vfRollback.setModelCustomizationUuid(modelCustomizationUuid);
+ vfRollback.setMode("CFY");
+
+ rollback.value = vfRollback; // Default rollback - no updates performed
+
+ // Get the VNF/VF Module definition from the Catalog DB first.
+ // There are three relevant records: VfModule, VfModuleCustomization, VnfResource
+
+ VfModule vfModule = null;
+ VnfResource vnfResource = null;
+ VfModuleCustomization vfModuleCust = null;
+
+ try {
+ vfModuleCust = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
+
+ if (vfModuleCust == null) {
+ String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + modelCustomizationUuid;
+ LOGGER.debug(error);
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
+ "VF Module ModelCustomizationUuid", modelCustomizationUuid, "CatalogDb", "", MsoLogger.ErrorCode.DataError, error);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ } else {
+ LOGGER.debug("Found vfModuleCust entry " + vfModuleCust.toString());
+ }
+
+ // Get the vfModule and vnfResource records
+ vfModule = vfModuleCust.getVfModule();
+ vnfResource = vfModuleCust.getVfModule().getVnfResources();
+ }
+ catch (Exception e) {
+
+ LOGGER.debug("unhandled exception in create VF - [Query]" + e.getMessage());
+ throw new VnfException("Exception during create VF " + e.getMessage());
+ }
+
+ // Perform a version check against cloudSite
+ // Obtain the cloud site information where we will create the VF Module
+ Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite (cloudSiteId);
+ if (!cloudSiteOp.isPresent()) {
+ throw new VnfException (new MsoCloudSiteNotFound (cloudSiteId));
+ }
+ CloudSite cloudSite = cloudSiteOp.get();
+ MavenLikeVersioning aicV = new MavenLikeVersioning();
+ aicV.setVersion(cloudSite.getAicVersion());
+
+ String vnfMin = vnfResource.getAicVersionMin();
+ String vnfMax = vnfResource.getAicVersionMax();
+
+ if ( (vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) ||
+ (vnfMax != null && aicV.isMoreRecentThan(vnfMax)))
+ {
+ // ERROR
+ String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + vnfMin + " VersionMax:" + vnfMax + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSite.getAicVersion();
+ LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
+ LOGGER.debug(error);
+ throw new VnfException(error, MsoExceptionCategory.USERDATA);
+ }
+ // End Version check
+
+
+ VduInstance vduInstance = null;
+ CloudInfo cloudInfo = new CloudInfo (cloudSiteId, tenantId, null);
+
+ // Use the VduPlugin.
+ VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
+
+ // First, look up to see if the VF already exists.
+
+ long subStartTime1 = System.currentTimeMillis ();
+ try {
+ vduInstance = vduPlugin.queryVdu (cloudInfo, vfModuleName);
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from VduPlugin", "VDU", "QueryVDU", vfModuleName);
+ }
+ catch (VduException me) {
+ // Failed to query the VDU due to a plugin exception.
+ String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "Exception - queryVdu", me);
+ LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVdu", vfModuleName);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule");
+ throw new VnfException (me);
+ }
+
+ // More precise handling/messaging if the Module already exists
+ if (vduInstance != null && !(vduInstance.getStatus().getState() == VduStateType.NOTFOUND)) {
+ VduStateType status = vduInstance.getStatus().getState();
+ LOGGER.debug ("Found Existing VDU, status=" + status);
+
+ if (status == VduStateType.INSTANTIATED) {
+ if (failIfExists != null && failIfExists) {
+ // fail - it exists
+ String error = "Create VF: Deployment " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "VF Module " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
+ } else {
+ // Found existing deployment and client has not requested "failIfExists".
+ // Populate the outputs from the existing deployment.
+
+ vnfId.value = vduInstance.getVduInstanceId();
+ outputs.value = copyStringOutputs (vduInstance.getOutputs ());
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module (found existing)");
+ return;
+ }
+ }
+ // Check through various detailed error cases
+ else if (status == VduStateType.INSTANTIATING || status == VduStateType.DELETING || status == VduStateType.UPDATING) {
+ // fail - it's in progress - return meaningful error
+ String error = "Create VF: Deployment " + 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, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "VF Module " + vfModuleName + " already exists");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
+ }
+ else if (status == VduStateType.FAILED) {
+ // fail - it exists and is in a FAILED state
+ String error = "Create VF: Deployment " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "VF Module " + vfModuleName + " already exists and is in FAILED state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
+ }
+ else if (status == VduStateType.UNKNOWN) {
+ // fail - it exists and is in a UNKNOWN state
+ String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "VF Module " + vfModuleName + " already exists and is in " + status.toString() + " state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
+ }
+ else {
+ // Unexpected, since all known status values have been tested for
+ String error = "Create VF: Deployment " + vfModuleName + " already exists with unexpected status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
+ LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "VDU", "queryVdu", MsoLogger.ErrorCode.DataError, "VF Module " + vfModuleName + " already exists and is in an unknown state");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
+ throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
+ }
+ }
+
+
+ // Collect outputs from Base Modules and Volume Modules
+ Map<String, Object> baseModuleOutputs = null;
+ Map<String, Object> volumeGroupOutputs = null;
+
+ // If a Volume Group was provided, query its outputs for inclusion in Module input parameters
+ if (volumeGroupId != null) {
+ long subStartTime2 = System.currentTimeMillis ();
+ VduInstance volumeVdu = null;
+ try {
+ volumeVdu = vduPlugin.queryVdu (cloudInfo, volumeGroupId);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Success response from VduPlugin", "VDU", "QueryVdu", volumeGroupId);
+ }
+ catch (VduException me) {
+ // Failed to query the Volume Group VDU due to a plugin exception.
+ String error = "Create VF Module: Query Volume Group " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, volumeGroupId, cloudSiteId, tenantId, "VDU", "queryVdu(volume)", MsoLogger.ErrorCode.DataError, "Exception - queryVdu(volume)", me);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVdu(volume)", volumeGroupId);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule(QueryVolume)");
+ throw new VnfException (me);
+ }
+
+ if (volumeVdu == null || volumeVdu.getStatus().getState() == VduStateType.NOTFOUND) {
+ String error = "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, volumeGroupId, cloudSiteId, tenantId, error, "VDU", "queryVdu(volume)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached Volume Group 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 group");
+ volumeGroupOutputs = volumeVdu.getOutputs();
+ this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
+ }
+ }
+
+ // If this is an Add-On Module, query the Base Module outputs
+ // Note: This will be performed whether or not the current request is for an
+ // Add-On Volume Group or Add-On VF Module
+
+ if (vfModule.getIsBase()) {
+ LOGGER.debug("This is a BASE Module request");
+ vfRollback.setIsBase(true);
+ } else {
+ LOGGER.debug("This is an Add-On Module request");
+
+ // Add-On Modules should always have a Base, but just treat as a warning if not provided.
+ // Add-on Volume requests may or may not specify a base.
+ if (!isVolumeRequest && baseVfModuleId == null) {
+ LOGGER.debug ("WARNING: Add-on Module request - no Base Module ID provided");
+ }
+
+ if (baseVfModuleId != null) {
+ long subStartTime2 = System.currentTimeMillis ();
+ VduInstance baseVdu = null;
+ try {
+ baseVdu = vduPlugin.queryVdu (cloudInfo, baseVfModuleId);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Success response from VduPlugin", "VDU", "QueryVdu(Base)", baseVfModuleId);
+ }
+ catch (MsoException me) {
+ // Failed to query the Base VF Module due to a Vdu Plugin exception.
+ String error = "Create VF Module: Query Base " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, "VDU", "queryVdu(Base)", MsoLogger.ErrorCode.DataError, "Exception - queryVdu(Base)", me);
+ LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVdu(Base)", baseVfModuleId);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+
+ // Convert to a generic VnfException
+ me.addContext ("CreateVFModule(QueryBase)");
+ throw new VnfException (me);
+ }
+
+ if (baseVdu == null || baseVdu.getStatus().getState() == VduStateType.NOTFOUND) {
+ String error = "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, error, "VDU", "queryVdu(Base)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Base Module 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 base module");
+ baseModuleOutputs = baseVdu.getOutputs();
+ this.sendMapToDebug(baseModuleOutputs, "baseModuleOutputs");
+ }
+ }
+ }
+
+
+ // NOTE: For this section, heatTemplate is used for all template artifacts.
+ // In final implementation (post-POC), the template object would either be generic or there would
+ // be a separate DB Table/Object for different sub-orchestrators.
+
+ // NOTE: The template is fixed for the VF Module. The environment is part of the customization.
+
+ HeatTemplate heatTemplate = null;
+ HeatEnvironment heatEnvironment = null;
+ if (isVolumeRequest) {
+ heatTemplate = vfModule.getVolumeHeatTemplate();
+ heatEnvironment = vfModuleCust.getVolumeHeatEnv();
+ } else {
+ heatTemplate = vfModule.getModuleHeatTemplate();
+ heatEnvironment = vfModuleCust.getHeatEnvironment();
+ }
+
+ if (heatTemplate == null) {
+ String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestType;
+ LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vfModuleType, "VNF", "", 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 {
+ LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
+ }
+
+ if (heatEnvironment == null) {
+ String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
+ LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", "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.getEnvironment());
+ }
+
+
+ // Create the combined set of parameters from the incoming request, base-module outputs,
+ // volume-module outputs. Also, convert all variables to their native object types.
+
+ HashMap<String, Object> goldenInputs = new HashMap<String,Object>();
+ List<String> extraInputs = new ArrayList<String>();
+
+ Boolean skipInputChecks = false;
+
+ if (skipInputChecks) {
+ goldenInputs = new HashMap<String,Object>();
+ for (String key : inputs.keySet()) {
+ goldenInputs.put(key, inputs.get(key));
+ }
+ }
+ else {
+ // Build maps for the parameters (including aliases) to simplify checks
+ HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
+
+ Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
+ LOGGER.debug("paramSet has " + paramSet.size() + " entries");
+
+ for (HeatTemplateParam htp : paramSet) {
+ params.put(htp.getParamName(), htp);
+
+ // Include aliases.
+ String alias = htp.getParamAlias();
+ if (alias != null && !alias.equals("") && !params.containsKey(alias)) {
+ params.put(alias, htp);
+ }
+ }
+
+ // First, convert all inputs to their "template" type
+ for (String key : inputs.keySet()) {
+ if (params.containsKey(key)) {
+ Object value = convertInputValue(inputs.get(key), params.get(key));
+ if (value != null) {
+ goldenInputs.put(key, value);
+ }
+ else {
+ LOGGER.debug("Failed to convert input " + key + "='" + inputs.get(key) + "' to " + params.get(key).getParamType());
+ }
+ } else {
+ extraInputs.add(key);
+ }
+ }
+
+ if (!extraInputs.isEmpty()) {
+ LOGGER.debug("Ignoring extra inputs: " + extraInputs);
+ }
+
+ // Next add in Volume Group Outputs if there are any. Copy directly without conversions.
+ if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
+ for (String key : volumeGroupOutputs.keySet()) {
+ if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
+ goldenInputs.put(key, volumeGroupOutputs.get(key));
+ }
+ }
+ }
+
+ // Next add in Base Module Outputs if there are any. Copy directly without conversions.
+ if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
+ for (String key : baseModuleOutputs.keySet()) {
+ if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
+ goldenInputs.put(key, baseModuleOutputs.get(key));
+ }
+ }
+ }
+
+ // TODO: The model should support a mechanism to pre-assign default parameter values
+ // per "customization" (i.e. usage) of a given module. In HEAT, this is specified by
+ // an Environment file. There is not a general mechanism in the model to handle this.
+ // For the general case, any such parameter/values can be added dynamically to the
+ // inputs (only if not already specified).
+
+
+ // Check that required parameters have been supplied from any of the sources
+ String missingParams = null;
+ boolean checkRequiredParameters = true;
+ try {
+ String propertyString = this.environment.getProperty(MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS);
+ if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
+ checkRequiredParameters = false;
+ LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
+ + MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS);
+ }
+ } catch (Exception e) {
+ // No problem - default is true
+ LOGGER.debug ("An exception occured trying to get property " + MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS, e);
+ }
+
+ // Do the actual parameter checking.
+ // Include looking at the ENV file as a valid definition of a parameter value.
+ // TODO: This handling of ENV applies only to Heat. A general mechanism to
+ // support pre-set parameter/values does not yet exist in the model.
+ //
+ StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
+ MsoHeatEnvironmentEntry mhee = new MsoHeatEnvironmentEntry (sb);
+ for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
+ if (parm.isRequired () && (!goldenInputs.containsKey (parm.getParamName ()))) {
+ 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 ();
+ }
+ }
+ }
+ }
+
+ 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, "VDU", "", 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 [" + missingParams + "] - but checkRequiredParameters is false - will not block");
+ }
+ } else {
+ LOGGER.debug ("No missing parameters found - ok to proceed");
+ }
+
+ } // NOTE: END PARAMETER CHECKING
+
+
+ // Here we go... ready to deploy the VF Module.
+ long instantiateVduStartTime = System.currentTimeMillis ();
+ if (backout == null) backout = true;
+
+ try {
+ // Construct the VDU Model structure to pass to the targeted VduPlugin
+ VduModelInfo vduModel = null;
+ if (! isVolumeRequest) {
+ vduModel = vduMapper.mapVfModuleCustomizationToVdu(vfModuleCust);
+ } else {
+ vduModel = vduMapper.mapVfModuleCustVolumeToVdu(vfModuleCust);
+ }
+
+ // Invoke the VduPlugin to instantiate the VF Module
+ vduInstance = vduPlugin.instantiateVdu(cloudInfo, vfModuleName, goldenInputs, vduModel, backout);
+
+ LOGGER.recordMetricEvent (instantiateVduStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from VduPlugin", "VDU", "instantiateVdu", vfModuleName);
+ }
+ catch (VduException me) {
+ // Failed to instantiate the VDU.
+ me.addContext ("CreateVFModule");
+ String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (instantiateVduStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "instantiateVdu", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "VDU", "", MsoLogger.ErrorCode.DataError, "MsoException - instantiateVdu", me);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ // Convert to a generic VnfException
+ throw new VnfException (me);
+ }
+ catch (NullPointerException npe) {
+ String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
+ LOGGER.recordMetricEvent (instantiateVduStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error, "VDU", "instantiateVdu", vfModuleName);
+ LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "VDU", "", MsoLogger.ErrorCode.DataError, "NullPointerException - instantiateVdu", npe);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
+ LOGGER.debug("NULL POINTER EXCEPTION at vduPlugin.instantiateVdu", npe);
+ throw new VnfException ("NullPointerException during instantiateVdu");
+ }
+ catch (Exception e) {
+ String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + e;
+ LOGGER.recordMetricEvent (instantiateVduStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, error, "VDU", "instantiateVdu", vfModuleName);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, error);
+ LOGGER.debug("Unhandled exception at vduPlugin.instantiateVdu", e);
+ throw new VnfException("Exception during instantiateVdu: " + e.getMessage());
+ }
+
+
+ // Reach this point if create is successful.
+ // Populate remaining rollback info and response parameters.
+ vfRollback.setVnfCreated (true);
+ vfRollback.setVnfId (vduInstance.getVduInstanceId());
+ vnfId.value = vduInstance.getVduInstanceId();
+ outputs.value = copyStringOutputs (vduInstance.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 vfModuleId,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs) throws VnfException
+ {
+ MsoLogger.setLogContext (msoRequest);
+ MsoLogger.setServiceName ("DeleteVfModule");
+
+ LOGGER.debug ("Deleting VF Module " + vfModuleId + " in " + cloudSiteId + "/" + tenantId);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+
+ // Capture the output parameters on a delete, so need to query first
+ VduInstance vduInstance = null;
+ CloudInfo cloudInfo = new CloudInfo(cloudSiteId, tenantId, null);
+
+ // Use the VduPlugin.
+ VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
+
+ try {
+ vduInstance = vduPlugin.queryVdu (cloudInfo, vfModuleId);
+ LOGGER.recordMetricEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received VDU Query response", "VDU", "QueryVDU", vfModuleId);
+ }
+ catch (VduException e) {
+ // Failed to query the VDU due to a plugin exception.
+ // Convert to a generic VnfException
+ e.addContext ("QueryVFModule");
+ String error = "Query VfModule (VDU): " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + e;
+ LOGGER.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVNF", vfModuleId);
+ LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleId, cloudSiteId, tenantId, "VDU", "QueryVFModule", MsoLogger.ErrorCode.DataError, "Exception - queryVDU", e);
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
+ throw new VnfException (e);
+ }
+
+ // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
+ outputs.value = convertMapStringObjectToStringString(vduInstance.getOutputs());
+
+ // Use the VduPlugin to delete the VDU.
+ // The possible outcomes of deleteVdu are
+ // - a vnfInstance object with status of DELETED (success)
+ // - a vnfInstance object with status of NOTFOUND (VDU did not exist, treat as success)
+ // - a vnfInstance object with status of FAILED (error)
+ // Also, VduException could be thrown.
+ long subStartTime = System.currentTimeMillis ();
+ try {
+ // TODO: Get an appropriate timeout value - require access to the model
+ vduPlugin.deleteVdu(cloudInfo, vfModuleId, 5);
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from deleteVdu", "VDU", "DeleteVdu", vfModuleId);
+ } catch (VduException me) {
+ me.addContext ("DeleteVfModule");
+ // Convert to a generic VnfException
+ String error = "Delete VF: " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
+ LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "DeleteVdu", "DeleteVdu", vfModuleId);
+ LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vfModuleId, cloudSiteId, tenantId, "VDU", "DeleteVdu", MsoLogger.ErrorCode.DataError, "Exception - DeleteVdu: " + me.getMessage());
+ 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;
+ }
+
+ // Update VF Module not yet implemented for generic VDU plug-in model.
+ @Override
+ public void updateVfModule (String cloudSiteId,
+ String tenantId,
+ String vnfType,
+ String vnfVersion,
+ String vnfName,
+ String requestType,
+ String volumeGroupHeatStackId,
+ String baseVfHeatStackId,
+ String vfModuleStackId,
+ String modelCustomizationUuid,
+ Map <String, String> inputs,
+ MsoRequest msoRequest,
+ Holder <Map <String, String>> outputs,
+ Holder <VnfRollback> rollback) throws VnfException
+ {
+ // This operation is not currently supported for VduPlugin-orchestrated VF Modules.
+ LOGGER.debug ("Update VF Module command attempted but not supported");
+ throw new VnfException ("UpdateVfModule: Unsupported command", MsoExceptionCategory.USERDATA);
+ }
+
+ /*
+ * Dynamic selection of a VduPlugin version. For initial tests, base on the "orchestrator"
+ * defined for the target cloud. Should really be looking at the VNF Model (ochestration_mode)
+ * but we don't currently have access to that in Query and Delete cases.
+ */
+ private VduPlugin getVduPlugin (String cloudSiteId) {
+ Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite(cloudSiteId);
+ if (cloudSiteOp.isPresent()) {
+ CloudSite cloudSite = cloudSiteOp.get();
+ String orchestrator = cloudSite.getOrchestrator();
+
+ if (orchestrator.equalsIgnoreCase("CLOUDIFY")) {
+ return cloudifyUtils;
+ }
+ else if (orchestrator.equalsIgnoreCase("HEAT")) {
+ return heatUtils;
+ }
+ }
+
+ // Default - return HEAT plugin, though will fail later
+ return heatUtils;
+ }
+} \ No newline at end of file
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VfRollback.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VfRollback.java
new file mode 100644
index 0000000000..5dca8696ef
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VfRollback.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+
+import org.onap.so.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-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRest.java
new file mode 100644
index 0000000000..3e27361ed1
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRest.java
@@ -0,0 +1,691 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.Map;
+
+import javax.inject.Provider;
+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.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
+import org.onap.so.adapters.vnfrest.CreateVfModuleResponse;
+import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
+import org.onap.so.adapters.vnfrest.DeleteVfModuleResponse;
+import org.onap.so.adapters.vnfrest.QueryVfModuleResponse;
+import org.onap.so.adapters.vnfrest.RollbackVfModuleRequest;
+import org.onap.so.adapters.vnfrest.RollbackVfModuleResponse;
+import org.onap.so.adapters.vnfrest.UpdateVfModuleRequest;
+import org.onap.so.adapters.vnfrest.UpdateVfModuleResponse;
+import org.onap.so.adapters.vnfrest.VfModuleExceptionResponse;
+import org.onap.so.adapters.vnfrest.VfModuleRollback;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * 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")
+@Api(value = "/v1/vnfs", description = "root of vnf adapters restful web service")
+@Transactional
+@Component
+public class VnfAdapterRest {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, VnfAdapterRest.class);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+
+ @Autowired
+ private MsoVnfAdapterImpl vnfAdapter;
+ //TODO Logging, SkipAAI, CREATED flags, Integrate with BPEL, Auth,
+
+ @Autowired
+ @Qualifier("VnfBpel")
+ private Provider<BpelRestClient> bpelRestClientProvider;
+
+
+ /*
+ * 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 })
+ @ApiOperation(value = "DeleteVfModule",
+ response = Response.class,
+ notes = "Delete an existing vnfModule, DeleteVfModuleRequest JSON is required")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully deleted"),
+ @ApiResponse(code = 202, message = "delete vnfModule request has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "delete vnfModule failed, examine entity object for details") })
+ public Response deleteVfModule (
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "DeleteVfModuleRequest", required = true)
+ 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();
+ Holder<Map<String, String>> outputs = new Holder <> ();
+ 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(), outputs);
+ }
+ response = new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE, req.getMessageId(), outputs.value);
+ } 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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "QueryVfModule",
+ response = Response.class,
+ notes = "Query an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully queried"),
+ @ApiResponse(code = 500, message = "query vnfModule failed, examine entity object for details") })
+ public Response queryVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "cloudSiteId", required = true)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "tenantId", required = true)
+ @QueryParam("tenantId") String tenantId,
+ @ApiParam(value = "vfModuleName", required = true)
+ @QueryParam("vfModuleName") String vfModuleName, //RAA? Id in doc
+ @ApiParam(value = "skipAAI", required = true)
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @ApiParam(value = "msoRequest.requestId", required = true)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = true)
+ @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<>();
+ Holder<String> vfModuleId = new Holder<>();
+ Holder<VnfStatus> status = new Holder<>();
+ Holder<Map<String, String>> outputs = new Holder <> ();
+ 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 })
+ @ApiOperation(value = "CreateVfModule",
+ response = Response.class,
+ notes = "Create a vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully created"),
+ @ApiResponse(code = 202, message = "create vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "create vnfModule failed, examine entity object for details") })
+ public Response createVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "CreateVfModuleRequest", required = true)
+ 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 <> ();
+ Holder <Map <String, String>> outputs = new Holder <> ();
+ Holder <VnfRollback> vnfRollback = new Holder <> ();
+ 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(), req.getModelCustomizationUuid());
+ 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.getModelCustomizationUuid(),
+ req.getVfModuleParams(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getEnableBridge(),
+ 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) {
+ LOGGER.debug("Exception :",e);
+ eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ BpelRestClient bpelClient = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "UpdateVfModule",
+ response = Response.class,
+ notes = "Update an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully updated"),
+ @ApiResponse(code = 202, message = "update vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "update vnfModule failed, examine entity object for details") })
+ public Response updateVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "UpdateVfModuleRequest", required = true)
+ 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 <> ();
+ Holder <Map <String, String>> outputs = new Holder <> ();
+ Holder <VnfRollback> vnfRollback = new Holder <> ();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in updateVf - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ vnfAdapter.updateVfModule (req.getCloudSiteId(),
+ req.getTenantId(),
+ //req.getVnfType(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVfModuleName(),
+ req.getRequestType(),
+ req.getVolumeGroupStackId(),
+ req.getBaseVfModuleStackId(),
+ req.getVfModuleStackId(),
+ req.getModelCustomizationUuid(),
+ req.getVfModuleParams(),
+ req.getMsoRequest(),
+ outputs,
+ vnfRollback);
+
+ response = new UpdateVfModuleResponse(req.getVnfId(), req.getVfModuleId(),
+ vfModuleStackId.value, outputs.value, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "RollbackVfModule",
+ response = Response.class,
+ notes = "Rollback an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully rolled back"),
+ @ApiResponse(code = 202, message = "rollback vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "rollback vnfModule failed, examine entity object for details") })
+ public Response rollbackVfModule (
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "RollbackVfModuleRequest", required = true)
+ //@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, 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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost (getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("RollbackVfModulesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+} \ No newline at end of file
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java
new file mode 100644
index 0000000000..876aae8a37
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+import java.util.Optional;
+
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.CloudSite;
+import org.onap.so.logger.MsoLogger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class VnfAdapterRestUtils
+{
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, VnfAdapterRestUtils.class);
+
+ @Autowired
+ private CloudConfig cloudConfig;
+
+ @Autowired
+ private MsoVnfCloudifyAdapterImpl cloudifyImpl;
+
+ @Autowired
+ private MsoVnfAdapterImpl vnfImpl;
+
+ /*
+ * Choose which implementation of VNF Adapter to use, based on the orchestration mode.
+ * Currently, the two supported orchestrators are HEAT and CLOUDIFY.
+ */
+ public MsoVnfAdapter getVnfAdapterImpl (String mode, String cloudSiteId)
+ {
+ // First, determine the orchestration mode to use.
+ // If was explicitly provided as a parameter, use that. Else if specified for the
+ // cloudsite, use that. Otherwise, the default is the (original) HEAT-based impl.
+
+ LOGGER.debug ("Entered GetVnfAdapterImpl: mode=" + mode + ", cloudSite=" + cloudSiteId);
+
+ if (mode == null) {
+ // Didn't get an explicit mode type requested.
+ // Use the CloudSite to determine which Impl to use, based on whether the target cloutSite
+ // has a CloudifyManager assigned to it
+ Optional<CloudSite> cloudSite = cloudConfig.getCloudSite(cloudSiteId);
+ if (cloudSite.isPresent()) {
+ LOGGER.debug("Got CloudSite: " + cloudSite.toString());
+ if (cloudConfig.getCloudifyManager(cloudSite.get().getCloudifyId()) != null) {
+ mode = "CLOUDIFY";
+ } else {
+ mode = "HEAT";
+ }
+ }
+ }
+
+ LOGGER.debug ("GetVnfAdapterImpl: mode=" + mode);
+
+ MsoVnfAdapter vnfAdapter = null;
+
+ // TODO: Make this more dynamic (e.g. Service Loader)
+ if ("CLOUDIFY".equalsIgnoreCase(mode)) {
+ LOGGER.debug ("GetVnfAdapterImpl: Return Cloudify Adapter");
+ vnfAdapter = cloudifyImpl;
+ }
+ else if ("HEAT".equalsIgnoreCase(mode)) {
+ LOGGER.debug ("GetVnfAdapterImpl: Return Heat Adapter");
+ vnfAdapter = vnfImpl;
+ }
+ else {
+ // Don't expect this, but default is the HEAT adapter
+ LOGGER.debug ("GetVnfAdapterImpl: Return Default (Heat) Adapter");
+ vnfAdapter = vnfImpl;
+ }
+
+ return vnfAdapter;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestV2.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestV2.java
new file mode 100644
index 0000000000..143f169c84
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestV2.java
@@ -0,0 +1,704 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.Map;
+
+import javax.inject.Provider;
+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.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
+import org.onap.so.adapters.vnfrest.CreateVfModuleResponse;
+import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
+import org.onap.so.adapters.vnfrest.DeleteVfModuleResponse;
+import org.onap.so.adapters.vnfrest.QueryVfModuleResponse;
+import org.onap.so.adapters.vnfrest.RollbackVfModuleRequest;
+import org.onap.so.adapters.vnfrest.RollbackVfModuleResponse;
+import org.onap.so.adapters.vnfrest.UpdateVfModuleRequest;
+import org.onap.so.adapters.vnfrest.UpdateVfModuleResponse;
+import org.onap.so.adapters.vnfrest.VfModuleExceptionResponse;
+import org.onap.so.adapters.vnfrest.VfModuleRollback;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * This class services calls to the REST interface for VF Modules (http://host:port/vnfs/rest/v2/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___
+ *
+ * V2 incorporates run-time selection of sub-orchestrator implementation (Heat or Cloudify)
+ * based on the target cloud.
+ */
+@Path("/v2/vnfs")
+@Api(value = "/v2/vnfs", description = "root of vnf adapters restful web service v2")
+@Component
+public class VnfAdapterRestV2 {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, VnfAdapterRestV2.class);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+
+ @Autowired
+ private VnfAdapterRestUtils vnfAdapterRestUtils;
+
+ @Autowired
+ @Qualifier("VnfBpel")
+ private Provider<BpelRestClient> bpelRestClientProvider;
+
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v2/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 })
+ @ApiOperation(value = "DeleteVfModule",
+ response = Response.class,
+ notes = "Delete an existing vnfModule, DeleteVfModuleRequest JSON is required")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully deleted"),
+ @ApiResponse(code = 202, message = "delete vnfModule request has been accepted (async only)"),
+ @ApiResponse(code = 500, message = "delete vnfModule failed, examine entity object for details") })
+ public Response deleteVfModule (
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "DeleteVfModuleRequest", required = true)
+ 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, mode);
+ 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;
+ private String mode;
+
+ public DeleteVfModuleTask(DeleteVfModuleRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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();
+ Holder<Map<String, String>> outputs = new Holder <Map <String, String>> ();
+ if (cloudsite != null && !cloudsite.equals(TESTING_KEYWORD)) {
+ //vnfAdapter.deleteVnf (req.getCloudSiteId(), req.getTenantId(), req.getVfModuleStackId(), req.getMsoRequest());
+ // Support different Adapter Implementations
+ MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsite);
+ adapter.deleteVfModule (req.getCloudSiteId(), req.getTenantId(), req.getVfModuleStackId(), req.getMsoRequest(), outputs);
+ }
+ response = new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE, req.getMessageId(), outputs.value);
+ } 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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("Delete vfModule exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v2/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 })
+ @ApiOperation(value = "QueryVfModule",
+ response = Response.class,
+ notes = "Query an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully queried"),
+ @ApiResponse(code = 500, message = "query vnfModule failed, examine entity object for details") })
+ public Response queryVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "cloudSiteId", required = true)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "tenantId", required = true)
+ @QueryParam("tenantId") String tenantId,
+ @ApiParam(value = "vfModuleName", required = true)
+ @QueryParam("vfModuleName") String vfModuleName, //RAA? Id in doc
+ @ApiParam(value = "skipAAI", required = true)
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @ApiParam(value = "msoRequest.requestId", required = true)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = true)
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode)
+ {
+ //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>> ();
+
+ // Support different Adapter Implementations
+ MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
+ adapter.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/v2/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 })
+ @ApiOperation(value = "CreateVfModule",
+ response = Response.class,
+ notes = "Create a vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully created"),
+ @ApiResponse(code = 202, message = "create vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "create vnfModule failed, examine entity object for details") })
+ public Response createVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "CreateVfModuleRequest", required = true)
+ 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, mode);
+ 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;
+ private String mode;
+
+ public CreateVfModuleTask(CreateVfModuleRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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 cloudsiteId = req.getCloudSiteId();
+ if (cloudsiteId != null && cloudsiteId.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, cloudsiteId,
+ true, false, new MsoRequest("reqid", "svcid"),
+ req.getVolumeGroupId(), req.getVolumeGroupId(), req.getRequestType(), req.getModelCustomizationUuid());
+ vfModuleStackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
+ outputs.value = VolumeAdapterRest.testMap();
+ } else {
+ // Support different Adapter Implementations
+ MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
+ adapter.createVfModule(req.getCloudSiteId(),
+ req.getTenantId(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVfModuleName(),
+ req.getRequestType(),
+ req.getVolumeGroupStackId(),
+ req.getBaseVfModuleStackId(),
+ req.getModelCustomizationUuid(),
+ req.getVfModuleParams(),
+ req.getFailIfExists(),
+ req.getBackout(),
+ req.getEnableBridge(),
+ 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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "UpdateVfModule",
+ response = Response.class,
+ notes = "Update an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully updated"),
+ @ApiResponse(code = 202, message = "update vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "update vnfModule failed, examine entity object for details") })
+ public Response updateVfModule(
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "UpdateVfModuleRequest", required = true)
+ final UpdateVfModuleRequest req)
+ {
+ LOGGER.debug("Update VfModule enter: " + req.toJsonString());
+ UpdateVfModulesTask task = new UpdateVfModulesTask(req, mode);
+ 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;
+ private String mode;
+
+ public UpdateVfModulesTask(UpdateVfModuleRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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);
+
+ String cloudsiteId = req.getCloudSiteId();
+
+ // Support different Adapter Implementations
+ MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
+ adapter.updateVfModule (req.getCloudSiteId(),
+ req.getTenantId(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVfModuleName(),
+ req.getRequestType(),
+ req.getVolumeGroupStackId(),
+ req.getBaseVfModuleId(),
+ req.getVfModuleStackId(),
+ req.getModelCustomizationUuid(),
+ 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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost (getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("Update VfModule exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+ /*
+ * URL:http://localhost:8080/vnfs/rest/v2/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 })
+ @ApiOperation(value = "RollbackVfModule",
+ response = Response.class,
+ notes = "Rollback an existing vnfModule")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfModule has been successfully rolled back"),
+ @ApiResponse(code = 202, message = "rollback vnfModule request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "rollback vnfModule failed, examine entity object for details") })
+ public Response rollbackVfModule (
+ @ApiParam(value = "aaiVnfId", required = true)
+ @PathParam("aaiVnfId") String aaiVnfId,
+ @ApiParam(value = "aaiVfModuleId", required = true)
+ @PathParam("aaiVfModuleId") String aaiVfModuleId,
+ @ApiParam(value = "RollbackVfModuleRequest", required = true)
+ //@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, vmr.isVfModuleCreated(),
+ vmr.getMsoRequest(), null, null, null, null);
+
+ // Support multiple adapter implementations
+ MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl (vmr.getMode(), vmr.getCloudSiteId());
+ adapter.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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost (getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("RollbackVfModulesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRest.java
new file mode 100644
index 0000000000..b4b5894491
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRest.java
@@ -0,0 +1,646 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Provider;
+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.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.adapters.vnfrest.CreateVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.CreateVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.DeleteVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.DeleteVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.QueryVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.RollbackVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.RollbackVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.UpdateVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.UpdateVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.VolumeGroupExceptionResponse;
+import org.onap.so.adapters.vnfrest.VolumeGroupRollback;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * 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")
+@Api(value = "/v1/volume-groups", description = "root of volume-groups adapters restful web service")
+@Component
+public class VolumeAdapterRest {
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA, VolumeAdapterRest.class);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+
+ @Autowired
+ private MsoVnfAdapterImpl vnfAdapter;
+
+ @Autowired
+ @Qualifier("VnfBpel")
+ private Provider<BpelRestClient> bpelRestClientProvider;
+
+ @POST
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "CreateVNFVolumes",
+ response = Response.class,
+ notes = "Create a new vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully created"),
+ @ApiResponse(code = 202, message = "create vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "create vnfVolume failed, examine entity object for details") })
+ public Response createVNFVolumes(
+ @ApiParam(value = "CreateVolumeGroupRequest", required = true)
+ 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<>();
+ Holder<Map<String, String>> outputs = new Holder<>();
+ Holder<VnfRollback> vnfRollback = new Holder<>();
+ 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.getModelCustomizationUuid(),
+ req.getVolumeGroupParams(), //inputs,
+ req.getFailIfExists(), //failIfExists,
+ req.getSuppressBackout(), //backout,
+ req.getEnableBridge(),
+ 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) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "DeleteVNFVolumes",
+ response = Response.class,
+ notes = "Delete an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully deleted"),
+ @ApiResponse(code = 202, message = "delete vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "delete vnfVolume failed, examine entity object for details") })
+ public Response deleteVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "DeleteVolumeGroupRequest", required = true)
+ 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) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "RollbackVNFVolumes",
+ response = Response.class,
+ notes = "Delete an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully rolled back"),
+ @ApiResponse(code = 202, message = "rollback vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "rollback vnfVolume failed, examine entity object for details") })
+ public Response rollbackVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "RollbackVolumeGroupRequest", required = true)
+ 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, null);
+ vnfAdapter.rollbackVnf(vrb);
+ response = new RollbackVolumeGroupResponse(true, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "UpdateVNFVolumes",
+ response = Response.class,
+ notes = "Update an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully updated"),
+ @ApiResponse(code = 202, message = "update vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "update vnfVolume failed, examine entity object for details") })
+ public Response updateVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "UpdateVolumeGroupRequest", required = true)
+ 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 {
+ Holder<Map<String, String>> outputs = new Holder<> ();
+ Holder<VnfRollback> vnfRollback = new Holder<> ();
+ 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.getModelCustomizationUuid(),
+ req.getVolumeGroupParams(),
+ req.getMsoRequest(),
+ outputs,
+ vnfRollback);
+ }
+ response = new UpdateVolumeGroupResponse(
+ req.getVolumeGroupId(), req.getVolumeGroupStackId(),
+ outputs.value, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("UpdateVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @GET
+ @Path("{aaiVolumeGroupId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "QueryVNFVolumes",
+ response = Response.class,
+ notes = "Query an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully queried"),
+ @ApiResponse(code = 500, message = "query vnfVolume failed, examine entity object for details") })
+ public Response queryVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "cloudSiteId", required = true)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "tenantId", required = true)
+ @QueryParam("tenantId") String tenantId,
+ @ApiParam(value = "volumeGroupStackId", required = true)
+ @QueryParam("volumeGroupStackId") String volumeGroupStackId,
+ @ApiParam(value = "skipAAI", required = true)
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @ApiParam(value = "msoRequest.requestId", required = true)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = true)
+ @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<>();
+ Holder<String> vfModuleId = new Holder<>();
+ Holder<VnfStatus> status = new Holder<>();
+ Holder<Map<String, String>> outputs = new Holder<>();
+ 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<>();
+ m.put("mickey", "7");
+ m.put("clyde", "10");
+ m.put("wayne", "99");
+ return m;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRestV2.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRestV2.java
new file mode 100644
index 0000000000..3f3a312e12
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VolumeAdapterRestV2.java
@@ -0,0 +1,648 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Provider;
+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.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.adapters.vnfrest.CreateVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.CreateVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.DeleteVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.DeleteVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.QueryVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.RollbackVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.RollbackVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.UpdateVolumeGroupRequest;
+import org.onap.so.adapters.vnfrest.UpdateVolumeGroupResponse;
+import org.onap.so.adapters.vnfrest.VolumeGroupExceptionResponse;
+import org.onap.so.adapters.vnfrest.VolumeGroupRollback;
+import org.onap.so.entity.MsoRequest;
+import org.onap.so.logger.MessageEnum;
+import org.onap.so.logger.MsoLogger;
+import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.beans.VnfStatus;
+import org.onap.so.openstack.exceptions.MsoExceptionCategory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * 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___
+ *
+ * V2 incorporates run-time selection of sub-orchestrator implementation (Heat or Cloudify)
+ * based on the target cloud.
+ */
+@Path("/v2/volume-groups")
+@Api(value = "/v2/volume-groups", description = "root of volume-groups adapters restful web service v2")
+@Component
+public class VolumeAdapterRestV2 {
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA, VolumeAdapterRestV2.class);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+
+ @Autowired
+ private VnfAdapterRestUtils vnfAdapterRestUtils;
+
+ @Autowired
+ @Qualifier("VnfBpel")
+ private Provider<BpelRestClient> bpelRestClientProvider;
+
+ @POST
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "CreateVNFVolumes",
+ response = Response.class,
+ notes = "Create a new vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully created"),
+ @ApiResponse(code = 202, message = "create vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "create vnfVolume failed, examine entity object for details") })
+ public Response createVNFVolumes(
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "CreateVolumeGroupRequest", required = true)
+ final CreateVolumeGroupRequest req)
+ {
+ LOGGER.debug("createVNFVolumes enter: " + req.toJsonString());
+ CreateVNFVolumesTask task = new CreateVNFVolumesTask(req, mode);
+ 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;
+ private String mode;
+
+ public CreateVNFVolumesTask(CreateVolumeGroupRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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<>();
+ Holder<Map<String, String>> outputs = new Holder<>();
+ Holder<VnfRollback> vnfRollback = new Holder<>();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in createVfModuleVolumes - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ String cloudsiteId = req.getCloudSiteId();
+ if (cloudsiteId != null && cloudsiteId.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 {
+ // Support different Adapter Implementations
+ MsoVnfAdapter vnfAdapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
+ vnfAdapter.createVfModule(
+ req.getCloudSiteId(), //cloudSiteId,
+ req.getTenantId(), //tenantId,
+ completeVnfVfModuleType, //vnfType,
+ req.getVnfVersion(), //vnfVersion,
+ req.getVolumeGroupName(), //vnfName,
+ "VOLUME", //requestType,
+ null, //volumeGroupHeatStackId,
+ null, //baseVfHeatStackId,
+ req.getModelCustomizationUuid(),
+ req.getVolumeGroupParams(), //inputs,
+ req.getFailIfExists(), //failIfExists,
+ req.getSuppressBackout(), //backout,
+ req.getEnableBridge(),
+ req.getMsoRequest(), // msoRequest,
+ stackId,
+ outputs,
+ vnfRollback);
+ }
+
+ VolumeGroupRollback rb = new VolumeGroupRollback(
+ req.getVolumeGroupId(),
+ stackId.value,
+ vnfRollback.value.getVnfCreated(),
+ req.getTenantId(),
+ req.getCloudSiteId(),
+ req.getMsoRequest(),
+ req.getMessageId());
+
+ response = new CreateVolumeGroupResponse(
+ req.getVolumeGroupId(),
+ stackId.value,
+ vnfRollback.value.getVnfCreated(),
+ outputs.value,
+ rb,
+ req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "DeleteVNFVolumes",
+ response = Response.class,
+ notes = "Delete an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully deleted"),
+ @ApiResponse(code = 202, message = "delete vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "delete vnfVolume failed, examine entity object for details") })
+ public Response deleteVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "DeleteVolumeGroupRequest", required = true)
+ 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, mode);
+ 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;
+ private String mode;
+
+ public DeleteVNFVolumesTask(DeleteVolumeGroupRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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");
+ String cloudSiteId = req.getCloudSiteId();
+ try {
+ if (! cloudSiteId.equals(TESTING_KEYWORD)) {
+ // Support different Adapter Implementations
+ MsoVnfAdapter vnfAdapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
+ vnfAdapter.deleteVnf(req.getCloudSiteId(), req.getTenantId(), req.getVolumeGroupStackId(), req.getMsoRequest());
+ }
+ response = new DeleteVolumeGroupResponse(true, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ 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 })
+ @ApiOperation(value = "RollbackVNFVolumes",
+ response = Response.class,
+ notes = "Delete an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully rolled back"),
+ @ApiResponse(code = 202, message = "rollback vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "rollback vnfVolume failed, examine entity object for details") })
+ public Response rollbackVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "RollbackVolumeGroupRequest", required = true)
+ 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("RollbackVNFVolumesTask start");
+ try {
+ VolumeGroupRollback vgr = req.getVolumeGroupRollback();
+ VnfRollback vrb = new VnfRollback(
+ vgr.getVolumeGroupStackId(), vgr.getTenantId(), vgr.getCloudSiteId(), true, true,
+ vgr.getMsoRequest(), null, null, null, null);
+
+ // Support different Adapter Implementations
+ MsoVnfAdapter vnfAdapter = vnfAdapterRestUtils.getVnfAdapterImpl(vrb.getMode(), vrb.getCloudSiteId());
+ vnfAdapter.rollbackVnf(vrb);
+ response = new RollbackVolumeGroupResponse(true, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("RollbackVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+
+ }
+
+ @PUT
+ @Path("{aaiVolumeGroupId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "UpdateVNFVolumes",
+ response = Response.class,
+ notes = "Update an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully updated"),
+ @ApiResponse(code = 202, message = "update vnfVolume request has been successfully accepted (async only)"),
+ @ApiResponse(code = 500, message = "update vnfVolume failed, examine entity object for details") })
+ public Response updateVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode,
+ @ApiParam(value = "UpdateVolumeGroupRequest", required = true)
+ 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, mode);
+ 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;
+ private String mode;
+
+ public UpdateVNFVolumesTask(UpdateVolumeGroupRequest req, String mode) {
+ this.req = req;
+ this.sendxml = true; // can be set with a field or header later
+ this.mode = mode;
+ }
+ 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 {
+ Holder<Map<String, String>> outputs = new Holder<> ();
+ Holder<VnfRollback> vnfRollback = new Holder<> ();
+ String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
+ LOGGER.debug("in updateVfModuleVolume - completeVnfVfModuleType=" + completeVnfVfModuleType);
+
+ if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ outputs.value = testMap();
+ } else {
+ // Support different Adapter Implementations
+ MsoVnfAdapter vnfAdapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, req.getCloudSiteId());
+ vnfAdapter.updateVfModule (req.getCloudSiteId(),
+ req.getTenantId(),
+ //req.getVnfType(),
+ completeVnfVfModuleType,
+ req.getVnfVersion(),
+ req.getVolumeGroupStackId(),
+ "VOLUME",
+ null,
+ null,
+ req.getVolumeGroupStackId(),
+ req.getModelCustomizationUuid(),
+ req.getVolumeGroupParams(),
+ req.getMsoRequest(),
+ outputs,
+ vnfRollback);
+ }
+ response = new UpdateVolumeGroupResponse(
+ req.getVolumeGroupId(), req.getVolumeGroupStackId(),
+ outputs.value, req.getMessageId());
+ } catch (VnfException e) {
+ LOGGER.debug("Exception :",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 = bpelRestClientProvider.get();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("UpdateVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @GET
+ @Path("{aaiVolumeGroupId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @ApiOperation(value = "QueryVNFVolumes",
+ response = Response.class,
+ notes = "Query an existing vnfVolume")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "vnfVolume has been successfully queried"),
+ @ApiResponse(code = 500, message = "query vnfVolume failed, examine entity object for details") })
+ public Response queryVNFVolumes(
+ @ApiParam(value = "aaiVolumeGroupId", required = true)
+ @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
+ @ApiParam(value = "cloudSiteId", required = true)
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @ApiParam(value = "tenantId", required = true)
+ @QueryParam("tenantId") String tenantId,
+ @ApiParam(value = "volumeGroupStackId", required = true)
+ @QueryParam("volumeGroupStackId") String volumeGroupStackId,
+ @ApiParam(value = "skipAAI", required = true)
+ @QueryParam("skipAAI") Boolean skipAAI,
+ @ApiParam(value = "msoRequest.requestId", required = true)
+ @QueryParam("msoRequest.requestId") String requestId,
+ @ApiParam(value = "msoRequest.serviceInstanceId", required = true)
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
+ @ApiParam(value = "mode", required = true)
+ @QueryParam("mode") String mode
+ )
+ {
+ //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<>();
+ Holder<String> vfModuleId = new Holder<>();
+ Holder<VnfStatus> status = new Holder<>();
+ Holder<Map<String, String>> outputs = new Holder<>();
+ 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 {
+ // Support different Adapter Implementations
+ MsoVnfAdapter vnfAdapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
+ 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<>();
+ m.put("mickey", "7");
+ m.put("clyde", "10");
+ m.put("wayne", "99");
+ return m;
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/CreateVnfNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/CreateVnfNotification.java
new file mode 100644
index 0000000000..39bd3ebf61
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/CreateVnfNotification.java
@@ -0,0 +1,410 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for createVnfNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="createVnfNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/vnfNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="vnfId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="outputs" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="rollback" type="{http://org.onap.so/vnfNotify}vnfRollback" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "createVnfNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "vnfId",
+ "outputs",
+ "rollback"
+})
+public class CreateVnfNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected String vnfId;
+ protected CreateVnfNotification.Outputs outputs;
+ protected VnfRollback rollback;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the vnfId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVnfId() {
+ return vnfId;
+ }
+
+ /**
+ * Sets the value of the vnfId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVnfId(String value) {
+ this.vnfId = value;
+ }
+
+ /**
+ * Gets the value of the outputs property.
+ *
+ * @return
+ * possible object is
+ * {@link CreateVnfNotification.Outputs }
+ *
+ */
+ public CreateVnfNotification.Outputs getOutputs() {
+ return outputs;
+ }
+
+ /**
+ * Sets the value of the outputs property.
+ *
+ * @param value
+ * allowed object is
+ * {@link CreateVnfNotification.Outputs }
+ *
+ */
+ public void setOutputs(CreateVnfNotification.Outputs value) {
+ this.outputs = value;
+ }
+
+ /**
+ * Gets the value of the rollback property.
+ *
+ * @return
+ * possible object is
+ * {@link VnfRollback }
+ *
+ */
+ public VnfRollback getRollback() {
+ return rollback;
+ }
+
+ /**
+ * Sets the value of the rollback property.
+ *
+ * @param value
+ * allowed object is
+ * {@link VnfRollback }
+ *
+ */
+ public void setRollback(VnfRollback value) {
+ this.rollback = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class Outputs {
+
+ protected List<CreateVnfNotification.Outputs.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link CreateVnfNotification.Outputs.Entry }
+ *
+ *
+ */
+ public List<CreateVnfNotification.Outputs.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<CreateVnfNotification.Outputs.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/DeleteVnfNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/DeleteVnfNotification.java
new file mode 100644
index 0000000000..d8c533b041
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/DeleteVnfNotification.java
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for deleteVnfNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="deleteVnfNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/vnfNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "deleteVnfNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage"
+})
+public class DeleteVnfNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoExceptionCategory.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoExceptionCategory.java
new file mode 100644
index 0000000000..73642a7f44
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoExceptionCategory.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for msoExceptionCategory.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p>
+ * <pre>
+ * &lt;simpleType name="msoExceptionCategory">
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * &lt;enumeration value="OPENSTACK"/>
+ * &lt;enumeration value="IO"/>
+ * &lt;enumeration value="INTERNAL"/>
+ * &lt;enumeration value="USERDATA"/>
+ * &lt;/restriction>
+ * &lt;/simpleType>
+ * </pre>
+ *
+ */
+@XmlType(name = "msoExceptionCategory")
+@XmlEnum
+public enum MsoExceptionCategory {
+
+ OPENSTACK,
+ IO,
+ INTERNAL,
+ USERDATA;
+
+ public String value() {
+ return name();
+ }
+
+ public static MsoExceptionCategory fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoRequest.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoRequest.java
new file mode 100644
index 0000000000..a4253b0cef
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/MsoRequest.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for msoRequest complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="msoRequest">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="requestId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="serviceInstanceId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "msoRequest", propOrder = {
+ "requestId",
+ "serviceInstanceId"
+})
+public class MsoRequest {
+
+ protected String requestId;
+ protected String serviceInstanceId;
+
+ /**
+ * Gets the value of the requestId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Sets the value of the requestId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setRequestId(String value) {
+ this.requestId = value;
+ }
+
+ /**
+ * Gets the value of the serviceInstanceId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getServiceInstanceId() {
+ return serviceInstanceId;
+ }
+
+ /**
+ * Sets the value of the serviceInstanceId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setServiceInstanceId(String value) {
+ this.serviceInstanceId = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/ObjectFactory.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/ObjectFactory.java
new file mode 100644
index 0000000000..0ab0fde747
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/ObjectFactory.java
@@ -0,0 +1,208 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.onap.so.adapters.vnf.async.client package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _QueryVnfNotification_QNAME = new QName("http://org.onap.so/vnfNotify", "queryVnfNotification");
+ private final static QName _RollbackVnfNotification_QNAME = new QName("http://org.onap.so/vnfNotify", "rollbackVnfNotification");
+ private final static QName _CreateVnfNotification_QNAME = new QName("http://org.onap.so/vnfNotify", "createVnfNotification");
+ private final static QName _DeleteVnfNotification_QNAME = new QName("http://org.onap.so/vnfNotify", "deleteVnfNotification");
+ private final static QName _UpdateVnfNotification_QNAME = new QName("http://org.onap.so/vnfNotify", "updateVnfNotification");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.onap.so.adapters.vnf.async.client
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link UpdateVnfNotification }
+ *
+ */
+ public UpdateVnfNotification createUpdateVnfNotification() {
+ return new UpdateVnfNotification();
+ }
+
+ /**
+ * Create an instance of {@link UpdateVnfNotification.Outputs }
+ *
+ */
+ public UpdateVnfNotification.Outputs createUpdateVnfNotificationOutputs() {
+ return new UpdateVnfNotification.Outputs();
+ }
+
+ /**
+ * Create an instance of {@link CreateVnfNotification }
+ *
+ */
+ public CreateVnfNotification createCreateVnfNotification() {
+ return new CreateVnfNotification();
+ }
+
+ /**
+ * Create an instance of {@link CreateVnfNotification.Outputs }
+ *
+ */
+ public CreateVnfNotification.Outputs createCreateVnfNotificationOutputs() {
+ return new CreateVnfNotification.Outputs();
+ }
+
+ /**
+ * Create an instance of {@link QueryVnfNotification }
+ *
+ */
+ public QueryVnfNotification createQueryVnfNotification() {
+ return new QueryVnfNotification();
+ }
+
+ /**
+ * Create an instance of {@link QueryVnfNotification.Outputs }
+ *
+ */
+ public QueryVnfNotification.Outputs createQueryVnfNotificationOutputs() {
+ return new QueryVnfNotification.Outputs();
+ }
+
+ /**
+ * Create an instance of {@link RollbackVnfNotification }
+ *
+ */
+ public RollbackVnfNotification createRollbackVnfNotification() {
+ return new RollbackVnfNotification();
+ }
+
+ /**
+ * Create an instance of {@link DeleteVnfNotification }
+ *
+ */
+ public DeleteVnfNotification createDeleteVnfNotification() {
+ return new DeleteVnfNotification();
+ }
+
+ /**
+ * Create an instance of {@link MsoRequest }
+ *
+ */
+ public MsoRequest createMsoRequest() {
+ return new MsoRequest();
+ }
+
+ /**
+ * Create an instance of {@link VnfRollback }
+ *
+ */
+ public VnfRollback createVnfRollback() {
+ return new VnfRollback();
+ }
+
+ /**
+ * Create an instance of {@link UpdateVnfNotification.Outputs.Entry }
+ *
+ */
+ public UpdateVnfNotification.Outputs.Entry createUpdateVnfNotificationOutputsEntry() {
+ return new UpdateVnfNotification.Outputs.Entry();
+ }
+
+ /**
+ * Create an instance of {@link CreateVnfNotification.Outputs.Entry }
+ *
+ */
+ public CreateVnfNotification.Outputs.Entry createCreateVnfNotificationOutputsEntry() {
+ return new CreateVnfNotification.Outputs.Entry();
+ }
+
+ /**
+ * Create an instance of {@link QueryVnfNotification.Outputs.Entry }
+ *
+ */
+ public QueryVnfNotification.Outputs.Entry createQueryVnfNotificationOutputsEntry() {
+ return new QueryVnfNotification.Outputs.Entry();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link QueryVnfNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/vnfNotify", name = "queryVnfNotification")
+ public JAXBElement<QueryVnfNotification> createQueryVnfNotification(QueryVnfNotification value) {
+ return new JAXBElement<QueryVnfNotification>(_QueryVnfNotification_QNAME, QueryVnfNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link RollbackVnfNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/vnfNotify", name = "rollbackVnfNotification")
+ public JAXBElement<RollbackVnfNotification> createRollbackVnfNotification(RollbackVnfNotification value) {
+ return new JAXBElement<RollbackVnfNotification>(_RollbackVnfNotification_QNAME, RollbackVnfNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link CreateVnfNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/vnfNotify", name = "createVnfNotification")
+ public JAXBElement<CreateVnfNotification> createCreateVnfNotification(CreateVnfNotification value) {
+ return new JAXBElement<CreateVnfNotification>(_CreateVnfNotification_QNAME, CreateVnfNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link DeleteVnfNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/vnfNotify", name = "deleteVnfNotification")
+ public JAXBElement<DeleteVnfNotification> createDeleteVnfNotification(DeleteVnfNotification value) {
+ return new JAXBElement<DeleteVnfNotification>(_DeleteVnfNotification_QNAME, DeleteVnfNotification.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link UpdateVnfNotification }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://org.onap.so/vnfNotify", name = "updateVnfNotification")
+ public JAXBElement<UpdateVnfNotification> createUpdateVnfNotification(UpdateVnfNotification value) {
+ return new JAXBElement<UpdateVnfNotification>(_UpdateVnfNotification_QNAME, UpdateVnfNotification.class, null, value);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/QueryVnfNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/QueryVnfNotification.java
new file mode 100644
index 0000000000..0fd701d4f6
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/QueryVnfNotification.java
@@ -0,0 +1,437 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for queryVnfNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="queryVnfNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/vnfNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="vnfExists" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ * &lt;element name="vnfId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="status" type="{http://org.onap.so/vnfNotify}vnfStatus" minOccurs="0"/>
+ * &lt;element name="outputs" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "queryVnfNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "vnfExists",
+ "vnfId",
+ "status",
+ "outputs"
+})
+public class QueryVnfNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected Boolean vnfExists;
+ protected String vnfId;
+ protected VnfStatus status;
+ protected QueryVnfNotification.Outputs outputs;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the vnfExists property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public Boolean isVnfExists() {
+ return vnfExists;
+ }
+
+ /**
+ * Sets the value of the vnfExists property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setVnfExists(Boolean value) {
+ this.vnfExists = value;
+ }
+
+ /**
+ * Gets the value of the vnfId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVnfId() {
+ return vnfId;
+ }
+
+ /**
+ * Sets the value of the vnfId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVnfId(String value) {
+ this.vnfId = value;
+ }
+
+ /**
+ * Gets the value of the status property.
+ *
+ * @return
+ * possible object is
+ * {@link VnfStatus }
+ *
+ */
+ public VnfStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the value of the status property.
+ *
+ * @param value
+ * allowed object is
+ * {@link VnfStatus }
+ *
+ */
+ public void setStatus(VnfStatus value) {
+ this.status = value;
+ }
+
+ /**
+ * Gets the value of the outputs property.
+ *
+ * @return
+ * possible object is
+ * {@link QueryVnfNotification.Outputs }
+ *
+ */
+ public QueryVnfNotification.Outputs getOutputs() {
+ return outputs;
+ }
+
+ /**
+ * Sets the value of the outputs property.
+ *
+ * @param value
+ * allowed object is
+ * {@link QueryVnfNotification.Outputs }
+ *
+ */
+ public void setOutputs(QueryVnfNotification.Outputs value) {
+ this.outputs = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class Outputs {
+
+ protected List<QueryVnfNotification.Outputs.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link QueryVnfNotification.Outputs.Entry }
+ *
+ *
+ */
+ public List<QueryVnfNotification.Outputs.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<QueryVnfNotification.Outputs.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/RollbackVnfNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/RollbackVnfNotification.java
new file mode 100644
index 0000000000..05947f5e62
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/RollbackVnfNotification.java
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for rollbackVnfNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="rollbackVnfNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/vnfNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "rollbackVnfNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage"
+})
+public class RollbackVnfNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/UpdateVnfNotification.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/UpdateVnfNotification.java
new file mode 100644
index 0000000000..13fa8cb0ef
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/UpdateVnfNotification.java
@@ -0,0 +1,383 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for updateVnfNotification complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="updateVnfNotification">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="exception" type="{http://org.onap.so/vnfNotify}msoExceptionCategory" minOccurs="0"/>
+ * &lt;element name="errorMessage" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="outputs" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="rollback" type="{http://org.onap.so/vnfNotify}vnfRollback" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "updateVnfNotification", propOrder = {
+ "messageId",
+ "completed",
+ "exception",
+ "errorMessage",
+ "outputs",
+ "rollback"
+})
+public class UpdateVnfNotification {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ protected boolean completed;
+ protected MsoExceptionCategory exception;
+ protected String errorMessage;
+ protected UpdateVnfNotification.Outputs outputs;
+ protected VnfRollback rollback;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the completed property.
+ *
+ */
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ /**
+ * Sets the value of the completed property.
+ *
+ */
+ public void setCompleted(boolean value) {
+ this.completed = value;
+ }
+
+ /**
+ * Gets the value of the exception property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public MsoExceptionCategory getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the value of the exception property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoExceptionCategory }
+ *
+ */
+ public void setException(MsoExceptionCategory value) {
+ this.exception = value;
+ }
+
+ /**
+ * Gets the value of the errorMessage property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the value of the errorMessage property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setErrorMessage(String value) {
+ this.errorMessage = value;
+ }
+
+ /**
+ * Gets the value of the outputs property.
+ *
+ * @return
+ * possible object is
+ * {@link UpdateVnfNotification.Outputs }
+ *
+ */
+ public UpdateVnfNotification.Outputs getOutputs() {
+ return outputs;
+ }
+
+ /**
+ * Sets the value of the outputs property.
+ *
+ * @param value
+ * allowed object is
+ * {@link UpdateVnfNotification.Outputs }
+ *
+ */
+ public void setOutputs(UpdateVnfNotification.Outputs value) {
+ this.outputs = value;
+ }
+
+ /**
+ * Gets the value of the rollback property.
+ *
+ * @return
+ * possible object is
+ * {@link VnfRollback }
+ *
+ */
+ public VnfRollback getRollback() {
+ return rollback;
+ }
+
+ /**
+ * Sets the value of the rollback property.
+ *
+ * @param value
+ * allowed object is
+ * {@link VnfRollback }
+ *
+ */
+ public void setRollback(VnfRollback value) {
+ this.rollback = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="entry" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "entry"
+ })
+ public static class Outputs {
+
+ protected List<UpdateVnfNotification.Outputs.Entry> entry;
+
+ /**
+ * Gets the value of the entry property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the entry property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getEntry().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link UpdateVnfNotification.Outputs.Entry }
+ *
+ *
+ */
+ public List<UpdateVnfNotification.Outputs.Entry> getEntry() {
+ if (entry == null) {
+ entry = new ArrayList<UpdateVnfNotification.Outputs.Entry>();
+ }
+ return this.entry;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "key",
+ "value"
+ })
+ public static class Entry {
+
+ protected String key;
+ protected String value;
+
+ /**
+ * Gets the value of the key property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Sets the value of the key property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setKey(String value) {
+ this.key = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify.java
new file mode 100644
index 0000000000..24370b4d79
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify.java
@@ -0,0 +1,177 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.jws.Oneway;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.ws.Action;
+import javax.xml.ws.RequestWrapper;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.9-b14002
+ * Generated source version: 2.2
+ *
+ */
+@WebService(name = "vnfAdapterNotify", targetNamespace = "http://org.onap.so/vnfNotify")
+@XmlSeeAlso({
+ ObjectFactory.class
+})
+public interface VnfAdapterNotify {
+
+
+ /**
+ *
+ * @param exception
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ */
+ @WebMethod
+ @Oneway
+ @RequestWrapper(localName = "rollbackVnfNotification", targetNamespace = "http://org.onap.so/vnfNotify", className = "org.onap.so.adapters.vnf.async.client.RollbackVnfNotification")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/rollbackVnfNotificationRequest")
+ public void rollbackVnfNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage);
+
+ /**
+ *
+ * @param exception
+ * @param outputs
+ * @param errorMessage
+ * @param vnfExists
+ * @param messageId
+ * @param completed
+ * @param vnfId
+ * @param status
+ */
+ @WebMethod
+ @Oneway
+ @RequestWrapper(localName = "queryVnfNotification", targetNamespace = "http://org.onap.so/vnfNotify", className = "org.onap.so.adapters.vnf.async.client.QueryVnfNotification")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/queryVnfNotificationRequest")
+ public void queryVnfNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "vnfExists", targetNamespace = "")
+ Boolean vnfExists,
+ @WebParam(name = "vnfId", targetNamespace = "")
+ String vnfId,
+ @WebParam(name = "status", targetNamespace = "")
+ VnfStatus status,
+ @WebParam(name = "outputs", targetNamespace = "")
+ org.onap.so.adapters.vnf.async.client.QueryVnfNotification.Outputs outputs);
+
+ /**
+ *
+ * @param exception
+ * @param outputs
+ * @param rollback
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ * @param vnfId
+ */
+ @WebMethod
+ @Oneway
+ @RequestWrapper(localName = "createVnfNotification", targetNamespace = "http://org.onap.so/vnfNotify", className = "org.onap.so.adapters.vnf.async.client.CreateVnfNotification")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/createVnfNotificationRequest")
+ public void createVnfNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "vnfId", targetNamespace = "")
+ String vnfId,
+ @WebParam(name = "outputs", targetNamespace = "")
+ org.onap.so.adapters.vnf.async.client.CreateVnfNotification.Outputs outputs,
+ @WebParam(name = "rollback", targetNamespace = "")
+ VnfRollback rollback);
+
+ /**
+ *
+ * @param exception
+ * @param outputs
+ * @param rollback
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ */
+ @WebMethod
+ @Oneway
+ @RequestWrapper(localName = "updateVnfNotification", targetNamespace = "http://org.onap.so/vnfNotify", className = "org.onap.so.adapters.vnf.async.client.UpdateVnfNotification")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/updateVnfNotificationRequest")
+ public void updateVnfNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage,
+ @WebParam(name = "outputs", targetNamespace = "")
+ org.onap.so.adapters.vnf.async.client.UpdateVnfNotification.Outputs outputs,
+ @WebParam(name = "rollback", targetNamespace = "")
+ VnfRollback rollback);
+
+ /**
+ *
+ * @param exception
+ * @param errorMessage
+ * @param messageId
+ * @param completed
+ */
+ @WebMethod
+ @Oneway
+ @RequestWrapper(localName = "deleteVnfNotification", targetNamespace = "http://org.onap.so/vnfNotify", className = "org.onap.so.adapters.vnf.async.client.DeleteVnfNotification")
+ @Action(input = "http://org.onap.so/notify/adapterNotify/deleteVnfNotificationRequest")
+ public void deleteVnfNotification(
+ @WebParam(name = "messageId", targetNamespace = "")
+ String messageId,
+ @WebParam(name = "completed", targetNamespace = "")
+ boolean completed,
+ @WebParam(name = "exception", targetNamespace = "")
+ MsoExceptionCategory exception,
+ @WebParam(name = "errorMessage", targetNamespace = "")
+ String errorMessage);
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify_Service.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify_Service.java
new file mode 100644
index 0000000000..4b140b1b30
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfAdapterNotify_Service.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebEndpoint;
+import javax.xml.ws.WebServiceClient;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.WebServiceFeature;
+
+
+/**
+ * This class was generated by the JAX-WS RI.
+ * JAX-WS RI 2.2.9-b14002
+ * Generated source version: 2.2
+ *
+ */
+@WebServiceClient(name = "vnfAdapterNotify", targetNamespace = "http://org.onap.so/vnfNotify", wsdlLocation = "/VnfAdapterNotify.wsdl")
+public class VnfAdapterNotify_Service
+ extends Service
+{
+
+ private final static URL VNFADAPTERNOTIFY_WSDL_LOCATION;
+ private final static WebServiceException VNFADAPTERNOTIFY_EXCEPTION;
+ private final static QName VNFADAPTERNOTIFY_QNAME = new QName("http://org.onap.so/vnfNotify", "vnfAdapterNotify");
+
+ static {
+ VNFADAPTERNOTIFY_WSDL_LOCATION = org.onap.so.adapters.vnf.async.client.VnfAdapterNotify_Service.class.getResource("/VnfAdapterNotify.wsdl");
+ WebServiceException e = null;
+ if (VNFADAPTERNOTIFY_WSDL_LOCATION == null) {
+ e = new WebServiceException("Cannot find '/VnfAdapterNotify.wsdl' wsdl. Place the resource correctly in the classpath.");
+ }
+ VNFADAPTERNOTIFY_EXCEPTION = e;
+ }
+
+ public VnfAdapterNotify_Service() {
+ super(__getWsdlLocation(), VNFADAPTERNOTIFY_QNAME);
+ }
+
+ public VnfAdapterNotify_Service(WebServiceFeature... features) {
+ super(__getWsdlLocation(), VNFADAPTERNOTIFY_QNAME, features);
+ }
+
+ public VnfAdapterNotify_Service(URL wsdlLocation) {
+ super(wsdlLocation, VNFADAPTERNOTIFY_QNAME);
+ }
+
+ public VnfAdapterNotify_Service(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, VNFADAPTERNOTIFY_QNAME, features);
+ }
+
+ public VnfAdapterNotify_Service(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public VnfAdapterNotify_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ *
+ * @return
+ * returns VnfAdapterNotify
+ */
+ @WebEndpoint(name = "MsoVnfAdapterAsyncImplPort")
+ public VnfAdapterNotify getMsoVnfAdapterAsyncImplPort() {
+ return super.getPort(new QName("http://org.onap.so/vnfNotify", "MsoVnfAdapterAsyncImplPort"), VnfAdapterNotify.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
+ * @return
+ * returns VnfAdapterNotify
+ */
+ @WebEndpoint(name = "MsoVnfAdapterAsyncImplPort")
+ public VnfAdapterNotify getMsoVnfAdapterAsyncImplPort(WebServiceFeature... features) {
+ return super.getPort(new QName("http://org.onap.so/vnfNotify", "MsoVnfAdapterAsyncImplPort"), VnfAdapterNotify.class, features);
+ }
+
+ private static URL __getWsdlLocation() {
+ if (VNFADAPTERNOTIFY_EXCEPTION!= null) {
+ throw VNFADAPTERNOTIFY_EXCEPTION;
+ }
+ return VNFADAPTERNOTIFY_WSDL_LOCATION;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfRollback.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfRollback.java
new file mode 100644
index 0000000000..9ad20738d0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfRollback.java
@@ -0,0 +1,198 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for vnfRollback complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="vnfRollback">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="cloudSiteId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="msoRequest" type="{http://org.onap.so/vnfNotify}msoRequest" minOccurs="0"/>
+ * &lt;element name="tenantCreated" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="tenantId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="vnfCreated" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ * &lt;element name="vnfId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "vnfRollback", propOrder = {
+ "cloudSiteId",
+ "msoRequest",
+ "tenantCreated",
+ "tenantId",
+ "vnfCreated",
+ "vnfId"
+})
+public class VnfRollback {
+
+ protected String cloudSiteId;
+ protected MsoRequest msoRequest;
+ protected boolean tenantCreated;
+ protected String tenantId;
+ protected boolean vnfCreated;
+ protected String vnfId;
+
+ /**
+ * Gets the value of the cloudSiteId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getCloudSiteId() {
+ return cloudSiteId;
+ }
+
+ /**
+ * Sets the value of the cloudSiteId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setCloudSiteId(String value) {
+ this.cloudSiteId = value;
+ }
+
+ /**
+ * Gets the value of the msoRequest property.
+ *
+ * @return
+ * possible object is
+ * {@link MsoRequest }
+ *
+ */
+ public MsoRequest getMsoRequest() {
+ return msoRequest;
+ }
+
+ /**
+ * Sets the value of the msoRequest property.
+ *
+ * @param value
+ * allowed object is
+ * {@link MsoRequest }
+ *
+ */
+ public void setMsoRequest(MsoRequest value) {
+ this.msoRequest = value;
+ }
+
+ /**
+ * Gets the value of the tenantCreated property.
+ *
+ */
+ public boolean isTenantCreated() {
+ return tenantCreated;
+ }
+
+ /**
+ * Sets the value of the tenantCreated property.
+ *
+ */
+ public void setTenantCreated(boolean value) {
+ this.tenantCreated = value;
+ }
+
+ /**
+ * Gets the value of the tenantId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ /**
+ * Sets the value of the tenantId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTenantId(String value) {
+ this.tenantId = value;
+ }
+
+ /**
+ * Gets the value of the vnfCreated property.
+ *
+ */
+ public boolean isVnfCreated() {
+ return vnfCreated;
+ }
+
+ /**
+ * Sets the value of the vnfCreated property.
+ *
+ */
+ public void setVnfCreated(boolean value) {
+ this.vnfCreated = value;
+ }
+
+ /**
+ * Gets the value of the vnfId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVnfId() {
+ return vnfId;
+ }
+
+ /**
+ * Sets the value of the vnfId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVnfId(String value) {
+ this.vnfId = value;
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfStatus.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfStatus.java
new file mode 100644
index 0000000000..1998ae0ce9
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/VnfStatus.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.async.client;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for vnfStatus.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * <p>
+ * <pre>
+ * &lt;simpleType name="vnfStatus">
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * &lt;enumeration value="ACTIVE"/>
+ * &lt;enumeration value="FAILED"/>
+ * &lt;enumeration value="NOTFOUND"/>
+ * &lt;enumeration value="UNKNOWN"/>
+ * &lt;/restriction>
+ * &lt;/simpleType>
+ * </pre>
+ *
+ */
+@XmlType(name = "vnfStatus")
+@XmlEnum
+public enum VnfStatus {
+
+ ACTIVE,
+ FAILED,
+ NOTFOUND,
+ UNKNOWN;
+
+ public String value() {
+ return name();
+ }
+
+ public static VnfStatus fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/package-info.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/package-info.java
new file mode 100644
index 0000000000..cc4a2a78ec
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/async/client/package-info.java
@@ -0,0 +1,21 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://org.onap.so/vnfNotify")
+package org.onap.so.adapters.vnf.async.client;
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfAlreadyExists.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfAlreadyExists.java
new file mode 100644
index 0000000000..2a7f33a682
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfAlreadyExists.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.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.onap.so.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://org.onap.so/vnf")
+public class VnfAlreadyExists extends VnfException {
+
+ private static final long serialVersionUID = 1L;
+
+ public VnfAlreadyExists (String name, String cloudId, String tenantId, String vnfId) {
+ super("Resource " + name + " already exists in cloud/tenant " + cloudId + "/" + tenantId + " with ID " + vnfId);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfException.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfException.java
new file mode 100644
index 0000000000..39f48e64dd
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfException.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.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.onap.so.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://org.onap.so/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-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfExceptionBean.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfExceptionBean.java
new file mode 100644
index 0000000000..011afa72ee
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfExceptionBean.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.exceptions;
+
+
+import java.io.Serializable;
+
+import org.onap.so.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) {
+ // Create a default category to prevent null pointer exceptions
+ this(message, MsoExceptionCategory.INTERNAL);
+ }
+
+ 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-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfNotFound.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfNotFound.java
new file mode 100644
index 0000000000..f3fa39cc2d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/exceptions/VnfNotFound.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vnf.exceptions;
+
+
+import javax.xml.ws.WebFault;
+
+/**
+ * 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.onap.so.adapters.vnf.exceptions.VnfExceptionBean", targetNamespace="http://org.onap.so/vnf")
+public class VnfNotFound extends VnfException {
+
+ private static final long serialVersionUID = 1L;
+
+ public VnfNotFound (String cloudId, String tenantId, String vnfName) {
+ super("Resource " + vnfName + " not found in cloud/tenant " + cloudId + "/" + tenantId);
+ }
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduBlueprint.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduBlueprint.java
new file mode 100644
index 0000000000..cef0371789
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduBlueprint.java
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.vdu.utils;
+
+import java.util.Map;
+
+/*
+ * This Java bean class describes the template model of a VDU as distributed
+ * by SDC to SO. It is composed of one or more templates, one of which must be
+ * the main template,
+ *
+ * The structure of this class corresponds to the format in which the templates
+ * and associated artifacts are represented in the SO Catalog.
+ *
+ * The map keys will be the "path" that is used to reference these artifacts within
+ * the other templates. This may be relevant to how different VDU plugins package
+ * the files for delivery to the sub-orchestrator.
+ *
+ * In the future, it is possible that pre-packaged blueprints (e.g. complete TOSCA CSARs)
+ * could be stored in the catalog (and added to this structure).
+ *
+ * This bean is passed as an input to instantiateVdu and updateVdu.
+ */
+
+public class VduBlueprint {
+ String vduModelId;
+ String mainTemplateName;
+ Map<String,byte[]> templateFiles;
+ Map<String,byte[]> attachedFiles;
+
+ public String getVduModelId() {
+ return vduModelId;
+ }
+
+ public void setVduModelId(String vduModelId) {
+ this.vduModelId = vduModelId;
+ }
+
+ public String getMainTemplateName() {
+ return mainTemplateName;
+ }
+
+ public void setMainTemplateName(String mainTemplateName) {
+ this.mainTemplateName = mainTemplateName;
+ }
+
+ public Map<String, byte[]> getTemplateFiles() {
+ return templateFiles;
+ }
+
+ public void setTemplateFiles(Map<String, byte[]> templateFiles) {
+ this.templateFiles = templateFiles;
+ }
+
+ public Map<String, byte[]> getAttachedFiles() {
+ return attachedFiles;
+ }
+
+ public void setAttachedFiles(Map<String, byte[]> attachedFiles) {
+ this.attachedFiles = attachedFiles;
+ }
+
+ @Override
+ public String toString() {
+ return "VduInfo {" +
+ "id='" + vduModelId + '\'' +
+ "mainTemplateName='" + mainTemplateName + '\'' +
+ '}';
+ }
+
+}
+
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduInfo.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduInfo.java
new file mode 100644
index 0000000000..227d513a0b
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduInfo.java
@@ -0,0 +1,130 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.vdu.utils;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/*
+ * This Java bean class relays VDU status information in a cloud-agnostic format.
+ *
+ * This bean is returned by all implementors of the MsoVduUtils interface operations
+ * (instantiate, query, delete).
+ */
+
+public class VduInfo {
+ // Set defaults for everything
+ private String vduInstanceId = "";
+ private String vduInstanceName = "";
+ private VduStatus status = VduStatus.NOTFOUND;
+ private Map<String,Object> outputs = new HashMap<>();
+ private Map<String,Object> inputs = new HashMap<>();
+ private String lastAction;
+ private String actionStatus;
+ private String errorMessage;
+
+ public VduInfo () {
+ }
+
+ // Add more constructors as appropriate
+ //
+
+ public VduInfo (String id, Map<String,Object> outputs) {
+ this.vduInstanceId = id;
+ if (outputs != null) this.outputs = outputs;
+ }
+
+ public VduInfo (String id) {
+ this.vduInstanceId = id;
+ }
+
+ public VduInfo (String id, VduStatus status) {
+ this.vduInstanceId = id;
+ this.status = status;
+ }
+
+ public String getVnfInstanceId() {
+ return vduInstanceId;
+ }
+
+ public void setVnfInstanceId (String id) {
+ this.vduInstanceId = id;
+ }
+
+ public String getVnfInstanceName() {
+ return vduInstanceName;
+ }
+
+ public void setVnfInstanceName (String name) {
+ this.vduInstanceName = name;
+ }
+
+ public VduStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus (VduStatus status) {
+ this.status = status;
+ }
+
+ public Map<String,Object> getOutputs () {
+ return outputs;
+ }
+
+ public void setOutputs (Map<String,Object> outputs) {
+ this.outputs = outputs;
+ }
+
+ public Map<String,Object> getInputs () {
+ return inputs;
+ }
+
+ public void setInputs (Map<String,Object> inputs) {
+ this.inputs = inputs;
+ }
+
+ public String getLastAction() {
+ return lastAction;
+ }
+
+ public String getActionStatus() {
+ return actionStatus;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String toString() {
+ return "VduInfo {" +
+ "id='" + vduInstanceId + '\'' +
+ "name='" + vduInstanceName + '\'' +
+ ", inputs='" + inputs + '\'' +
+ ", outputs='" + outputs + '\'' +
+ ", lastAction='" + lastAction + '\'' +
+ ", status='" + status + '\'' +
+ ", errorMessage='" + errorMessage + '\'' +
+ '}';
+ }
+
+}
+
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduPlugin.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduPlugin.java
new file mode 100644
index 0000000000..871260a86d
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduPlugin.java
@@ -0,0 +1,248 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.vdu.utils;
+
+/**
+ * This interface defines a common API for template-based cloud deployments.
+ * The methods here should be adaptable for Openstack (Heat), Cloudify (TOSCA),
+ * Aria (TOSCA), Multi-VIM (TBD), and others (e.g. Azure Resource Manager).
+ *
+ * The deployed instances are referred to here as Virtual Deployment Units (VDUs).
+ * The package of templates that define a give VDU is referred to as its blueprint.
+ *
+ * Template-based orchestrators all follow a similar template/blueprint model.
+ * - One main template that is the top level definition
+ * - Optional nested templates referenced/included by the main template
+ * - Optional files attached to the template package, typically containing
+ * configuration files, install scripts, orchestration scripts, etc.
+ *
+ * The main template also defines the required inputs for creating a new instance,
+ * and output values exposed by successfully deployed instances. Inputs and outputs
+ * may include simple or complex (JSON) data types.
+ *
+ * Each implementation of this interface is expected to understand the MSO CloudConfig
+ * to obtain the credentials for its sub-orchestrator and the targeted cloud.
+ * The sub-orchestrator may have different credentials from the cloud (e.g. an Aria
+ * instance in front of an Openstack cloud) or they may be the same (e.g. Heat)
+ */
+import java.util.Map;
+
+import org.onap.so.openstack.exceptions.MsoException;
+
+public interface VduPlugin {
+
+ /**
+ * The instantiateVdu interface deploys a new VDU instance from a blueprint package.
+ * The templates and files in the blueprint may be pre-installed where supported
+ * (e.g. in Cloudify or Aria), or may be passed in directly (e.g. for Heat). These
+ * files are expressed as byte arrays, though only text files are expected from ASDC.
+ *
+ * For some VIMs, this may be a single command (e.g. Heat -> create stack) or may
+ * require a series of API calls (e.g. Cloudify -> upload blueprint, create deployment,
+ * execute install workflow). These details are hidden within the implementation.
+ * The instantiation should be fully completed before returning. On failures, this
+ * method is expected to back out the attempt, leaving the cloud in its previous state.
+ *
+ * It is expected that parameters have been validated and contain at minimum the
+ * required parameters for the given template with no extra parameters.
+ *
+ * The VDU name supplied by the caller will be globally unique, and identify the artifact
+ * in A&AI. Inventory is managed by the higher levels invoking this function.
+ *
+ * @param cloudSiteId The target cloud for the VDU. Maps to a CloudConfig entry.
+ * @param tenantId The cloud tenant in which to deploy the VDU. The meaning may differ by
+ * cloud provider, but every cloud supports some sort of tenant partitioning.
+ * @param vduInstanceName A unique name for the VDU instance to create
+ * @param vduBlueprint Object containing the collection of templates and files that comprise
+ * the blueprint for this VDU.
+ * @param inputs A map of key/value inputs. Values may be strings, numbers, or JSON objects.
+ * @param environmentFile A file containing default parameter name/value pairs. This is
+ * primarily for Heat, though ASDC may create a similar file for other orchestrators.
+ * @param timeoutMinutes Timeout after which the instantiation attempt will be cancelled
+ * @param suppressBackout Flag to preserve the deployment on install Failure. Should normally
+ * be False except in troubleshooting/debug cases
+ *
+ * @return A VduInfo object
+ * @throws MsoException Thrown if the sub-orchestrator API calls fail or if a timeout occurs.
+ * Various subclasses of MsoException may be thrown.
+ */
+ public VduInfo instantiateVdu (
+ String cloudSiteId,
+ String tenantId,
+ String vduInstanceName,
+ VduBlueprint vduBlueprint,
+ Map <String, ?> inputs,
+ String environmentFile,
+ int timeoutMinutes,
+ boolean suppressBackout)
+ throws MsoException;
+
+
+ /**
+ * Query a deployed VDU instance. This call will return a VduInfo object, or null
+ * if the deployment does not exist.
+ *
+ * Some VIM orchestrators identify deployment instances by string UUIDs, and others
+ * by integers. In the latter case, the ID will be passed in as a numeric string.
+ *
+ * The returned VduInfo object contains the input and output parameter maps,
+ * as well as other properties of the deployment (name, status, last action, etc.).
+ *
+ * @param cloudSiteId The target cloud to query for the VDU.
+ * @param tenantId The cloud tenant in which to query
+ * @param vduInstanceId The ID of the deployment to query
+ *
+ * @return A VduInfo object
+ * @throws MsoException Thrown if the VIM/sub-orchestrator API calls fail.
+ * Various subclasses of MsoException may be thrown.
+ */
+ public VduInfo queryVdu (
+ String cloudSiteId,
+ String tenantId,
+ String vduInstanceId)
+ throws MsoException;
+
+
+ /**
+ * Delete a VDU instance by ID. If the VIM sub-orchestrator supports pre-installation
+ * of blueprints, the blueprint itself may remain installed. This is recommended, since
+ * other VDU instances may be using it.
+ *
+ * Some VIM orchestrators identify deployment instances by string UUIDs, and others
+ * by integers. In the latter case, the ID will be passed in as a numeric string.
+ *
+ * For some VIMs, deletion may be a single command (e.g. Heat -> delete stack) or a
+ * series of API calls (e.g. Cloudify -> execute uninstall workflow, delete deployment).
+ * These details are hidden within the implementation. The deletion should be fully
+ * completed before returning.
+ *
+ * The successful return is a VduInfo object which contains the state of the object just prior
+ * to deletion, with a status of DELETED. If the deployment was not found, the VduInfo object
+ * should be empty (with a status of NOTFOUND). There is no rollback from a successful deletion.
+ *
+ * A deletion failure will result in an undefined deployment state - the components may
+ * or may not have been all or partially uninstalled, so the resulting deployment must
+ * be considered invalid.
+ *
+ * @param cloudSiteId The target cloud from which to delete the VDU.
+ * @param tenantId The cloud tenant in which to delete the VDU.
+ * @param vduInstanceId The unique id of the deployment to delete.
+ * @param timeoutMinutes Timeout after which the delete action will be cancelled
+ * @param keepBlueprintLoaded Flag to also delete the blueprint
+ *
+ * @return A VduInfo object, representing the state of the instance just prior to deletion.
+ *
+ * @throws MsoException Thrown if the API calls fail or if a timeout occurs.
+ * Various subclasses of MsoException may be thrown.
+ */
+ public VduInfo deleteVdu (
+ String cloudSiteId,
+ String tenantId,
+ String vduInstanceId,
+ int timeoutMinutes,
+ boolean keepBlueprintLoaded)
+ throws MsoException;
+
+
+ /**
+ * The updateVdu interface attempts to update a VDU in-place, using either new inputs or
+ * a new model definition (i.e. updated templates/blueprints). This depends on the
+ * capabilities of the targeted sub-orchestrator, as not all implementations are expected
+ * to support this ability. It is primary included initially only for Heat.
+ *
+ * It is expected that parameters have been validated and contain at minimum the required
+ * parameters for the given template with no extra parameters. The VDU instance name cannot
+ * be updated.
+ *
+ * The update should be fully completed before returning. The successful return is a
+ * VduInfo object containing the updated VDU state.
+ *
+ * An update failure will result in an undefined deployment state - the components may
+ * or may not have been all or partially modified, deleted, recreated, etc. So the resulting
+ * VDU must be considered invalid.
+ *
+ * @param cloudSiteId The target cloud for the VDU. Maps to a CloudConfig entry.
+ * @param tenantId The cloud tenant in which to deploy the VDU. The meaning may differ by
+ * cloud provider, but every cloud supports some sort of tenant partitioning.
+ * @param vduInstanceId The unique ID for the VDU instance to update.
+ * @param vduBlueprint Object containing the collection of templates and files that comprise
+ * the blueprint for this VDU.
+ * @param inputs A map of key/value inputs. Values may be strings, numbers, or JSON objects.
+ * @param environmentFile A file containing default parameter name/value pairs. This is
+ * primarily for Heat, though ASDC may create a similar file for other orchestrators.
+ * @param timeoutMinutes Timeout after which the instantiation attempt will be cancelled
+ *
+ * @return A VduInfo object
+ * @throws MsoException Thrown if the sub-orchestrator API calls fail or if a timeout occurs.
+ * Various subclasses of MsoException may be thrown.
+ */
+ public VduInfo updateVdu (
+ String cloudSiteId,
+ String tenantId,
+ String vduInstanceId,
+ VduBlueprint vduBlueprint,
+ Map <String, ?> inputs,
+ String environmentFile,
+ int timeoutMinutes)
+ throws MsoException;
+
+
+ /**
+ * Check if a blueprint package has been installed in the sub-orchestrator and available
+ * for use at a targeted cloud site. If the specific sub-orchestrator does not support
+ * pre-installation, then those implementations should always return False.
+ *
+ * @param cloudSiteId The cloud site where the blueprint is needed
+ * @param vduModelId Unique ID of the VDU model to query
+ *
+ * @throws MsoException Thrown if the API call fails.
+ */
+ public boolean isBlueprintLoaded (String cloudSiteId, String vduModelId)
+ throws MsoException;
+
+
+ /**
+ * Install a blueprint package to the target sub-orchestrator for a cloud site.
+ * The blueprints currently must be structured as a single directory with all of the
+ * required files. One of those files is designated the "main file" for the blueprint.
+ * Files are provided as byte arrays, though expect only text files will be distributed
+ * from ASDC and stored by MSO.
+ *
+ * @param cloudSiteId The cloud site where the blueprint is needed
+ * @param vduBlueprint Object containing the collection of templates and files that comprise
+ * the blueprint for this VDU.
+ * @param failIfExists Flag to return an error if blueprint already exists
+ *
+ * @throws MsoException Thrown if the API call fails.
+ */
+ public void uploadBlueprint (String cloudSiteId,
+ VduBlueprint vduBlueprint,
+ boolean failIfExists)
+ throws MsoException;
+
+ /**
+ * Indicator that this VIM sub-orchestrator implementation supports independent upload
+ * of blueprint packages. Each implementation should return a constant value.
+ *
+ * @returns True if the sub-orchestrator supports blueprint pre-installation (upload).
+ */
+ public boolean blueprintUploadSupported ();
+
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduStatus.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduStatus.java
new file mode 100644
index 0000000000..1412b02da0
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/vdu/utils/VduStatus.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.vdu.utils;
+
+
+/*
+ * Enum status values to capture the state of a generic (cloud-agnostic) VDU.
+ */
+public enum VduStatus {
+ NOTFOUND,
+ INSTANTIATING,
+ INSTANTIATED,
+ DELETING,
+ DELETED, // Note - only returned in success response to deleteVdu call.
+ UPDATING,
+ FAILED,
+ UNKNOWN
+}
+