Committed by
Gerrit Code Review
[Goldeneye] CORD-568 Ensure location transparency of node init operation
- Added MapListener for cordvtn node store and made the init process to be triggered by map event, so that the leader can do its job regardless of the location where node init CLI command happens - Fixed equals and hashCode override to use all node attributes except for the node init state - Adjusted some log levels Change-Id: I45688afa60de3516d91132e8a6c49cf90c4dcae4
Showing
5 changed files
with
81 additions
and
39 deletions
... | @@ -718,7 +718,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -718,7 +718,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
718 | .stream() | 718 | .stream() |
719 | .forEach(entry -> { | 719 | .forEach(entry -> { |
720 | arpProxy.addGateway(entry.getKey(), entry.getValue()); | 720 | arpProxy.addGateway(entry.getKey(), entry.getValue()); |
721 | - log.debug("Added public gateway IP {}, MAC {}", | 721 | + log.info("Added public gateway IP {}, MAC {}", |
722 | entry.getKey().toString(), entry.getValue().toString()); | 722 | entry.getKey().toString(), entry.getValue().toString()); |
723 | }); | 723 | }); |
724 | // TODO notice gateway MAC change to VMs holds this gateway IP | 724 | // TODO notice gateway MAC change to VMs holds this gateway IP | ... | ... |
... | @@ -97,7 +97,6 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -97,7 +97,6 @@ public class CordVtnConfig extends Config<ApplicationId> { |
97 | getConfig(jsonNode, DATA_PLANE_INTF), | 97 | getConfig(jsonNode, DATA_PLANE_INTF), |
98 | CordVtnNodeState.noState()); | 98 | CordVtnNodeState.noState()); |
99 | 99 | ||
100 | - log.info("Successfully read {} from the config", hostname); | ||
101 | nodes.add(newNode); | 100 | nodes.add(newNode); |
102 | } catch (IllegalArgumentException | NullPointerException e) { | 101 | } catch (IllegalArgumentException | NullPointerException e) { |
103 | log.error("{}", e.toString()); | 102 | log.error("{}", e.toString()); |
... | @@ -121,7 +120,6 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -121,7 +120,6 @@ public class CordVtnConfig extends Config<ApplicationId> { |
121 | log.error("{} is not configured", path); | 120 | log.error("{} is not configured", path); |
122 | return null; | 121 | return null; |
123 | } else { | 122 | } else { |
124 | - log.debug("{} : {}", path, jsonNode.asText()); | ||
125 | return jsonNode.asText(); | 123 | return jsonNode.asText(); |
126 | } | 124 | } |
127 | } | 125 | } | ... | ... |
... | @@ -181,11 +181,16 @@ public final class CordVtnNode { | ... | @@ -181,11 +181,16 @@ public final class CordVtnNode { |
181 | return true; | 181 | return true; |
182 | } | 182 | } |
183 | 183 | ||
184 | - // hostname here is a network hostname and it is intended to be | ||
185 | - // unique throughout the service. | ||
186 | if (obj instanceof CordVtnNode) { | 184 | if (obj instanceof CordVtnNode) { |
187 | CordVtnNode that = (CordVtnNode) obj; | 185 | CordVtnNode that = (CordVtnNode) obj; |
188 | - if (Objects.equals(hostname, that.hostname)) { | 186 | + if (Objects.equals(hostname, that.hostname) && |
187 | + Objects.equals(hostMgmtIp, that.hostMgmtIp) && | ||
188 | + Objects.equals(localMgmtIp, that.localMgmtIp) && | ||
189 | + Objects.equals(dpIp, that.dpIp) && | ||
190 | + Objects.equals(ovsdbPort, that.ovsdbPort) && | ||
191 | + Objects.equals(sshInfo, that.sshInfo) && | ||
192 | + Objects.equals(bridgeId, that.bridgeId) && | ||
193 | + Objects.equals(dpIntf, that.dpIntf)) { | ||
189 | return true; | 194 | return true; |
190 | } | 195 | } |
191 | } | 196 | } |
... | @@ -194,7 +199,8 @@ public final class CordVtnNode { | ... | @@ -194,7 +199,8 @@ public final class CordVtnNode { |
194 | 199 | ||
195 | @Override | 200 | @Override |
196 | public int hashCode() { | 201 | public int hashCode() { |
197 | - return Objects.hash(hostname); | 202 | + return Objects.hash(hostname, hostMgmtIp, localMgmtIp, dpIp, |
203 | + ovsdbPort, sshInfo, bridgeId, dpIntf); | ||
198 | } | 204 | } |
199 | 205 | ||
200 | @Override | 206 | @Override | ... | ... |
... | @@ -62,6 +62,8 @@ import org.onosproject.ovsdb.controller.OvsdbController; | ... | @@ -62,6 +62,8 @@ import org.onosproject.ovsdb.controller.OvsdbController; |
62 | import org.onosproject.ovsdb.controller.OvsdbNodeId; | 62 | import org.onosproject.ovsdb.controller.OvsdbNodeId; |
63 | import org.onosproject.store.serializers.KryoNamespaces; | 63 | import org.onosproject.store.serializers.KryoNamespaces; |
64 | import org.onosproject.store.service.ConsistentMap; | 64 | import org.onosproject.store.service.ConsistentMap; |
65 | +import org.onosproject.store.service.MapEvent; | ||
66 | +import org.onosproject.store.service.MapEventListener; | ||
65 | import org.onosproject.store.service.Serializer; | 67 | import org.onosproject.store.service.Serializer; |
66 | import org.onosproject.store.service.StorageService; | 68 | import org.onosproject.store.service.StorageService; |
67 | import org.onosproject.store.service.Versioned; | 69 | import org.onosproject.store.service.Versioned; |
... | @@ -164,6 +166,7 @@ public class CordVtnNodeManager { | ... | @@ -164,6 +166,7 @@ public class CordVtnNodeManager { |
164 | 166 | ||
165 | private final NetworkConfigListener configListener = new InternalConfigListener(); | 167 | private final NetworkConfigListener configListener = new InternalConfigListener(); |
166 | private final DeviceListener deviceListener = new InternalDeviceListener(); | 168 | private final DeviceListener deviceListener = new InternalDeviceListener(); |
169 | + private final MapEventListener<String, CordVtnNode> nodeStoreListener = new InternalMapListener(); | ||
167 | 170 | ||
168 | private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); | 171 | private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); |
169 | private final BridgeHandler bridgeHandler = new BridgeHandler(); | 172 | private final BridgeHandler bridgeHandler = new BridgeHandler(); |
... | @@ -236,6 +239,7 @@ public class CordVtnNodeManager { | ... | @@ -236,6 +239,7 @@ public class CordVtnNodeManager { |
236 | configRegistry, | 239 | configRegistry, |
237 | DEFAULT_TUNNEL); | 240 | DEFAULT_TUNNEL); |
238 | 241 | ||
242 | + nodeStore.addListener(nodeStoreListener); | ||
239 | deviceService.addListener(deviceListener); | 243 | deviceService.addListener(deviceListener); |
240 | configService.addListener(configListener); | 244 | configService.addListener(configListener); |
241 | } | 245 | } |
... | @@ -245,22 +249,21 @@ public class CordVtnNodeManager { | ... | @@ -245,22 +249,21 @@ public class CordVtnNodeManager { |
245 | configService.removeListener(configListener); | 249 | configService.removeListener(configListener); |
246 | deviceService.removeListener(deviceListener); | 250 | deviceService.removeListener(deviceListener); |
247 | 251 | ||
248 | - eventExecutor.shutdown(); | 252 | + nodeStore.removeListener(nodeStoreListener); |
249 | nodeStore.clear(); | 253 | nodeStore.clear(); |
254 | + | ||
250 | leadershipService.withdraw(appId.name()); | 255 | leadershipService.withdraw(appId.name()); |
256 | + eventExecutor.shutdown(); | ||
251 | } | 257 | } |
252 | 258 | ||
253 | /** | 259 | /** |
254 | - * Adds a new node to the service. | 260 | + * Adds or updates a new node to the service. |
255 | * | 261 | * |
256 | * @param node cordvtn node | 262 | * @param node cordvtn node |
257 | */ | 263 | */ |
258 | - public void addNode(CordVtnNode node) { | 264 | + public void addOrUpdateNode(CordVtnNode node) { |
259 | checkNotNull(node); | 265 | checkNotNull(node); |
260 | - | ||
261 | - // allow update node attributes | ||
262 | nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, getNodeState(node))); | 266 | nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, getNodeState(node))); |
263 | - initNode(node); | ||
264 | } | 267 | } |
265 | 268 | ||
266 | /** | 269 | /** |
... | @@ -283,23 +286,12 @@ public class CordVtnNodeManager { | ... | @@ -283,23 +286,12 @@ public class CordVtnNodeManager { |
283 | * | 286 | * |
284 | * @param node cordvtn node | 287 | * @param node cordvtn node |
285 | */ | 288 | */ |
286 | - public void initNode(CordVtnNode node) { | 289 | + private void initNode(CordVtnNode node) { |
287 | checkNotNull(node); | 290 | checkNotNull(node); |
288 | 291 | ||
289 | - if (!nodeStore.containsKey(node.hostname())) { | 292 | + NodeState state = (NodeState) node.state(); |
290 | - log.warn("Node {} does not exist, add node first", node.hostname()); | 293 | + log.debug("Processing node: {} state: {}", node.hostname(), state); |
291 | - return; | ||
292 | - } | ||
293 | - | ||
294 | - NodeId leaderNodeId = leadershipService.getLeader(appId.name()); | ||
295 | - log.debug("Node init requested, local: {} leader: {}", localNodeId, leaderNodeId); | ||
296 | - if (!Objects.equals(localNodeId, leaderNodeId)) { | ||
297 | - // only the leader performs node init | ||
298 | - return; | ||
299 | - } | ||
300 | 294 | ||
301 | - NodeState state = getNodeState(node); | ||
302 | - log.debug("Init node: {} state: {}", node.hostname(), state.toString()); | ||
303 | state.process(this, node); | 295 | state.process(this, node); |
304 | } | 296 | } |
305 | 297 | ||
... | @@ -432,9 +424,8 @@ public class CordVtnNodeManager { | ... | @@ -432,9 +424,8 @@ public class CordVtnNodeManager { |
432 | private void setNodeState(CordVtnNode node, NodeState newState) { | 424 | private void setNodeState(CordVtnNode node, NodeState newState) { |
433 | checkNotNull(node); | 425 | checkNotNull(node); |
434 | 426 | ||
435 | - log.debug("Changed {} state: {}", node.hostname(), newState.toString()); | 427 | + log.debug("Changed {} state: {}", node.hostname(), newState); |
436 | nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, newState)); | 428 | nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, newState)); |
437 | - newState.process(this, node); | ||
438 | } | 429 | } |
439 | 430 | ||
440 | /** | 431 | /** |
... | @@ -812,7 +803,7 @@ public class CordVtnNodeManager { | ... | @@ -812,7 +803,7 @@ public class CordVtnNodeManager { |
812 | return; | 803 | return; |
813 | } | 804 | } |
814 | 805 | ||
815 | - log.debug("Port {} is added to {}", portName, node.hostname()); | 806 | + log.info("Port {} is added to {}", portName, node.hostname()); |
816 | 807 | ||
817 | if (portName.startsWith(VPORT_PREFIX)) { | 808 | if (portName.startsWith(VPORT_PREFIX)) { |
818 | if (isNodeStateComplete(node)) { | 809 | if (isNodeStateComplete(node)) { |
... | @@ -840,7 +831,7 @@ public class CordVtnNodeManager { | ... | @@ -840,7 +831,7 @@ public class CordVtnNodeManager { |
840 | return; | 831 | return; |
841 | } | 832 | } |
842 | 833 | ||
843 | - log.debug("Port {} is removed from {}", portName, node.hostname()); | 834 | + log.info("Port {} is removed from {}", portName, node.hostname()); |
844 | 835 | ||
845 | if (portName.startsWith(VPORT_PREFIX)) { | 836 | if (portName.startsWith(VPORT_PREFIX)) { |
846 | if (isNodeStateComplete(node)) { | 837 | if (isNodeStateComplete(node)) { |
... | @@ -861,7 +852,7 @@ public class CordVtnNodeManager { | ... | @@ -861,7 +852,7 @@ public class CordVtnNodeManager { |
861 | 852 | ||
862 | NodeId leaderNodeId = leadershipService.getLeader(appId.name()); | 853 | NodeId leaderNodeId = leadershipService.getLeader(appId.name()); |
863 | if (!Objects.equals(localNodeId, leaderNodeId)) { | 854 | if (!Objects.equals(localNodeId, leaderNodeId)) { |
864 | - // only the leader processes events | 855 | + // do not allow to proceed without leadership |
865 | return; | 856 | return; |
866 | } | 857 | } |
867 | 858 | ||
... | @@ -871,19 +862,19 @@ public class CordVtnNodeManager { | ... | @@ -871,19 +862,19 @@ public class CordVtnNodeManager { |
871 | 862 | ||
872 | switch (event.type()) { | 863 | switch (event.type()) { |
873 | case PORT_ADDED: | 864 | case PORT_ADDED: |
874 | - eventExecutor.submit(() -> bridgeHandler.portAdded(event.port())); | 865 | + eventExecutor.execute(() -> bridgeHandler.portAdded(event.port())); |
875 | break; | 866 | break; |
876 | case PORT_UPDATED: | 867 | case PORT_UPDATED: |
877 | if (!event.port().isEnabled()) { | 868 | if (!event.port().isEnabled()) { |
878 | - eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port())); | 869 | + eventExecutor.execute(() -> bridgeHandler.portRemoved(event.port())); |
879 | } | 870 | } |
880 | break; | 871 | break; |
881 | case DEVICE_ADDED: | 872 | case DEVICE_ADDED: |
882 | case DEVICE_AVAILABILITY_CHANGED: | 873 | case DEVICE_AVAILABILITY_CHANGED: |
883 | if (deviceService.isAvailable(device.id())) { | 874 | if (deviceService.isAvailable(device.id())) { |
884 | - eventExecutor.submit(() -> handler.connected(device)); | 875 | + eventExecutor.execute(() -> handler.connected(device)); |
885 | } else { | 876 | } else { |
886 | - eventExecutor.submit(() -> handler.disconnected(device)); | 877 | + eventExecutor.execute(() -> handler.disconnected(device)); |
887 | } | 878 | } |
888 | break; | 879 | break; |
889 | default: | 880 | default: |
... | @@ -902,14 +893,19 @@ public class CordVtnNodeManager { | ... | @@ -902,14 +893,19 @@ public class CordVtnNodeManager { |
902 | return; | 893 | return; |
903 | } | 894 | } |
904 | 895 | ||
905 | - config.cordVtnNodes().forEach(this::addNode); | 896 | + config.cordVtnNodes().forEach(this::addOrUpdateNode); |
906 | - // TODO remove nodes if needed | ||
907 | } | 897 | } |
908 | 898 | ||
909 | private class InternalConfigListener implements NetworkConfigListener { | 899 | private class InternalConfigListener implements NetworkConfigListener { |
910 | 900 | ||
911 | @Override | 901 | @Override |
912 | public void event(NetworkConfigEvent event) { | 902 | public void event(NetworkConfigEvent event) { |
903 | + NodeId leaderNodeId = leadershipService.getLeader(appId.name()); | ||
904 | + if (!Objects.equals(localNodeId, leaderNodeId)) { | ||
905 | + // do not allow to proceed without leadership | ||
906 | + return; | ||
907 | + } | ||
908 | + | ||
913 | if (!event.configClass().equals(CordVtnConfig.class)) { | 909 | if (!event.configClass().equals(CordVtnConfig.class)) { |
914 | return; | 910 | return; |
915 | } | 911 | } |
... | @@ -924,4 +920,46 @@ public class CordVtnNodeManager { | ... | @@ -924,4 +920,46 @@ public class CordVtnNodeManager { |
924 | } | 920 | } |
925 | } | 921 | } |
926 | } | 922 | } |
923 | + | ||
924 | + private class InternalMapListener implements MapEventListener<String, CordVtnNode> { | ||
925 | + | ||
926 | + @Override | ||
927 | + public void event(MapEvent<String, CordVtnNode> event) { | ||
928 | + NodeId leaderNodeId = leadershipService.getLeader(appId.name()); | ||
929 | + if (!Objects.equals(localNodeId, leaderNodeId)) { | ||
930 | + // do not allow to proceed without leadership | ||
931 | + return; | ||
932 | + } | ||
933 | + | ||
934 | + CordVtnNode oldNode; | ||
935 | + CordVtnNode newNode; | ||
936 | + | ||
937 | + switch (event.type()) { | ||
938 | + case UPDATE: | ||
939 | + oldNode = event.oldValue().value(); | ||
940 | + newNode = event.newValue().value(); | ||
941 | + | ||
942 | + if (!newNode.equals(oldNode)) { | ||
943 | + log.info("{} has been updated", newNode.hostname()); | ||
944 | + log.debug("New node: {}", newNode); | ||
945 | + } | ||
946 | + // perform init procedure based on current state on any updates, | ||
947 | + // insert, or even if the node is the same for robustness since | ||
948 | + // it's no harm to run the init procedure multiple times | ||
949 | + eventExecutor.execute(() -> initNode(newNode)); | ||
950 | + break; | ||
951 | + case INSERT: | ||
952 | + newNode = event.newValue().value(); | ||
953 | + log.info("Added {}", newNode.hostname()); | ||
954 | + eventExecutor.execute(() -> initNode(newNode)); | ||
955 | + break; | ||
956 | + case REMOVE: | ||
957 | + oldNode = event.oldValue().value(); | ||
958 | + log.info("{} is removed", oldNode.hostname()); | ||
959 | + break; | ||
960 | + default: | ||
961 | + break; | ||
962 | + } | ||
963 | + } | ||
964 | + } | ||
927 | } | 965 | } | ... | ... |
... | @@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { | ... | @@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { |
51 | continue; | 51 | continue; |
52 | } | 52 | } |
53 | 53 | ||
54 | - nodeManager.initNode(node); | 54 | + nodeManager.addOrUpdateNode(node); |
55 | } | 55 | } |
56 | } | 56 | } |
57 | } | 57 | } | ... | ... |
-
Please register or login to post a comment