Committed by
Gerrit Code Review
CORD-562 Don't allow nodes with duplicate hostname
And update existing node if newly added node has the same hostname with existing node. Change-Id: Ifebbf4129df4f742e16b9a25be619dd90e0745ff
Showing
4 changed files
with
88 additions
and
25 deletions
... | @@ -60,7 +60,7 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -60,7 +60,7 @@ public class CordVtnConfig extends Config<ApplicationId> { |
60 | /** | 60 | /** |
61 | * Returns the set of nodes read from network config. | 61 | * Returns the set of nodes read from network config. |
62 | * | 62 | * |
63 | - * @return set of CordVtnNodeConfig or null | 63 | + * @return set of CordVtnNodeConfig or empty set |
64 | */ | 64 | */ |
65 | public Set<CordVtnNode> cordVtnNodes() { | 65 | public Set<CordVtnNode> cordVtnNodes() { |
66 | 66 | ||
... | @@ -68,7 +68,7 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -68,7 +68,7 @@ public class CordVtnConfig extends Config<ApplicationId> { |
68 | JsonNode jsonNodes = object.get(CORDVTN_NODES); | 68 | JsonNode jsonNodes = object.get(CORDVTN_NODES); |
69 | if (jsonNodes == null) { | 69 | if (jsonNodes == null) { |
70 | log.debug("No CORD VTN nodes found"); | 70 | log.debug("No CORD VTN nodes found"); |
71 | - return null; | 71 | + return nodes; |
72 | } | 72 | } |
73 | 73 | ||
74 | for (JsonNode jsonNode : jsonNodes) { | 74 | for (JsonNode jsonNode : jsonNodes) { |
... | @@ -94,7 +94,8 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -94,7 +94,8 @@ public class CordVtnConfig extends Config<ApplicationId> { |
94 | TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))), | 94 | TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))), |
95 | sshInfo, | 95 | sshInfo, |
96 | DeviceId.deviceId(getConfig(jsonNode, BRIDGE_ID)), | 96 | DeviceId.deviceId(getConfig(jsonNode, BRIDGE_ID)), |
97 | - getConfig(jsonNode, DATA_PLANE_INTF)); | 97 | + getConfig(jsonNode, DATA_PLANE_INTF), |
98 | + CordVtnNodeState.noState()); | ||
98 | 99 | ||
99 | log.info("Successfully read {} from the config", hostname); | 100 | log.info("Successfully read {} from the config", hostname); |
100 | nodes.add(newNode); | 101 | nodes.add(newNode); | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014-2015 Open Networking Laboratory | 2 | + * Copyright 2015-2016 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -37,6 +37,7 @@ public final class CordVtnNode { | ... | @@ -37,6 +37,7 @@ public final class CordVtnNode { |
37 | private final SshAccessInfo sshInfo; | 37 | private final SshAccessInfo sshInfo; |
38 | private final DeviceId bridgeId; | 38 | private final DeviceId bridgeId; |
39 | private final String dpIntf; | 39 | private final String dpIntf; |
40 | + private final CordVtnNodeState state; | ||
40 | 41 | ||
41 | public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR = | 42 | public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR = |
42 | (node1, node2) -> node1.hostname().compareTo(node2.hostname()); | 43 | (node1, node2) -> node1.hostname().compareTo(node2.hostname()); |
... | @@ -52,10 +53,11 @@ public final class CordVtnNode { | ... | @@ -52,10 +53,11 @@ public final class CordVtnNode { |
52 | * @param sshInfo SSH access information | 53 | * @param sshInfo SSH access information |
53 | * @param bridgeId integration bridge identifier | 54 | * @param bridgeId integration bridge identifier |
54 | * @param dpIntf data plane interface name | 55 | * @param dpIntf data plane interface name |
56 | + * @param state cordvtn node state | ||
55 | */ | 57 | */ |
56 | public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp, | 58 | public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp, |
57 | NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo, | 59 | NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo, |
58 | - DeviceId bridgeId, String dpIntf) { | 60 | + DeviceId bridgeId, String dpIntf, CordVtnNodeState state) { |
59 | this.hostname = checkNotNull(hostname, "hostname cannot be null"); | 61 | this.hostname = checkNotNull(hostname, "hostname cannot be null"); |
60 | this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null"); | 62 | this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null"); |
61 | this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null"); | 63 | this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null"); |
... | @@ -64,6 +66,23 @@ public final class CordVtnNode { | ... | @@ -64,6 +66,23 @@ public final class CordVtnNode { |
64 | this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null"); | 66 | this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null"); |
65 | this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null"); | 67 | this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null"); |
66 | this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null"); | 68 | this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null"); |
69 | + this.state = state; | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * Returns cordvtn node with new state. | ||
74 | + * | ||
75 | + * @param node cordvtn node | ||
76 | + * @param state cordvtn node init state | ||
77 | + * @return cordvtn node | ||
78 | + */ | ||
79 | + public static CordVtnNode getUpdatedNode(CordVtnNode node, CordVtnNodeState state) { | ||
80 | + return new CordVtnNode(node.hostname, | ||
81 | + node.hostMgmtIp, node.localMgmtIp, node.dpIp, | ||
82 | + node.ovsdbPort, | ||
83 | + node.sshInfo, | ||
84 | + node.bridgeId, | ||
85 | + node.dpIntf, state); | ||
67 | } | 86 | } |
68 | 87 | ||
69 | /** | 88 | /** |
... | @@ -147,6 +166,15 @@ public final class CordVtnNode { | ... | @@ -147,6 +166,15 @@ public final class CordVtnNode { |
147 | return this.dpIntf; | 166 | return this.dpIntf; |
148 | } | 167 | } |
149 | 168 | ||
169 | + /** | ||
170 | + * Returns the state of the node. | ||
171 | + * | ||
172 | + * @return state | ||
173 | + */ | ||
174 | + public CordVtnNodeState state() { | ||
175 | + return this.state; | ||
176 | + } | ||
177 | + | ||
150 | @Override | 178 | @Override |
151 | public boolean equals(Object obj) { | 179 | public boolean equals(Object obj) { |
152 | if (this == obj) { | 180 | if (this == obj) { |
... | @@ -180,6 +208,7 @@ public final class CordVtnNode { | ... | @@ -180,6 +208,7 @@ public final class CordVtnNode { |
180 | .add("sshInfo", sshInfo) | 208 | .add("sshInfo", sshInfo) |
181 | .add("bridgeId", bridgeId) | 209 | .add("bridgeId", bridgeId) |
182 | .add("dpIntf", dpIntf) | 210 | .add("dpIntf", dpIntf) |
211 | + .add("state", state) | ||
183 | .toString(); | 212 | .toString(); |
184 | } | 213 | } |
185 | } | 214 | } | ... | ... |
... | @@ -72,6 +72,7 @@ import java.util.List; | ... | @@ -72,6 +72,7 @@ import java.util.List; |
72 | import java.util.Map; | 72 | import java.util.Map; |
73 | import java.util.Set; | 73 | import java.util.Set; |
74 | import java.util.concurrent.ExecutorService; | 74 | import java.util.concurrent.ExecutorService; |
75 | +import java.util.stream.Collectors; | ||
75 | 76 | ||
76 | import static com.google.common.base.Preconditions.checkNotNull; | 77 | import static com.google.common.base.Preconditions.checkNotNull; |
77 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | 78 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; |
... | @@ -165,11 +166,11 @@ public class CordVtnNodeManager { | ... | @@ -165,11 +166,11 @@ public class CordVtnNodeManager { |
165 | private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); | 166 | private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); |
166 | private final BridgeHandler bridgeHandler = new BridgeHandler(); | 167 | private final BridgeHandler bridgeHandler = new BridgeHandler(); |
167 | 168 | ||
168 | - private ConsistentMap<CordVtnNode, NodeState> nodeStore; | 169 | + private ConsistentMap<String, CordVtnNode> nodeStore; |
169 | private CordVtnRuleInstaller ruleInstaller; | 170 | private CordVtnRuleInstaller ruleInstaller; |
170 | private ApplicationId appId; | 171 | private ApplicationId appId; |
171 | 172 | ||
172 | - private enum NodeState { | 173 | + private enum NodeState implements CordVtnNodeState { |
173 | 174 | ||
174 | INIT { | 175 | INIT { |
175 | @Override | 176 | @Override |
... | @@ -197,7 +198,6 @@ public class CordVtnNodeManager { | ... | @@ -197,7 +198,6 @@ public class CordVtnNodeManager { |
197 | public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | 198 | public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { |
198 | nodeManager.setIpAddress(node); | 199 | nodeManager.setIpAddress(node); |
199 | } | 200 | } |
200 | - | ||
201 | }, | 201 | }, |
202 | COMPLETE { | 202 | COMPLETE { |
203 | @Override | 203 | @Override |
... | @@ -217,7 +217,7 @@ public class CordVtnNodeManager { | ... | @@ -217,7 +217,7 @@ public class CordVtnNodeManager { |
217 | @Activate | 217 | @Activate |
218 | protected void active() { | 218 | protected void active() { |
219 | appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID); | 219 | appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID); |
220 | - nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder() | 220 | + nodeStore = storageService.<String, CordVtnNode>consistentMapBuilder() |
221 | .withSerializer(Serializer.using(NODE_SERIALIZER.build())) | 221 | .withSerializer(Serializer.using(NODE_SERIALIZER.build())) |
222 | .withName("cordvtn-nodestore") | 222 | .withName("cordvtn-nodestore") |
223 | .withApplicationId(appId) | 223 | .withApplicationId(appId) |
... | @@ -252,7 +252,8 @@ public class CordVtnNodeManager { | ... | @@ -252,7 +252,8 @@ public class CordVtnNodeManager { |
252 | public void addNode(CordVtnNode node) { | 252 | public void addNode(CordVtnNode node) { |
253 | checkNotNull(node); | 253 | checkNotNull(node); |
254 | 254 | ||
255 | - nodeStore.putIfAbsent(node, getNodeState(node)); | 255 | + // allow update node attributes |
256 | + nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, getNodeState(node))); | ||
256 | initNode(node); | 257 | initNode(node); |
257 | } | 258 | } |
258 | 259 | ||
... | @@ -268,7 +269,7 @@ public class CordVtnNodeManager { | ... | @@ -268,7 +269,7 @@ public class CordVtnNodeManager { |
268 | disconnectOvsdb(node); | 269 | disconnectOvsdb(node); |
269 | } | 270 | } |
270 | 271 | ||
271 | - nodeStore.remove(node); | 272 | + nodeStore.remove(node.hostname()); |
272 | } | 273 | } |
273 | 274 | ||
274 | /** | 275 | /** |
... | @@ -279,12 +280,13 @@ public class CordVtnNodeManager { | ... | @@ -279,12 +280,13 @@ public class CordVtnNodeManager { |
279 | public void initNode(CordVtnNode node) { | 280 | public void initNode(CordVtnNode node) { |
280 | checkNotNull(node); | 281 | checkNotNull(node); |
281 | 282 | ||
282 | - if (!nodeStore.containsKey(node)) { | 283 | + if (!nodeStore.containsKey(node.hostname())) { |
283 | log.warn("Node {} does not exist, add node first", node.hostname()); | 284 | log.warn("Node {} does not exist, add node first", node.hostname()); |
284 | return; | 285 | return; |
285 | } | 286 | } |
286 | 287 | ||
287 | NodeState state = getNodeState(node); | 288 | NodeState state = getNodeState(node); |
289 | + log.debug("Init node: {} state: {}", node.hostname(), state.toString()); | ||
288 | state.process(this, node); | 290 | state.process(this, node); |
289 | } | 291 | } |
290 | 292 | ||
... | @@ -296,7 +298,7 @@ public class CordVtnNodeManager { | ... | @@ -296,7 +298,7 @@ public class CordVtnNodeManager { |
296 | */ | 298 | */ |
297 | public boolean isNodeInitComplete(CordVtnNode node) { | 299 | public boolean isNodeInitComplete(CordVtnNode node) { |
298 | checkNotNull(node); | 300 | checkNotNull(node); |
299 | - return nodeStore.containsKey(node) && getNodeState(node).equals(NodeState.COMPLETE); | 301 | + return nodeStore.containsKey(node.hostname()) && getNodeState(node).equals(NodeState.COMPLETE); |
300 | } | 302 | } |
301 | 303 | ||
302 | /** | 304 | /** |
... | @@ -311,8 +313,9 @@ public class CordVtnNodeManager { | ... | @@ -311,8 +313,9 @@ public class CordVtnNodeManager { |
311 | // the state saved in nodeStore can be wrong if IP address settings are changed | 313 | // the state saved in nodeStore can be wrong if IP address settings are changed |
312 | // after the node init has been completed since there's no way to detect it | 314 | // after the node init has been completed since there's no way to detect it |
313 | // getNodeState and checkNodeInitState always return correct answer but can be slow | 315 | // getNodeState and checkNodeInitState always return correct answer but can be slow |
314 | - Versioned<NodeState> state = nodeStore.get(node); | 316 | + Versioned<CordVtnNode> versionedNode = nodeStore.get(node.hostname()); |
315 | - return state != null && state.value().equals(NodeState.COMPLETE); | 317 | + CordVtnNodeState state = versionedNode.value().state(); |
318 | + return state != null && state.equals(NodeState.COMPLETE); | ||
316 | } | 319 | } |
317 | 320 | ||
318 | /** | 321 | /** |
... | @@ -324,7 +327,7 @@ public class CordVtnNodeManager { | ... | @@ -324,7 +327,7 @@ public class CordVtnNodeManager { |
324 | public String checkNodeInitState(CordVtnNode node) { | 327 | public String checkNodeInitState(CordVtnNode node) { |
325 | checkNotNull(node); | 328 | checkNotNull(node); |
326 | 329 | ||
327 | - if (!nodeStore.containsKey(node)) { | 330 | + if (!nodeStore.containsKey(node.hostname())) { |
328 | log.warn("Node {} does not exist, add node first", node.hostname()); | 331 | log.warn("Node {} does not exist, add node first", node.hostname()); |
329 | return null; | 332 | return null; |
330 | } | 333 | } |
... | @@ -337,13 +340,13 @@ public class CordVtnNodeManager { | ... | @@ -337,13 +340,13 @@ public class CordVtnNodeManager { |
337 | 340 | ||
338 | Set<IpAddress> intBrIps = RemoteIpCommandUtil.getCurrentIps(session, DEFAULT_BRIDGE); | 341 | Set<IpAddress> intBrIps = RemoteIpCommandUtil.getCurrentIps(session, DEFAULT_BRIDGE); |
339 | String result = String.format( | 342 | String result = String.format( |
340 | - "Integration bridge created/connected : %s (%s)%n" + | 343 | + "br-int created and connected : %s (%s)%n" + |
341 | "VXLAN interface created : %s%n" + | 344 | "VXLAN interface created : %s%n" + |
342 | "Data plane interface added : %s (%s)%n" + | 345 | "Data plane interface added : %s (%s)%n" + |
343 | "IP flushed from %s : %s%n" + | 346 | "IP flushed from %s : %s%n" + |
344 | "Data plane IP added to br-int : %s (%s)%n" + | 347 | "Data plane IP added to br-int : %s (%s)%n" + |
345 | "Local management IP added to br-int : %s (%s)", | 348 | "Local management IP added to br-int : %s (%s)", |
346 | - isBrIntCreated(node) ? OK : NO, DEFAULT_BRIDGE, | 349 | + isBrIntCreated(node) ? OK : NO, node.intBrId(), |
347 | isTunnelIntfCreated(node) ? OK : NO, | 350 | isTunnelIntfCreated(node) ? OK : NO, |
348 | isDataPlaneIntfAdded(node) ? OK : NO, node.dpIntf(), | 351 | isDataPlaneIntfAdded(node) ? OK : NO, node.dpIntf(), |
349 | node.dpIntf(), | 352 | node.dpIntf(), |
... | @@ -371,9 +374,9 @@ public class CordVtnNodeManager { | ... | @@ -371,9 +374,9 @@ public class CordVtnNodeManager { |
371 | * @return list of nodes | 374 | * @return list of nodes |
372 | */ | 375 | */ |
373 | public List<CordVtnNode> getNodes() { | 376 | public List<CordVtnNode> getNodes() { |
374 | - List<CordVtnNode> nodes = new ArrayList<>(); | 377 | + return nodeStore.values().stream() |
375 | - nodes.addAll(nodeStore.keySet()); | 378 | + .map(Versioned::value) |
376 | - return nodes; | 379 | + .collect(Collectors.toList()); |
377 | } | 380 | } |
378 | 381 | ||
379 | /** | 382 | /** |
... | @@ -410,8 +413,7 @@ public class CordVtnNodeManager { | ... | @@ -410,8 +413,7 @@ public class CordVtnNodeManager { |
410 | checkNotNull(node); | 413 | checkNotNull(node); |
411 | 414 | ||
412 | log.debug("Changed {} state: {}", node.hostname(), newState.toString()); | 415 | log.debug("Changed {} state: {}", node.hostname(), newState.toString()); |
413 | - | 416 | + nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, newState)); |
414 | - nodeStore.put(node, newState); | ||
415 | newState.process(this, node); | 417 | newState.process(this, node); |
416 | } | 418 | } |
417 | 419 | ||
... | @@ -497,7 +499,7 @@ public class CordVtnNodeManager { | ... | @@ -497,7 +499,7 @@ public class CordVtnNodeManager { |
497 | private void connectOvsdb(CordVtnNode node) { | 499 | private void connectOvsdb(CordVtnNode node) { |
498 | checkNotNull(node); | 500 | checkNotNull(node); |
499 | 501 | ||
500 | - if (!nodeStore.containsKey(node)) { | 502 | + if (!nodeStore.containsKey(node.hostname())) { |
501 | log.warn("Node {} does not exist", node.hostname()); | 503 | log.warn("Node {} does not exist", node.hostname()); |
502 | return; | 504 | return; |
503 | } | 505 | } |
... | @@ -515,7 +517,7 @@ public class CordVtnNodeManager { | ... | @@ -515,7 +517,7 @@ public class CordVtnNodeManager { |
515 | private void disconnectOvsdb(CordVtnNode node) { | 517 | private void disconnectOvsdb(CordVtnNode node) { |
516 | checkNotNull(node); | 518 | checkNotNull(node); |
517 | 519 | ||
518 | - if (!nodeStore.containsKey(node)) { | 520 | + if (!nodeStore.containsKey(node.hostname())) { |
519 | log.warn("Node {} does not exist", node.hostname()); | 521 | log.warn("Node {} does not exist", node.hostname()); |
520 | return; | 522 | return; |
521 | } | 523 | } |
... | @@ -747,6 +749,7 @@ public class CordVtnNodeManager { | ... | @@ -747,6 +749,7 @@ public class CordVtnNodeManager { |
747 | @Override | 749 | @Override |
748 | public void disconnected(Device device) { | 750 | public void disconnected(Device device) { |
749 | if (!deviceService.isAvailable(device.id())) { | 751 | if (!deviceService.isAvailable(device.id())) { |
752 | + log.debug("Device {} is disconnected", device.id()); | ||
750 | adminService.removeDevice(device.id()); | 753 | adminService.removeDevice(device.id()); |
751 | } | 754 | } |
752 | } | 755 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 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 | +package org.onosproject.cordvtn; | ||
17 | + | ||
18 | +/** | ||
19 | + * Entity that defines possible init state of the cordvtn node. | ||
20 | + */ | ||
21 | +public interface CordVtnNodeState { | ||
22 | + /** | ||
23 | + * Returns null for no state. | ||
24 | + * | ||
25 | + * @return null | ||
26 | + */ | ||
27 | + static CordVtnNodeState noState() { | ||
28 | + return null; | ||
29 | + } | ||
30 | +} |
-
Please register or login to post a comment