summaryrefslogtreecommitdiffstats
path: root/adapters/mso-network-adapter/src/main
diff options
context:
space:
mode:
authorChrisC <cc697w@intl.att.com>2017-01-31 11:40:03 +0100
committerChrisC <cc697w@intl.att.com>2017-01-31 12:59:33 +0100
commit025301d08b061482c1f046d562bf017c8cbcfe8d (patch)
tree68a2a549736c9bf0f7cd4e71c76e40ef7e2606f2 /adapters/mso-network-adapter/src/main
parent2754ad52f833278a5c925bd788a16d1dce16a598 (diff)
Initial OpenECOMP MSO commit
Change-Id: Ia6a7574859480717402cc2f22534d9973a78fa6d Signed-off-by: ChrisC <cc697w@intl.att.com>
Diffstat (limited to 'adapters/mso-network-adapter/src/main')
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/BpelRestClient.java304
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRef.java78
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRefSeq.java65
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnet.java196
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetIp.java58
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetPool.java67
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/HealthCheckHandler.java67
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapter.java216
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsync.java103
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsyncImpl.java679
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterImpl.java2052
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/NetworkAdapterRest.java595
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkException.java81
-rw-r--r--adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkExceptionBean.java73
14 files changed, 4634 insertions, 0 deletions
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/BpelRestClient.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/BpelRestClient.java
new file mode 100644
index 0000000000..dcd12d24e7
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/BpelRestClient.java
@@ -0,0 +1,304 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.properties.MsoJavaProperties;
+import org.openecomp.mso.properties.MsoPropertiesException;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+/**
+ * This is the class that is used to POST replies from the MSO adapters to the BPEL engine.
+ * It can be configured via property file, or modified using the member methods.
+ * The properties to use are:
+ * org.openecomp.mso.adapters.vnf.bpelauth encrypted authorization string to send to BEPL engine
+ * org.openecomp.mso.adapters.vnf.sockettimeout socket timeout value
+ * org.openecomp.mso.adapters.vnf.connecttimeout connect timeout value
+ * org.openecomp.mso.adapters.vnf.retrycount number of times to retry failed connections
+ * org.openecomp.mso.adapters.vnf.retryinterval interval (in seconds) between retries
+ * org.openecomp.mso.adapters.vnf.retrylist list of response codes that will trigger a retry (the special code
+ * 900 means "connection was not established")
+ */
+public class BpelRestClient {
+ public static final String MSO_PROP_NETWORK_ADAPTER = "MSO_PROP_NETWORK_ADAPTER";
+ private static final String PROPERTY_DOMAIN = "org.openecomp.mso.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);
+
+ /** 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 = "";
+
+ try {
+ MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ MsoJavaProperties jp = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_NETWORK_ADAPTER);
+ socketTimeout = jp.getIntProperty(SOCKET_TIMEOUT_PROPERTY, DEFAULT_SOCKET_TIMEOUT);
+ connectTimeout = jp.getIntProperty(CONN_TIMEOUT_PROPERTY, DEFAULT_CONNECT_TIMEOUT);
+ retryCount = jp.getIntProperty(RETRY_COUNT_PROPERTY, DEFAULT_RETRY_COUNT);
+ retryInterval = jp.getIntProperty(RETRY_INTERVAL_PROPERTY, DEFAULT_RETRY_INTERVAL);
+ setRetryList(jp.getProperty(RETRY_LIST_PROPERTY, DEFAULT_RETRY_LIST));
+ credentials = jp.getEncryptedProperty(BPEL_AUTH_PROPERTY, DEFAULT_CREDENTIALS, ENCRYPTION_KEY);
+ } catch (MsoPropertiesException e) {
+ String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Unable to get properties", e);
+ }
+ }
+
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(int retryCount) {
+ if (retryCount < 0)
+ retryCount = DEFAULT_RETRY_COUNT;
+ this.retryCount = retryCount;
+ }
+
+ public int getRetryInterval() {
+ return retryInterval;
+ }
+
+ public void setRetryInterval(int retryInterval) {
+ this.retryInterval = retryInterval;
+ }
+
+ public String getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(String credentials) {
+ this.credentials = credentials;
+ }
+
+ public String getRetryList() {
+ if (retryList.size() == 0)
+ return "";
+ String t = retryList.toString();
+ return t.substring(1, t.length()-1);
+ }
+
+ public void setRetryList(String retryList) {
+ Set<Integer> s = new TreeSet<Integer>();
+ for (String t : retryList.split("[, ]")) {
+ try {
+ s.add(Integer.parseInt(t));
+ } catch (NumberFormatException x) {
+ // ignore
+ }
+ }
+ this.retryList = s;
+ }
+
+ public int getLastResponseCode() {
+ return lastResponseCode;
+ }
+
+ public String getLastResponse() {
+ return lastResponse;
+ }
+
+ /**
+ * Post a response to the URL of the BPEL engine. As long as the response code is one of those in
+ * the retryList, the post will be retried up to "retrycount" times with an interval (in seconds)
+ * of "retryInterval". If retryInterval is negative, then each successive retry interval will be
+ * double the previous one.
+ * @param toBpelStr the content (XML or JSON) to post
+ * @param bpelUrl the URL to post to
+ * @param isxml true if the content is XML, otherwise assumed to be JSON
+ * @return true if the post succeeded, false if all retries failed
+ */
+ public boolean bpelPost(final String toBpelStr, final String bpelUrl, final boolean isxml) {
+ debug("Sending response to BPEL: " + toBpelStr);
+ int totalretries = 0;
+ int retryint = retryInterval;
+ while (true) {
+ sendOne(toBpelStr, bpelUrl, isxml);
+ // Note: really should handle response code 415 by switching between content types if needed
+ if (!retryList.contains(lastResponseCode)) {
+ debug("Got response code: " + lastResponseCode + ": returning.");
+ return true;
+ }
+ if (totalretries >= retryCount) {
+ debug("Retried " + totalretries + " times, giving up.");
+ LOGGER.error(MessageEnum.RA_SEND_VNF_NOTIF_ERR, "Could not deliver response to BPEL after "+totalretries+" tries: "+toBpelStr, "Camunda", "", MsoLogger.ErrorCode.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) {
+ // ignore
+ }
+ }
+ }
+ private void debug(String m) {
+ LOGGER.debug(m);
+// System.err.println(m);
+ }
+ private void sendOne(final String toBpelStr, final String bpelUrl, final boolean isxml) {
+ LOGGER.debug("Sending to BPEL server: "+bpelUrl);
+ LOGGER.debug("Content is: "+toBpelStr);
+
+ //POST
+ HttpPost post = new HttpPost(bpelUrl);
+ if (credentials != null && !credentials.isEmpty())
+ post.addHeader("Authorization", "Basic " + DatatypeConverter.printBase64Binary(credentials.getBytes()));
+
+ //ContentType
+ ContentType ctype = isxml ? ContentType.APPLICATION_XML : ContentType.APPLICATION_JSON;
+ post.setEntity(new StringEntity(toBpelStr, ctype));
+
+ //Timeouts
+ RequestConfig requestConfig = RequestConfig
+ .custom()
+ .setSocketTimeout(socketTimeout * 1000)
+ .setConnectTimeout(connectTimeout * 1000)
+ .build();
+ post.setConfig(requestConfig);
+
+ //Client 4.3+
+ //Execute & GetResponse
+ try (CloseableHttpClient client = HttpClients.createDefault();
+ CloseableHttpResponse response = client.execute(post)) {
+ if (response != null) {
+ lastResponseCode = response.getStatusLine().getStatusCode();
+ HttpEntity entity = response.getEntity();
+ lastResponse = (entity != null) ? EntityUtils.toString(entity) : "";
+ } else {
+ lastResponseCode = 900;
+ lastResponse = "";
+ }
+ } catch (Exception e) {
+ String error = "Error sending Bpel notification:" + toBpelStr;
+ LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, error, "Camunda", "", MsoLogger.ErrorCode.AvailabilityError, "Exception sending Bpel notification", e);
+ lastResponseCode = 900;
+ lastResponse = "";
+ }
+ LOGGER.debug("Response code from BPEL server: "+lastResponseCode);
+ LOGGER.debug("Response body is: "+lastResponse);
+ }
+
+ public static void main(String[] a) throws MsoPropertiesException {
+ final String bpelengine = "http://mtmac1.research.att.com:8080/catch.jsp";
+ final String propfile = "/tmp/mso.vnf.properties";
+ // "/Users/eby/src/mso.rest/mso/packages/mso-config-centralized/mso-po-adapter-config/mso.vnf.properties"
+ final String xml =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
+ "<updateVolumeGroupResponse><volumeGroupId>1464013300723</volumeGroupId><volumeGroupOutputs>" +
+ "<entry><key>clyde</key><value>10</value></entry>" +
+ "<entry><key>wayne</key><value>99</value></entry>" +
+ "<entry><key>mickey</key><value>7</value></entry>" +
+ "</volumeGroupOutputs></updateVolumeGroupResponse>";
+
+ MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ msoPropertiesFactory.initializeMsoProperties (MSO_PROP_NETWORK_ADAPTER, propfile);
+
+ BpelRestClient bc = new BpelRestClient();
+ System.out.println(bc.getRetryList());
+ System.out.println(bc.getCredentials()); // poAvos:Domain2.0!
+
+ bc.bpelPost(xml, bpelengine, true);
+ System.out.println("respcode = "+bc.getLastResponseCode());
+ System.out.println("resp = "+bc.getLastResponse());
+ }
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRef.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRef.java
new file mode 100644
index 0000000000..6e2644db73
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRef.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
+
+public class ContrailPolicyRef {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+
+ @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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRefSeq.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRefSeq.java
new file mode 100644
index 0000000000..b5d750288f
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailPolicyRefSeq.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import org.codehaus.jackson.annotate.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() {
+ }
+
+ 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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnet.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnet.java
new file mode 100644
index 0000000000..3df1014a90
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnet.java
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.Pool;
+import org.openecomp.mso.openstack.beans.Subnet;
+import static org.openecomp.mso.openstack.utils.MsoCommonUtils.isNullOrEmpty;
+
+public class ContrailSubnet {
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet")
+ private ContrailSubnetIp subnet = new ContrailSubnetIp();
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_default_gateway")
+ private String default_gateway;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_name")
+ private String subnet_name;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_enable_dhcp")
+ private Boolean enable_dhcp;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_addr_from_start")
+ private Boolean addr_from_start = true;
+
+ /** future - leave this commented
+ private String subnet_uuid;
+ private String dns_server_address;
+ private List<String> dns_nameservers;
+ private String dhcp_option_list;
+ private String host_routes;
+ **/
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_allocation_pools")
+ private List<ContrailSubnetPool> allocation_pools = new ArrayList <ContrailSubnetPool> ();
+
+ public ContrailSubnet() {
+ super();
+ }
+
+ public String getDefault_gateway() {
+ return default_gateway;
+ }
+
+ public void setDefault_gateway(String default_gateway) {
+ this.default_gateway = default_gateway;
+ }
+
+ public ContrailSubnetIp getSubnet() {
+ return subnet;
+ }
+
+ public void setSubnet(ContrailSubnetIp subnet) {
+ this.subnet = subnet;
+ }
+
+ public Boolean isEnable_dhcp() {
+ return enable_dhcp;
+ }
+
+ public void setEnable_dhcp(Boolean enable_dhcp) {
+ this.enable_dhcp = enable_dhcp;
+ }
+
+ public String getSubnet_name() {
+ return subnet_name;
+ }
+
+ public void setSubnet_name(String subnet_name) {
+ this.subnet_name = subnet_name;
+ }
+
+ public List<ContrailSubnetPool> getAllocation_pools() {
+ return allocation_pools;
+ }
+
+ public void setPools(List<ContrailSubnetPool> allocation_pools) {
+ this.allocation_pools = allocation_pools;
+ }
+
+ public Boolean isAddr_from_start() {
+ return addr_from_start;
+ }
+
+ public void setAddr_from_start(Boolean addr_from_start) {
+ this.addr_from_start = addr_from_start;
+ }
+
+ 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:" + subnet_name;
+ 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:" + subnet_name;
+ 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 i_subnet)
+ {
+ if (i_subnet != null)
+ {
+ if (!isNullOrEmpty(i_subnet.getSubnetName()))
+ subnet_name = i_subnet.getSubnetName();
+ else
+ subnet_name = i_subnet.getSubnetId();
+ enable_dhcp = i_subnet.getEnableDHCP();
+ default_gateway = i_subnet.getGatewayIp();
+ if (!isNullOrEmpty(i_subnet.getCidr()) )
+ {
+ int idx = i_subnet.getCidr().indexOf("/");
+ if (idx != -1)
+ {
+ subnet.setIp_prefix(i_subnet.getCidr().substring(0, idx));
+ subnet.setIp_prefix_len(i_subnet.getCidr().substring(idx+1));
+ }
+ }
+ if (i_subnet.getAllocationPools() != null)
+ {
+ for (Pool pool : i_subnet.getAllocationPools())
+ {
+ if ( !isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()) )
+ {
+ ContrailSubnetPool csp = new ContrailSubnetPool();
+ csp.populateWith(pool);
+ allocation_pools.add (csp);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder buf = new StringBuilder ();
+ for (ContrailSubnetPool pool : allocation_pools)
+ {
+ buf.append(pool.toString());
+ }
+ return "ContrailSubnet [subnet=" + subnet.toString() + " default_gateway=" + default_gateway
+ + " enable_dhcp=" + enable_dhcp + " addr_from_start=" + addr_from_start + " subnet_name=" + subnet_name + " allocation_pools=" + buf + " ]";
+ }
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetIp.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetIp.java
new file mode 100644
index 0000000000..c0a5311fec
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetIp.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class ContrailSubnetIp {
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_ip_prefix")
+ private String ip_prefix;
+
+ @JsonProperty("network_ipam_refs_data_ipam_subnets_subnet_ip_prefix_len")
+ private String ip_prefix_len;
+
+ public ContrailSubnetIp() {
+ }
+
+ public String getIp_prefix() {
+ return ip_prefix;
+ }
+
+ public void setIp_prefix(String ip_prefix) {
+ this.ip_prefix = ip_prefix;
+ }
+
+ public String getIp_prefix_len() {
+ return ip_prefix_len;
+ }
+
+ public void setIp_prefix_len(String ip_prefix_len) {
+ this.ip_prefix_len = ip_prefix_len;
+ }
+
+ @Override
+ public String toString() {
+ return "ContrailSubnetIp [ip_prefix=" + ip_prefix + ", ip_prefix_len=" + ip_prefix_len + "]";
+ }
+
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetPool.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetPool.java
new file mode 100644
index 0000000000..5b40ba26a6
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/ContrailSubnetPool.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import org.openecomp.mso.openstack.beans.Pool;
+import org.codehaus.jackson.annotate.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() {
+ }
+
+ 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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/HealthCheckHandler.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/HealthCheckHandler.java
new file mode 100644
index 0000000000..2767baffac
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/HealthCheckHandler.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.HealthCheckUtils;
+import org.openecomp.mso.utils.UUIDChecker;
+
+
+@Path("/")
+ public class HealthCheckHandler {
+
+ private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
+ private static final String MSO_PROP_NETWORK_ADAPTER = "MSO_PROP_NETWORK_ADAPTER";
+
+ @HEAD
+ @GET
+ @Path("/healthcheck")
+ @Produces("text/html")
+ public Response healthcheck (@QueryParam("requestId") String requestId) {
+ long startTime = System.currentTimeMillis ();
+ MsoLogger.setServiceName ("Healthcheck");
+ UUIDChecker.verifyOldUUID(requestId, msoLogger);
+ HealthCheckUtils healthCheck = new HealthCheckUtils ();
+ if (!healthCheck.siteStatusCheck(msoLogger, startTime)) {
+ return HealthCheckUtils.HEALTH_CHECK_NOK_RESPONSE;
+ }
+
+ if (!healthCheck.configFileCheck(msoLogger, startTime, MSO_PROP_NETWORK_ADAPTER)) {
+ return HealthCheckUtils.NOT_STARTED_RESPONSE;
+ }
+
+ if (!healthCheck.catalogDBCheck (msoLogger, startTime)) {
+ return HealthCheckUtils.NOT_STARTED_RESPONSE;
+ }
+ msoLogger.debug("healthcheck - Successful");
+ return HealthCheckUtils.HEALTH_CHECK_RESPONSE;
+ }
+
+
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapter.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapter.java
new file mode 100644
index 0000000000..4960877b8a
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapter.java
@@ -0,0 +1,216 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.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.openecomp.mso.adapters.network.exceptions.NetworkException;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.openstack.beans.NetworkRollback;
+import org.openecomp.mso.openstack.beans.NetworkStatus;
+import org.openecomp.mso.openstack.beans.Subnet;
+
+@WebService (name="NetworkAdapter", targetNamespace="http://com.att.mso/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="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="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="routeTargets") List<String> 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="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="networkId") @XmlElement(required=true) String networkId,
+ @WebParam(name="networkName") @XmlElement(required=true) String networkName,
+ @WebParam(name="routeTargets") List<String> 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<String>> 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="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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsync.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsync.java
new file mode 100644
index 0000000000..e79ba125e2
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsync.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import javax.jws.Oneway;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.openstack.beans.Subnet;
+import org.openecomp.mso.openstack.beans.NetworkRollback;
+
+import java.util.List;
+/**
+ * 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://com.att.mso/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="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="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="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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsyncImpl.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsyncImpl.java
new file mode 100644
index 0000000000..75cbc636cc
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterAsyncImpl.java
@@ -0,0 +1,679 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jws.WebService;
+import javax.xml.bind.DatatypeConverter;
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Holder;
+import javax.xml.ws.handler.MessageContext;
+
+import org.openecomp.mso.adapters.network.async.client.CreateNetworkNotification;
+import org.openecomp.mso.adapters.network.async.client.MsoExceptionCategory;
+import org.openecomp.mso.adapters.network.async.client.NetworkAdapterNotify;
+import org.openecomp.mso.adapters.network.async.client.NetworkAdapterNotify_Service;
+import org.openecomp.mso.adapters.network.async.client.QueryNetworkNotification;
+import org.openecomp.mso.adapters.network.async.client.UpdateNetworkNotification;
+import org.openecomp.mso.adapters.network.exceptions.NetworkException;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoAlarmLogger;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.NetworkRollback;
+import org.openecomp.mso.openstack.beans.NetworkStatus;
+import org.openecomp.mso.openstack.beans.Subnet;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+
+@WebService(serviceName = "NetworkAdapterAsync", endpointInterface = "org.openecomp.mso.adapters.network.MsoNetworkAdapterAsync", targetNamespace = "http://com.att.mso/networkA")
+public class MsoNetworkAdapterAsyncImpl implements MsoNetworkAdapterAsync {
+
+ MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
+
+ CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
+
+ public static final String MSO_PROP_NETWORK_ADAPTER="MSO_PROP_NETWORK_ADAPTER";
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ private static final String BPEL_AUTH_PROP = "org.openecomp.mso.adapters.network.bpelauth";
+ private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
+ /**
+ * Health Check web method. Does nothing but return to show the adapter is deployed.
+ */
+ @Override
+ public void healthCheckA () {
+ LOGGER.debug ("Health check call in 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 networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ Boolean failIfExists,
+ Boolean backout,
+ List <Subnet> subnets,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ 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
+ MsoNetworkAdapter networkAdapter = new MsoNetworkAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <String> networkId = new Holder <String> ();
+ Holder <String> neutronNetworkId = new Holder <String> ();
+ Holder <NetworkRollback> networkRollback = new Holder <NetworkRollback> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <Map <String, String>> ();
+
+ try {
+ networkAdapter.createNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ 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 networkId,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <Subnet> subnets,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ 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
+ MsoNetworkAdapter networkAdapter = new MsoNetworkAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <NetworkRollback> networkRollback = new Holder <NetworkRollback> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <Map <String, String>> ();
+
+ try {
+ networkAdapter.updateNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ 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;
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ 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
+ MsoNetworkAdapter networkAdapter = new MsoNetworkAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> networkExists = new Holder <Boolean> ();
+ Holder <String> networkId = new Holder <String> ();
+ Holder <String> neutronNetworkId = new Holder <String> ();
+ Holder <NetworkStatus> status = new Holder <NetworkStatus> ();
+ Holder <List <Integer>> vlans = new Holder <List <Integer>> ();
+ Holder <Map <String, String>> subnetIdMap = new Holder <Map <String, String>> ();
+
+ 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.openecomp.mso.adapters.network.async.client.NetworkStatus networkS = org.openecomp.mso.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 networkId,
+ String messageId,
+ MsoRequest msoRequest,
+ String notificationUrl) {
+ String error;
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ 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
+ MsoNetworkAdapter networkAdapter = new MsoNetworkAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ // Synchronous Web Service Outputs
+ Holder <Boolean> networkDeleted = new Holder <Boolean> ();
+
+ try {
+ networkAdapter.deleteNetwork (cloudSiteId, tenantId, networkType, 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);
+ // Will capture execution time for metrics
+ long startTime = System.currentTimeMillis ();
+ // 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
+ MsoNetworkAdapter networkAdapter = new MsoNetworkAdapterImpl (msoPropertiesFactory,cloudConfigFactory);
+
+ 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.openecomp.mso.adapters.network.async.client.NetworkRollback copyNrb (Holder <NetworkRollback> hNrb) {
+ org.openecomp.mso.adapters.network.async.client.NetworkRollback cnrb = new org.openecomp.mso.adapters.network.async.client.NetworkRollback ();
+
+ if (hNrb != null && hNrb.value != null) {
+ org.openecomp.mso.adapters.network.async.client.MsoRequest cmr = new org.openecomp.mso.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://com.att.mso/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);
+ }
+
+ LOGGER.debug ("Notification Endpoint URL: " + epUrl.toExternalForm ());
+
+ bp.getRequestContext ().put (BindingProvider.ENDPOINT_ADDRESS_PROPERTY, epUrl.toExternalForm ());
+
+ // authentication
+ try {
+ Map <String, Object> reqCtx = bp.getRequestContext ();
+ Map <String, List <String>> headers = new HashMap <String, List <String>> ();
+
+ String userCredentials = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_NETWORK_ADAPTER).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;
+ }
+
+ 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 <String, String> ();
+ 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 <String, String> ();
+ sMap = hMap.value;
+ UpdateNetworkNotification.SubnetIdMap.Entry entry = new UpdateNetworkNotification.SubnetIdMap.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ 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 <String, String> ();
+ sMap = hMap.value;
+ QueryNetworkNotification.SubnetIdMap.Entry entry = new QueryNetworkNotification.SubnetIdMap.Entry ();
+
+ for (String key : sMap.keySet ()) {
+ entry.setKey (key);
+ entry.setValue (sMap.get (key));
+ subnetIdMap.getEntry ().add (entry);
+ }
+ }
+ return subnetIdMap;
+ }
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterImpl.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterImpl.java
new file mode 100644
index 0000000000..97624dae30
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/MsoNetworkAdapterImpl.java
@@ -0,0 +1,2052 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.Holder;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import org.openecomp.mso.adapters.network.exceptions.NetworkException;
+import org.openecomp.mso.cloud.CloudConfig;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.cloud.CloudSite;
+import org.openecomp.mso.db.catalog.CatalogDatabase;
+import org.openecomp.mso.db.catalog.beans.HeatTemplate;
+import org.openecomp.mso.db.catalog.beans.NetworkResource;
+import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoAlarmLogger;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.HeatStatus;
+import org.openecomp.mso.openstack.beans.NetworkInfo;
+import org.openecomp.mso.openstack.beans.NetworkRollback;
+import org.openecomp.mso.openstack.beans.NetworkStatus;
+import org.openecomp.mso.openstack.beans.Pool;
+import org.openecomp.mso.openstack.beans.StackInfo;
+import org.openecomp.mso.openstack.beans.Subnet;
+import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
+import org.openecomp.mso.openstack.exceptions.MsoException;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.openstack.utils.MsoCommonUtils;
+import org.openecomp.mso.openstack.utils.MsoHeatUtils;
+import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
+import org.openecomp.mso.openstack.utils.MsoNeutronUtils;
+import org.openecomp.mso.openstack.utils.MsoNeutronUtils.NetworkType;
+import org.openecomp.mso.properties.MsoPropertiesException;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+import static org.openecomp.mso.openstack.utils.MsoCommonUtils.isNullOrEmpty;
+
+@WebService(serviceName = "NetworkAdapter", endpointInterface = "org.openecomp.mso.adapters.network.MsoNetworkAdapter", targetNamespace = "http://com.att.mso/network")
+public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
+
+ MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
+
+ CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
+
+ private static final String AIC3_NW_PROPERTY= "org.openecomp.mso.adapters.network.aic3nw";
+ private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
+ public static final String MSO_PROP_NETWORK_ADAPTER="MSO_PROP_NETWORK_ADAPTER";
+ 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 MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+ protected CloudConfig cloudConfig;
+
+ /**
+ * 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() {
+ }
+
+ /**
+ * This constructor MUST be used if this class if called with the new operator.
+ * @param msoPropFactory
+
+ */
+ public MsoNetworkAdapterImpl(MsoPropertiesFactory msoPropFactory,CloudConfigFactory cloudConfigFact) {
+ this.msoPropertiesFactory = msoPropFactory;
+ this.cloudConfigFactory=cloudConfigFact;
+ cloudConfig = cloudConfigFactory.getCloudConfig ();
+ }
+
+ @Override
+ public void createNetwork (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ 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 <String> ();
+ createNetwork (cloudSiteId,
+ tenantId,
+ networkType,
+ 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 networkName,
+ List <String> 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,
+ 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 networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <String> 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);
+
+ // 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.
+
+ cloudConfig = cloudConfigFactory.getCloudConfig ();
+ CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
+ if (cloudSite == null)
+ {
+ 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);
+ }
+
+ try (CatalogDatabase db = getCatalogDb()) {
+ NetworkResource networkResource = networkCheck (db,
+ startTime,
+ networkType,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ cloudSite);
+ String mode = networkResource.getOrchestrationMode ();
+ NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
+
+ if (NEUTRON_MODE.equals (mode)) {
+
+ // Use an MsoNeutronUtils for all neutron commands
+ MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
+
+ // 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);
+ String error = "Create Network (neutron): query network " + networkName
+ + " in "
+ + cloudSiteId
+ + "/"
+ + tenantId
+ + ": "
+ + me;
+ 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)) {
+
+ // Use an MsoHeatUtils for all Heat commands
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
+ 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;
+ try {
+ aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
+ } catch (MsoPropertiesException e) {
+ String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
+ }
+
+ 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 <String, String> ();
+ 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;
+ String msg = "Found Existing network stack, status=" + heatStack.getStatus () + " for Heat mode";
+ 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.
+ long createStackStartTime = System.currentTimeMillis ();
+ 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 <String, String> ();
+ 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 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,
+ networkId,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ null,
+ null,
+ null,
+ subnets,
+ null,
+ null,
+ msoRequest,
+ subnetIdMap,
+ rollback);
+
+ }
+
+ @Override
+ public void updateNetworkContrail (String cloudSiteId,
+ String tenantId,
+ String networkType,
+ String networkId,
+ String networkName,
+ List <String> 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,
+ 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 networkId,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <String> 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);
+
+ cloudConfig = cloudConfigFactory.getCloudConfig ();
+ CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
+ if (cloudSite == null) {
+ 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);
+ }
+
+ try(CatalogDatabase db = getCatalogDb()) {
+ NetworkResource networkResource = networkCheck (db,
+ startTime,
+ networkType,
+ networkName,
+ physicalNetworkName,
+ vlans,
+ routeTargets,
+ cloudSite);
+ String mode = networkResource.getOrchestrationMode ();
+ NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
+
+ // Use an MsoNeutronUtils for all Neutron commands
+ MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
+
+ 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)) {
+
+ // Use an MsoHeatUtils for all Heat commands
+ MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ // 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 <Integer> ();
+ 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 = db.getHeatTemplate (networkResource.getTemplateId ());
+ 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;
+ try {
+ aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
+ } catch (MsoPropertiesException e) {
+ String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
+ LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
+ }
+ 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 = heat.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 <String, String> ();
+ 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 ());
+ networkRollback.setNeutronNetworkId ((String) outputs.get (NETWORK_ID));
+ 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 (CatalogDatabase db,
+ long startTime,
+ String networkType,
+ String networkName,
+ String physicalNetworkName,
+ List <Integer> vlans,
+ List <String> routeTargets,
+ CloudSite cloudSite) throws NetworkException {
+ // Retrieve the Network Resource definition
+ NetworkResource networkResource = db.getNetworkResource (networkType);
+ if (networkResource == null) {
+ String error = "CreateNetwork: Unknown Network Type: " + networkType;
+ LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Unknown Network Type");
+
+ 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.getAic_version());
+ 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:" + cloudSite.getId()
+ + " with AIC_Version:" + cloudSite.getAic_version());
+ }
+ else
+ {
+ String error = "Network Type:" + networkType
+ + " Version_Min:" + networkResource.getAicVersionMin()
+ + " Version_Max:" + networkResource.getAicVersionMax()
+ + " not supported on Cloud:" + cloudSite.getId()
+ + " with AIC_Version:" + cloudSite.getAic_version();
+ 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 <String>> 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 <String>> 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 (isNullOrEmpty (cloudSiteId)
+ || isNullOrEmpty(tenantId)
+ || 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);
+ }
+
+ cloudConfig = cloudConfigFactory.getCloudConfig ();
+ CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
+ if (cloudSite == null)
+ {
+ 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
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
+ MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
+
+ String mode = null;
+ String neutronId = null;
+ // 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 <String, String> ();
+ 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 <Integer> ();
+
+ 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 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 ();
+
+ try (CatalogDatabase db = getCatalogDb()) {
+ if (isNullOrEmpty (cloudSiteId)
+ || isNullOrEmpty(tenantId)
+ || 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 = db.getNetworkResource (networkType);
+ if (networkResource == null) {
+ String error = "Unknown Network Type: " + networkType;
+ LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Unknown Network Type");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
+
+ String mode = networkResource.getOrchestrationMode ();
+
+ if (NEUTRON_MODE.equals (mode)) {
+
+ // Use MsoNeutronUtils for all NEUTRON commands
+ MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
+ 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 if ("HEAT".equals (mode)) {
+ long deleteStackStarttime = System.currentTimeMillis ();
+ // Use MsoHeatUtils for all HEAT commands
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+
+ 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;
+ }
+
+ public CatalogDatabase getCatalogDb() {
+ return new CatalogDatabase();
+ }
+
+ /**
+ * 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 ();
+
+ LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
+
+ // rollback may be null (e.g. if network already existed when Create was called)
+ // Get a handle to the Catalog Database
+
+ try (CatalogDatabase db = getCatalogDb()){
+
+ // Retrieve the Network Resource definition
+ NetworkResource networkResource = db.getNetworkResource (networkType);
+ if (networkResource == null) {
+ String error = "Rollback Network: Unknown Network Type: " + networkType;
+ LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Rollback Network: Unknown Network Type");
+ LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
+ throw new NetworkException (error, MsoExceptionCategory.USERDATA);
+ }
+ LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
+
+ String 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
+ MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
+ 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 if ("HEAT".equals (mode)) {
+ // Use MsoHeatUtils for all HEAT commands
+ MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
+ 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 <String> routeTargets) {
+ String sep = "";
+ StringBuilder missing = new StringBuilder ();
+ if (isNullOrEmpty(networkName)) {
+ missing.append ("networkName");
+ sep = ",";
+ }
+
+ if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
+ if (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 <String> routeTargets,
+ String shared,
+ String external,
+ boolean aic3template) {
+ // Build the common set of HEAT template parameters
+ Map <String, Object> stackParams = new HashMap <String, Object> ();
+ 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 && !routeTargets.isEmpty()) {
+ StringBuilder buf = new StringBuilder ();
+ String sep = "";
+ for (String rt : routeTargets) {
+ if (!isNullOrEmpty(rt))
+ {
+ if (aic3template)
+ buf.append (sep).append ("target:" + rt.toString ());
+ else
+ buf.append (sep).append (rt.toString ());
+
+ sep = ",";
+ }
+ }
+ String csl = buf.toString ();
+
+ stackParams.put ("route_targets", csl);
+ }
+ if (isNullOrEmpty(shared)) {
+ stackParams.put ("shared", "False");
+ } else {
+ stackParams.put ("shared", shared);
+ }
+ if (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 <ContrailPolicyRef> ();
+ int index = 1;
+ for (String pf : pFqdns) {
+ if (!isNullOrEmpty(pf))
+ {
+ ContrailPolicyRef pr = new ContrailPolicyRef();
+ pr.populate(String.valueOf(index), "0");
+ 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 (!isNullOrEmpty(pf))
+ {
+ buf.append (sep).append (pf.toString ());
+ 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 (!isNullOrEmpty(rtf))
+ {
+ buf.append (sep).append (rtf.toString ());
+ 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 <ContrailSubnet> ();
+ for (Subnet subnet : subnets) {
+ ContrailSubnet cs = new ContrailSubnet();
+ LOGGER.debug("Input Subnet:" + subnet.toString());
+ cs.populateWith(subnet);
+ 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 (!isNullOrEmpty(pool.getStart()) && !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 <String, String> ();
+
+ 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").getTextValue();
+ String uuid = sNode.path("subnet_uuid").getTextValue();
+ String aaiId = name; // default
+ // try to find aaiId for name in input subnetList
+ if (subnets != null)
+ {
+ for (Subnet subnet : subnets)
+ {
+ if ( subnet != null && !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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/NetworkAdapterRest.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/NetworkAdapterRest.java
new file mode 100644
index 0000000000..c813534212
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/NetworkAdapterRest.java
@@ -0,0 +1,595 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network;
+
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.ws.Holder;
+
+import org.apache.http.HttpStatus;
+
+import org.openecomp.mso.adapters.network.exceptions.NetworkException;
+import org.openecomp.mso.adapters.nwrest.ContrailNetwork;
+import org.openecomp.mso.adapters.nwrest.CreateNetworkError;
+import org.openecomp.mso.adapters.nwrest.CreateNetworkRequest;
+import org.openecomp.mso.adapters.nwrest.CreateNetworkResponse;
+import org.openecomp.mso.adapters.nwrest.DeleteNetworkError;
+import org.openecomp.mso.adapters.nwrest.DeleteNetworkRequest;
+import org.openecomp.mso.adapters.nwrest.DeleteNetworkResponse;
+import org.openecomp.mso.adapters.nwrest.ProviderVlanNetwork;
+import org.openecomp.mso.adapters.nwrest.QueryNetworkError;
+import org.openecomp.mso.adapters.nwrest.QueryNetworkResponse;
+import org.openecomp.mso.adapters.nwrest.RollbackNetworkError;
+import org.openecomp.mso.adapters.nwrest.RollbackNetworkRequest;
+import org.openecomp.mso.adapters.nwrest.RollbackNetworkResponse;
+import org.openecomp.mso.adapters.nwrest.UpdateNetworkError;
+import org.openecomp.mso.adapters.nwrest.UpdateNetworkRequest;
+import org.openecomp.mso.adapters.nwrest.UpdateNetworkResponse;
+import org.openecomp.mso.cloud.CloudConfigFactory;
+import org.openecomp.mso.entity.MsoRequest;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.openstack.beans.NetworkRollback;
+import org.openecomp.mso.openstack.beans.NetworkStatus;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+@Path("/v1/networks")
+public class NetworkAdapterRest {
+ private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
+ private static final String TESTING_KEYWORD = "___TESTING___";
+ private final CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
+ private final MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+ private final MsoNetworkAdapterImpl adapter = new MsoNetworkAdapterImpl(msoPropertiesFactory, cloudConfigFactory);
+
+ @POST
+ @Path("")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response createNetwork(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<String>();
+ Holder<String> neutronNetworkId = new Holder<String>();
+ Holder<String> networkFqdn = new Holder<String>();
+ Holder<Map<String, String>> subnetIdMap = new Holder<Map<String, String>>();
+ Holder<NetworkRollback> rollback = new Holder<NetworkRollback>();
+
+ 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.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.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) {
+ eresp = new CreateNetworkError(
+ e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug ("CreateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @DELETE
+ @Path("{aaiNetworkId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response deleteNetwork(
+ @PathParam("aaiNetworkId") String aaiNetworkId,
+ 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<Boolean>();
+ if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
+ networkDeleted.value = true;
+ } else {
+ adapter.deleteNetwork(
+ req.getCloudSiteId(),
+ req.getTenantId(),
+ req.getNetworkType(),
+ req.getNetworkStackId(),
+ req.getMsoRequest(),
+ networkDeleted);
+ }
+ response = new DeleteNetworkResponse(req.getNetworkId(), networkDeleted.value, req.getMessageId());
+ } catch (NetworkException 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 = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("DeleteNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @GET
+ @Path("{aaiNetworkId}")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response queryNetwork(
+ @QueryParam("cloudSiteId") String cloudSiteId,
+ @QueryParam("tenantId") String tenantId,
+ @QueryParam("networkStackId") String networkStackId,
+ @QueryParam("skipAAI") String skipAAI,
+ @QueryParam("msoRequest.requestId") String requestId,
+ @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
+ @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<Boolean>();
+ Holder<String> networkId = new Holder<String>();
+ Holder<String> neutronNetworkId = new Holder<String>();
+ Holder<NetworkStatus> status = new Holder<NetworkStatus>();
+ Holder<List<String>> routeTargets = new Holder<List<String>>();
+ Holder<Map<String, String>> subnetIdMap = new Holder<Map<String, String>>();
+
+ 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 })
+ public Response rollbackNetwork(
+ 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) {
+ eresp = new RollbackNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("RollbackNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ @PUT
+ @Path("{aaiNetworkId}")
+ @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ public Response updateNetwork(
+ @PathParam("aaiNetworkId") String aaiNetworkId,
+ 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<Map<String, String>>();
+ Holder<NetworkRollback> rollback = new Holder<NetworkRollback> ();
+
+ 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.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.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) {
+ eresp = new UpdateNetworkError(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
+ }
+ if (!req.isSynchronous()) {
+ // This is asynch, so POST response back to caller
+ BpelRestClient bpelClient = new BpelRestClient();
+ bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
+ }
+ LOGGER.debug("UpdateNetworkTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
+ }
+ }
+
+ public static Map<String, String> testMap() {
+ Map<String, String> m = new HashMap<String, String>();
+ m.put("mickey", "7");
+ m.put("clyde", "10");
+ m.put("wayne", "99");
+ return m;
+ }
+}
diff --git a/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkException.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkException.java
new file mode 100644
index 0000000000..0fd4d02933
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkException.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network.exceptions;
+
+
+
+import javax.xml.ws.WebFault;
+
+import org.openecomp.mso.adapters.network.exceptions.NetworkExceptionBean;
+import org.openecomp.mso.openstack.exceptions.MsoException;
+import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
+
+/**
+ * This class simply extends Exception (without addition additional functionality)
+ * to provide an identifier for Network related exceptions on create, delete, query.
+ *
+ *
+ */
+@WebFault (name="NetworkException", faultBean="org.openecomp.mso.adapters.network.exceptions.NetworkExceptionBean", targetNamespace="http://com.att.mso/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-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkExceptionBean.java b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkExceptionBean.java
new file mode 100644
index 0000000000..af4e0e386e
--- /dev/null
+++ b/adapters/mso-network-adapter/src/main/java/org/openecomp/mso/adapters/network/exceptions/NetworkExceptionBean.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.adapters.network.exceptions;
+
+
+import java.io.Serializable;
+
+import org.openecomp.mso.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;
+ }
+}