restart vBNG based on XOS's record
re-set up the private IP address to public IP address mapping
based on the mapping record in XOS.
re-calculates and re-installs all the intents.
Change-Id: I89aa75662da596b9793e02ba41398a43517ccecf
diff --git a/apps/virtualbng/features.xml b/apps/virtualbng/features.xml
index 10fc32b..2b48bec 100644
--- a/apps/virtualbng/features.xml
+++ b/apps/virtualbng/features.xml
@@ -18,6 +18,7 @@
<repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
+ <bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle>
<bundle>mvn:${project.groupId}/onos-app-virtualbng/${project.version}</bundle>
<feature>onos-thirdparty-web</feature>
</feature>
diff --git a/apps/virtualbng/pom.xml b/apps/virtualbng/pom.xml
index d177014..e42f888 100644
--- a/apps/virtualbng/pom.xml
+++ b/apps/virtualbng/pom.xml
@@ -38,6 +38,11 @@
<dependencies>
<dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.19</version>
+ </dependency>
+ <dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
@@ -75,6 +80,7 @@
javax.ws.rs,
javax.ws.rs.core,
com.sun.jersey.api.core,
+ com.sun.jersey.api.client,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
diff --git a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/RestClient.java b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/RestClient.java
new file mode 100644
index 0000000..b5c1322
--- /dev/null
+++ b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/RestClient.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.
+ *
+ */
+package org.onosproject.virtualbng;
+
+import static com.google.common.net.MediaType.JSON_UTF_8;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+
+public class RestClient {
+ private final Logger log = getLogger(getClass());
+ private final String hostName = "10.254.1.22";
+ private final int xosServerPort = 8000;
+ private static final String UTF_8 = JSON_UTF_8.toString();
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+ private final String url = "http://" + hostName + ":" + xosServerPort
+ + "/xoslib/rs/vbng_mapping/";
+
+ /**
+ * Gets a client web resource builder.
+ *
+ * @param url the URL to access remote resource
+ * @return web resource builder
+ */
+ public WebResource.Builder getClientBuilder(String url) {
+ log.info("URL: {}", url);
+ Client client = Client.create();
+ WebResource resource = client.resource(url);
+ return resource.accept(UTF_8).type(UTF_8);
+ }
+
+ /**
+ * Builds a REST client and fetches XOS mapping data in JSON format.
+ *
+ * @return the vBNG map if REST GET succeeds, otherwise return null
+ */
+ public ObjectNode getRest() {
+ WebResource.Builder builder = getClientBuilder(url);
+ ClientResponse response = builder.get(ClientResponse.class);
+
+ if (response.getStatus() != HTTP_OK) {
+ log.info("REST GET request returned error code {}",
+ response.getStatus());
+ return null;
+ }
+
+ String jsonString = response.getEntity(String.class);
+ log.info("Fetched JSON string: {}", jsonString);
+
+ JsonNode node;
+ try {
+ node = MAPPER.readTree(jsonString);
+ } catch (IOException e) {
+ log.error("Failed to read JSON string", e);
+ return null;
+ }
+
+ return (ObjectNode) node;
+ }
+}
diff --git a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
index 35f4542..653a87d 100644
--- a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
+++ b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
@@ -184,7 +184,7 @@
}
@Override
- public IpAddress recycleAssignedPublicIpAddress(IpAddress
+ public synchronized IpAddress recycleAssignedPublicIpAddress(IpAddress
privateIpAddress) {
IpAddress publicIpAddress = ipAddressMap.remove(privateIpAddress);
if (publicIpAddress == null) {
@@ -210,6 +210,61 @@
return Collections.unmodifiableMap(ipAddressMap);
}
+ @Override
+ public synchronized boolean assignSpecifiedPublicIp(IpAddress publicIpAddress,
+ IpAddress privateIpAddress) {
+
+ // Judge whether this public IP address is in our public IP
+ // prefix/address list.
+ boolean isPublicIpExist = false;
+ for (Entry<IpPrefix, Boolean> prefix: localPublicIpPrefixes.entrySet()) {
+ if (prefix.getKey().contains(publicIpAddress)) {
+ isPublicIpExist = true;
+
+ // Judge whether this public IP address is already assigned
+ if (!prefix.getValue() ||
+ isAssignedPublicIpAddress(publicIpAddress)) {
+ log.info("The public IP address {} is already assigned, "
+ + "and not available.", publicIpAddress);
+ return false;
+ }
+
+ // The public IP address is still available
+ // Store the mapping from private IP address to public IP address
+ ipAddressMap.put(privateIpAddress, publicIpAddress);
+
+ // Update the prefix status
+ if (prefix.getKey().prefixLength() == 32) {
+ updateIpPrefixStatus(prefix.getKey(), false);
+ return true;
+ }
+
+ // Judge whether the prefix of this public IP address is used
+ // up, if so, update the IP prefix status.
+ int prefixLen = prefix.getKey().prefixLength();
+ int availableIpNum = (int) Math.pow(2,
+ IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
+ int usedIpNum = 0;
+ for (Entry<IpAddress, IpAddress> ipAddressMapEntry:
+ ipAddressMap.entrySet()) {
+ if (prefix.getKey().contains(ipAddressMapEntry.getValue())) {
+ usedIpNum = usedIpNum + 1;
+ }
+ }
+ if (usedIpNum == availableIpNum) {
+ updateIpPrefixStatus(prefix.getKey(), false);
+ }
+
+ return true;
+ }
+ }
+ if (!isPublicIpExist) {
+ log.info("The public IP address {} retrieved from XOS mapping does "
+ + "not exist", publicIpAddress);
+ }
+ return false;
+ }
+
/**
* Generates a new IP address base on a given IP address plus a number to
* increase.
diff --git a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
index 31e6d4f..6f17ebc 100644
--- a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
+++ b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
@@ -81,4 +81,16 @@
* @return the address map from private IP address to public IP address
*/
Map<IpAddress, IpAddress> getIpAddressMappings();
+
+ /**
+ * Tries to assign a given public IP address to a private IP address. If
+ * success, then sets up the mapping from this private IP address to the
+ * public IP address, and stores the mapping.
+ *
+ * @param publicIpAddress the public IP address try to assign
+ * @param privateIpAddress a private IP address
+ * @return true if this public IP address is available, otherwise false
+ */
+ boolean assignSpecifiedPublicIp(IpAddress publicIpAddress,
+ IpAddress privateIpAddress);
}
diff --git a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
index 775cff4..8fae896 100644
--- a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
+++ b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
@@ -17,8 +17,12 @@
import static com.google.common.base.Preconditions.checkNotNull;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Maps;
+import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
@@ -66,6 +70,7 @@
public class VbngManager implements VbngService {
private static final String APP_NAME = "org.onosproject.virtualbng";
+ private static final String VBNG_MAP_NAME = "vbng_mapping";
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -113,6 +118,9 @@
hostService.addListener(hostListener);
log.info("vBNG Started");
+
+ // Recover the status before vBNG restarts
+ statusRecovery();
}
@Deactivate
@@ -122,6 +130,42 @@
}
/**
+ * Recovers from XOS record. Re-sets up the mapping between private IP
+ * address and public IP address, re-calculates intents and re-installs
+ * those intents.
+ */
+ private void statusRecovery() {
+ log.info("vBNG starts to recover from XOS record......");
+ RestClient restClient = new RestClient();
+ ObjectNode map = restClient.getRest();
+ if (map == null) {
+ log.info("Stop to recover vBNG status due to the vBNG map "
+ + "is null!");
+ return;
+ }
+
+ log.info("Get record from XOS: {}", map);
+
+ ArrayNode array = (ArrayNode) map.get(VBNG_MAP_NAME);
+ Iterator<JsonNode> entries = array.elements();
+ while (entries.hasNext()) {
+ ObjectNode entry = (ObjectNode) entries.next();
+
+ IpAddress hostIpAdddress =
+ IpAddress.valueOf(entry.get("private_ip").asText());
+ IpAddress publicIpAddress =
+ IpAddress.valueOf(entry.get("routeable_subnet").asText());
+ MacAddress macAddress =
+ MacAddress.valueOf(entry.get("mac").asText());
+ String hostName = entry.get("hostname").asText();
+
+ // Create vBNG
+ createVbng(hostIpAdddress, publicIpAddress, macAddress, hostName);
+
+ }
+ }
+
+ /**
* Sets up mapping from hostname to connect point.
*/
private void setupMap() {
@@ -136,6 +180,39 @@
PortNumber.portNumber(47)));
}
+ /**
+ * Creates a new vBNG.
+ *
+ * @param privateIpAddress a private IP address
+ * @param publicIpAddress the public IP address for the private IP address
+ * @param hostMacAddress the MAC address for the private IP address
+ * @param hostName the host name for the private IP address
+ */
+ private void createVbng(IpAddress privateIpAddress,
+ IpAddress publicIpAddress,
+ MacAddress hostMacAddress,
+ String hostName) {
+ boolean result = vbngConfigurationService
+ .assignSpecifiedPublicIp(publicIpAddress, privateIpAddress);
+ if (!result) {
+ log.info("Assign public IP address {} for private IP address {} "
+ + "failed!", publicIpAddress, privateIpAddress);
+ log.info("Failed to create vBNG for private IP address {}",
+ privateIpAddress);
+ return;
+ }
+ log.info("[ADD] Private IP to Public IP mapping: {} --> {}",
+ privateIpAddress, publicIpAddress);
+
+ // Setup paths between the host configured with private IP and
+ // next hop
+ if (!setupForwardingPaths(privateIpAddress, publicIpAddress,
+ hostMacAddress, hostName)) {
+ privateIpAddressMap.put(privateIpAddress,
+ new VcpeHost(hostMacAddress, hostName));
+ }
+ }
+
@Override
public IpAddress createVbng(IpAddress privateIpAddress,
MacAddress hostMacAddress,