Pingping Lin
Committed by Gerrit Code Review

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
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
18 <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository> 18 <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
19 <feature name="${project.artifactId}" version="${project.version}" 19 <feature name="${project.artifactId}" version="${project.version}"
20 description="${project.description}"> 20 description="${project.description}">
21 + <bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle>
21 <bundle>mvn:${project.groupId}/onos-app-virtualbng/${project.version}</bundle> 22 <bundle>mvn:${project.groupId}/onos-app-virtualbng/${project.version}</bundle>
22 <feature>onos-thirdparty-web</feature> 23 <feature>onos-thirdparty-web</feature>
23 </feature> 24 </feature>
......
...@@ -38,6 +38,11 @@ ...@@ -38,6 +38,11 @@
38 38
39 <dependencies> 39 <dependencies>
40 <dependency> 40 <dependency>
41 + <groupId>com.sun.jersey</groupId>
42 + <artifactId>jersey-client</artifactId>
43 + <version>1.19</version>
44 + </dependency>
45 + <dependency>
41 <groupId>org.onosproject</groupId> 46 <groupId>org.onosproject</groupId>
42 <artifactId>onos-cli</artifactId> 47 <artifactId>onos-cli</artifactId>
43 <version>${project.version}</version> 48 <version>${project.version}</version>
...@@ -75,6 +80,7 @@ ...@@ -75,6 +80,7 @@
75 javax.ws.rs, 80 javax.ws.rs,
76 javax.ws.rs.core, 81 javax.ws.rs.core,
77 com.sun.jersey.api.core, 82 com.sun.jersey.api.core,
83 + com.sun.jersey.api.client,
78 com.sun.jersey.spi.container.servlet, 84 com.sun.jersey.spi.container.servlet,
79 com.sun.jersey.server.impl.container.servlet, 85 com.sun.jersey.server.impl.container.servlet,
80 com.fasterxml.jackson.databind, 86 com.fasterxml.jackson.databind,
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +package org.onosproject.virtualbng;
18 +
19 +import static com.google.common.net.MediaType.JSON_UTF_8;
20 +import static java.net.HttpURLConnection.HTTP_OK;
21 +import static org.slf4j.LoggerFactory.getLogger;
22 +
23 +import com.fasterxml.jackson.databind.JsonNode;
24 +import com.fasterxml.jackson.databind.ObjectMapper;
25 +import com.fasterxml.jackson.databind.node.ObjectNode;
26 +import com.sun.jersey.api.client.Client;
27 +import com.sun.jersey.api.client.ClientResponse;
28 +import com.sun.jersey.api.client.WebResource;
29 +
30 +import java.io.IOException;
31 +
32 +import org.slf4j.Logger;
33 +
34 +public class RestClient {
35 + private final Logger log = getLogger(getClass());
36 + private final String hostName = "10.254.1.22";
37 + private final int xosServerPort = 8000;
38 + private static final String UTF_8 = JSON_UTF_8.toString();
39 + private static final ObjectMapper MAPPER = new ObjectMapper();
40 + private final String url = "http://" + hostName + ":" + xosServerPort
41 + + "/xoslib/rs/vbng_mapping/";
42 +
43 + /**
44 + * Gets a client web resource builder.
45 + *
46 + * @param url the URL to access remote resource
47 + * @return web resource builder
48 + */
49 + public WebResource.Builder getClientBuilder(String url) {
50 + log.info("URL: {}", url);
51 + Client client = Client.create();
52 + WebResource resource = client.resource(url);
53 + return resource.accept(UTF_8).type(UTF_8);
54 + }
55 +
56 + /**
57 + * Builds a REST client and fetches XOS mapping data in JSON format.
58 + *
59 + * @return the vBNG map if REST GET succeeds, otherwise return null
60 + */
61 + public ObjectNode getRest() {
62 + WebResource.Builder builder = getClientBuilder(url);
63 + ClientResponse response = builder.get(ClientResponse.class);
64 +
65 + if (response.getStatus() != HTTP_OK) {
66 + log.info("REST GET request returned error code {}",
67 + response.getStatus());
68 + return null;
69 + }
70 +
71 + String jsonString = response.getEntity(String.class);
72 + log.info("Fetched JSON string: {}", jsonString);
73 +
74 + JsonNode node;
75 + try {
76 + node = MAPPER.readTree(jsonString);
77 + } catch (IOException e) {
78 + log.error("Failed to read JSON string", e);
79 + return null;
80 + }
81 +
82 + return (ObjectNode) node;
83 + }
84 +}
...@@ -184,7 +184,7 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -184,7 +184,7 @@ public class VbngConfigurationManager implements VbngConfigurationService {
184 } 184 }
185 185
186 @Override 186 @Override
187 - public IpAddress recycleAssignedPublicIpAddress(IpAddress 187 + public synchronized IpAddress recycleAssignedPublicIpAddress(IpAddress
188 privateIpAddress) { 188 privateIpAddress) {
189 IpAddress publicIpAddress = ipAddressMap.remove(privateIpAddress); 189 IpAddress publicIpAddress = ipAddressMap.remove(privateIpAddress);
190 if (publicIpAddress == null) { 190 if (publicIpAddress == null) {
...@@ -210,6 +210,61 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -210,6 +210,61 @@ public class VbngConfigurationManager implements VbngConfigurationService {
210 return Collections.unmodifiableMap(ipAddressMap); 210 return Collections.unmodifiableMap(ipAddressMap);
211 } 211 }
212 212
213 + @Override
214 + public synchronized boolean assignSpecifiedPublicIp(IpAddress publicIpAddress,
215 + IpAddress privateIpAddress) {
216 +
217 + // Judge whether this public IP address is in our public IP
218 + // prefix/address list.
219 + boolean isPublicIpExist = false;
220 + for (Entry<IpPrefix, Boolean> prefix: localPublicIpPrefixes.entrySet()) {
221 + if (prefix.getKey().contains(publicIpAddress)) {
222 + isPublicIpExist = true;
223 +
224 + // Judge whether this public IP address is already assigned
225 + if (!prefix.getValue() ||
226 + isAssignedPublicIpAddress(publicIpAddress)) {
227 + log.info("The public IP address {} is already assigned, "
228 + + "and not available.", publicIpAddress);
229 + return false;
230 + }
231 +
232 + // The public IP address is still available
233 + // Store the mapping from private IP address to public IP address
234 + ipAddressMap.put(privateIpAddress, publicIpAddress);
235 +
236 + // Update the prefix status
237 + if (prefix.getKey().prefixLength() == 32) {
238 + updateIpPrefixStatus(prefix.getKey(), false);
239 + return true;
240 + }
241 +
242 + // Judge whether the prefix of this public IP address is used
243 + // up, if so, update the IP prefix status.
244 + int prefixLen = prefix.getKey().prefixLength();
245 + int availableIpNum = (int) Math.pow(2,
246 + IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
247 + int usedIpNum = 0;
248 + for (Entry<IpAddress, IpAddress> ipAddressMapEntry:
249 + ipAddressMap.entrySet()) {
250 + if (prefix.getKey().contains(ipAddressMapEntry.getValue())) {
251 + usedIpNum = usedIpNum + 1;
252 + }
253 + }
254 + if (usedIpNum == availableIpNum) {
255 + updateIpPrefixStatus(prefix.getKey(), false);
256 + }
257 +
258 + return true;
259 + }
260 + }
261 + if (!isPublicIpExist) {
262 + log.info("The public IP address {} retrieved from XOS mapping does "
263 + + "not exist", publicIpAddress);
264 + }
265 + return false;
266 + }
267 +
213 /** 268 /**
214 * Generates a new IP address base on a given IP address plus a number to 269 * Generates a new IP address base on a given IP address plus a number to
215 * increase. 270 * increase.
......
...@@ -81,4 +81,16 @@ public interface VbngConfigurationService { ...@@ -81,4 +81,16 @@ public interface VbngConfigurationService {
81 * @return the address map from private IP address to public IP address 81 * @return the address map from private IP address to public IP address
82 */ 82 */
83 Map<IpAddress, IpAddress> getIpAddressMappings(); 83 Map<IpAddress, IpAddress> getIpAddressMappings();
84 +
85 + /**
86 + * Tries to assign a given public IP address to a private IP address. If
87 + * success, then sets up the mapping from this private IP address to the
88 + * public IP address, and stores the mapping.
89 + *
90 + * @param publicIpAddress the public IP address try to assign
91 + * @param privateIpAddress a private IP address
92 + * @return true if this public IP address is available, otherwise false
93 + */
94 + boolean assignSpecifiedPublicIp(IpAddress publicIpAddress,
95 + IpAddress privateIpAddress);
84 } 96 }
......
...@@ -17,8 +17,12 @@ package org.onosproject.virtualbng; ...@@ -17,8 +17,12 @@ package org.onosproject.virtualbng;
17 17
18 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 +import com.fasterxml.jackson.databind.JsonNode;
21 +import com.fasterxml.jackson.databind.node.ArrayNode;
22 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 import com.google.common.collect.Maps; 23 import com.google.common.collect.Maps;
21 24
25 +import java.util.Iterator;
22 import java.util.Map; 26 import java.util.Map;
23 import java.util.Map.Entry; 27 import java.util.Map.Entry;
24 import java.util.concurrent.ConcurrentHashMap; 28 import java.util.concurrent.ConcurrentHashMap;
...@@ -66,6 +70,7 @@ import org.slf4j.LoggerFactory; ...@@ -66,6 +70,7 @@ import org.slf4j.LoggerFactory;
66 public class VbngManager implements VbngService { 70 public class VbngManager implements VbngService {
67 71
68 private static final String APP_NAME = "org.onosproject.virtualbng"; 72 private static final String APP_NAME = "org.onosproject.virtualbng";
73 + private static final String VBNG_MAP_NAME = "vbng_mapping";
69 74
70 private final Logger log = LoggerFactory.getLogger(getClass()); 75 private final Logger log = LoggerFactory.getLogger(getClass());
71 76
...@@ -113,6 +118,9 @@ public class VbngManager implements VbngService { ...@@ -113,6 +118,9 @@ public class VbngManager implements VbngService {
113 hostService.addListener(hostListener); 118 hostService.addListener(hostListener);
114 119
115 log.info("vBNG Started"); 120 log.info("vBNG Started");
121 +
122 + // Recover the status before vBNG restarts
123 + statusRecovery();
116 } 124 }
117 125
118 @Deactivate 126 @Deactivate
...@@ -122,6 +130,42 @@ public class VbngManager implements VbngService { ...@@ -122,6 +130,42 @@ public class VbngManager implements VbngService {
122 } 130 }
123 131
124 /** 132 /**
133 + * Recovers from XOS record. Re-sets up the mapping between private IP
134 + * address and public IP address, re-calculates intents and re-installs
135 + * those intents.
136 + */
137 + private void statusRecovery() {
138 + log.info("vBNG starts to recover from XOS record......");
139 + RestClient restClient = new RestClient();
140 + ObjectNode map = restClient.getRest();
141 + if (map == null) {
142 + log.info("Stop to recover vBNG status due to the vBNG map "
143 + + "is null!");
144 + return;
145 + }
146 +
147 + log.info("Get record from XOS: {}", map);
148 +
149 + ArrayNode array = (ArrayNode) map.get(VBNG_MAP_NAME);
150 + Iterator<JsonNode> entries = array.elements();
151 + while (entries.hasNext()) {
152 + ObjectNode entry = (ObjectNode) entries.next();
153 +
154 + IpAddress hostIpAdddress =
155 + IpAddress.valueOf(entry.get("private_ip").asText());
156 + IpAddress publicIpAddress =
157 + IpAddress.valueOf(entry.get("routeable_subnet").asText());
158 + MacAddress macAddress =
159 + MacAddress.valueOf(entry.get("mac").asText());
160 + String hostName = entry.get("hostname").asText();
161 +
162 + // Create vBNG
163 + createVbng(hostIpAdddress, publicIpAddress, macAddress, hostName);
164 +
165 + }
166 + }
167 +
168 + /**
125 * Sets up mapping from hostname to connect point. 169 * Sets up mapping from hostname to connect point.
126 */ 170 */
127 private void setupMap() { 171 private void setupMap() {
...@@ -136,6 +180,39 @@ public class VbngManager implements VbngService { ...@@ -136,6 +180,39 @@ public class VbngManager implements VbngService {
136 PortNumber.portNumber(47))); 180 PortNumber.portNumber(47)));
137 } 181 }
138 182
183 + /**
184 + * Creates a new vBNG.
185 + *
186 + * @param privateIpAddress a private IP address
187 + * @param publicIpAddress the public IP address for the private IP address
188 + * @param hostMacAddress the MAC address for the private IP address
189 + * @param hostName the host name for the private IP address
190 + */
191 + private void createVbng(IpAddress privateIpAddress,
192 + IpAddress publicIpAddress,
193 + MacAddress hostMacAddress,
194 + String hostName) {
195 + boolean result = vbngConfigurationService
196 + .assignSpecifiedPublicIp(publicIpAddress, privateIpAddress);
197 + if (!result) {
198 + log.info("Assign public IP address {} for private IP address {} "
199 + + "failed!", publicIpAddress, privateIpAddress);
200 + log.info("Failed to create vBNG for private IP address {}",
201 + privateIpAddress);
202 + return;
203 + }
204 + log.info("[ADD] Private IP to Public IP mapping: {} --> {}",
205 + privateIpAddress, publicIpAddress);
206 +
207 + // Setup paths between the host configured with private IP and
208 + // next hop
209 + if (!setupForwardingPaths(privateIpAddress, publicIpAddress,
210 + hostMacAddress, hostName)) {
211 + privateIpAddressMap.put(privateIpAddress,
212 + new VcpeHost(hostMacAddress, hostName));
213 + }
214 + }
215 +
139 @Override 216 @Override
140 public IpAddress createVbng(IpAddress privateIpAddress, 217 public IpAddress createVbng(IpAddress privateIpAddress,
141 MacAddress hostMacAddress, 218 MacAddress hostMacAddress,
......