Hyunsun Moon
Committed by Gerrit Code Review

CORD-151 Refactor cordvtn service to reduce complexity

Change-Id: I489e1d3df7f08d04d6b6a2aa23b9d4e6d7a054e4
...@@ -21,24 +21,11 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -21,24 +21,11 @@ import org.apache.felix.scr.annotations.Deactivate;
21 import org.apache.felix.scr.annotations.Reference; 21 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 23 import org.apache.felix.scr.annotations.Service;
24 -import org.onlab.packet.IpAddress;
25 -import org.onlab.packet.TpPort;
26 import org.onlab.util.KryoNamespace; 24 import org.onlab.util.KryoNamespace;
27 -import org.onosproject.cluster.ClusterService;
28 -import org.onosproject.cluster.LeadershipEvent;
29 -import org.onosproject.cluster.LeadershipEventListener;
30 -import org.onosproject.cluster.LeadershipService;
31 -import org.onosproject.cluster.NodeId;
32 -import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.CoreService; 25 import org.onosproject.core.CoreService;
34 -import org.onosproject.mastership.MastershipService;
35 import org.onosproject.net.Device; 26 import org.onosproject.net.Device;
36 import org.onosproject.net.DeviceId; 27 import org.onosproject.net.DeviceId;
37 import org.onosproject.net.Host; 28 import org.onosproject.net.Host;
38 -import org.onosproject.net.config.ConfigFactory;
39 -import org.onosproject.net.config.NetworkConfigRegistry;
40 -import org.onosproject.net.config.NetworkConfigService;
41 -import org.onosproject.net.config.basics.SubjectFactories;
42 import org.onosproject.net.device.DeviceEvent; 29 import org.onosproject.net.device.DeviceEvent;
43 import org.onosproject.net.device.DeviceListener; 30 import org.onosproject.net.device.DeviceListener;
44 import org.onosproject.net.device.DeviceService; 31 import org.onosproject.net.device.DeviceService;
...@@ -57,11 +44,15 @@ import java.util.concurrent.Executors; ...@@ -57,11 +44,15 @@ import java.util.concurrent.Executors;
57 import java.util.stream.Collectors; 44 import java.util.stream.Collectors;
58 45
59 import static org.onlab.util.Tools.groupedThreads; 46 import static org.onlab.util.Tools.groupedThreads;
47 +import static org.onosproject.cordvtn.OvsdbNode.State;
60 import static org.onosproject.cordvtn.OvsdbNode.State.INIT; 48 import static org.onosproject.cordvtn.OvsdbNode.State.INIT;
49 +import static org.onosproject.cordvtn.OvsdbNode.State.DISCONNECT;
50 +import static org.onosproject.net.Device.Type.SWITCH;
61 import static org.slf4j.LoggerFactory.getLogger; 51 import static org.slf4j.LoggerFactory.getLogger;
62 52
63 /** 53 /**
64 - * CORD VTN Application that provisions overlay virtual tenant networks. 54 + * Provides initial setup or cleanup for provisioning virtual tenant networks
55 + * on ovsdb, integration bridge and vm when they are added or deleted.
65 */ 56 */
66 @Component(immediate = true) 57 @Component(immediate = true)
67 @Service 58 @Service
...@@ -69,6 +60,11 @@ public class CordVtn implements CordVtnService { ...@@ -69,6 +60,11 @@ public class CordVtn implements CordVtnService {
69 60
70 protected final Logger log = getLogger(getClass()); 61 protected final Logger log = getLogger(getClass());
71 62
63 + private static final int NUM_THREADS = 1;
64 + private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
65 + .register(KryoNamespaces.API)
66 + .register(OvsdbNode.class);
67 +
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected CoreService coreService; 69 protected CoreService coreService;
74 70
...@@ -79,112 +75,81 @@ public class CordVtn implements CordVtnService { ...@@ -79,112 +75,81 @@ public class CordVtn implements CordVtnService {
79 protected LogicalClockService clockService; 75 protected LogicalClockService clockService;
80 76
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 - protected ClusterService clusterService;
83 -
84 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 - protected LeadershipService leadershipService;
86 -
87 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 - protected NetworkConfigService configService;
89 -
90 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 - protected NetworkConfigRegistry configRegistry;
92 -
93 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected DeviceService deviceService; 78 protected DeviceService deviceService;
95 79
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected HostService hostService; 81 protected HostService hostService;
98 82
99 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 83 + private final ExecutorService eventExecutor = Executors
100 - protected MastershipService mastershipService; 84 + .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
101 -
102 - private static final int DEFAULT_NUM_THREADS = 1;
103 - private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
104 - .register(KryoNamespaces.API)
105 - .register(OvsdbNode.class);
106 85
107 - private final ExecutorService eventExecutor = Executors.newFixedThreadPool(
108 - DEFAULT_NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
109 -
110 - private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
111 private final DeviceListener deviceListener = new InternalDeviceListener(); 86 private final DeviceListener deviceListener = new InternalDeviceListener();
112 private final HostListener hostListener = new InternalHostListener(); 87 private final HostListener hostListener = new InternalHostListener();
113 - private final NodeHandler nodeHandler = new NodeHandler(); 88 +
89 + private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
114 private final BridgeHandler bridgeHandler = new BridgeHandler(); 90 private final BridgeHandler bridgeHandler = new BridgeHandler();
115 - private final VirtualMachineHandler vmHandler = new VirtualMachineHandler(); 91 + private final VmHandler vmHandler = new VmHandler();
116 - 92 +
117 - private final ConfigFactory configFactory =
118 - new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
119 - @Override
120 - public CordVtnConfig createConfig() {
121 - return new CordVtnConfig();
122 - }
123 - };
124 -
125 - private ApplicationId appId;
126 - private NodeId local;
127 private EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore; 93 private EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
128 - private NodeConnectionManager nodeConnectionManager;
129 94
130 @Activate 95 @Activate
131 protected void activate() { 96 protected void activate() {
132 - appId = coreService.registerApplication("org.onosproject.cordvtn"); 97 + coreService.registerApplication("org.onosproject.cordvtn");
133 -
134 - local = clusterService.getLocalNode().id();
135 nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder() 98 nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder()
136 .withName("cordvtn-nodestore") 99 .withName("cordvtn-nodestore")
137 .withSerializer(NODE_SERIALIZER) 100 .withSerializer(NODE_SERIALIZER)
138 .withTimestampProvider((k, v) -> clockService.getTimestamp()) 101 .withTimestampProvider((k, v) -> clockService.getTimestamp())
139 .build(); 102 .build();
140 - configRegistry.registerConfigFactory(configFactory);
141 103
142 deviceService.addListener(deviceListener); 104 deviceService.addListener(deviceListener);
143 hostService.addListener(hostListener); 105 hostService.addListener(hostListener);
144 - leadershipService.addListener(leadershipListener); 106 +
145 - leadershipService.runForLeadership(appId.name());
146 - nodeConnectionManager = new NodeConnectionManager(appId, local, nodeStore,
147 - mastershipService, leadershipService);
148 - nodeConnectionManager.start();
149 log.info("Started"); 107 log.info("Started");
150 } 108 }
151 109
152 @Deactivate 110 @Deactivate
153 protected void deactivate() { 111 protected void deactivate() {
154 - nodeConnectionManager.stop();
155 - leadershipService.removeListener(leadershipListener);
156 - leadershipService.withdraw(appId.name());
157 deviceService.removeListener(deviceListener); 112 deviceService.removeListener(deviceListener);
158 hostService.removeListener(hostListener); 113 hostService.removeListener(hostListener);
114 +
159 eventExecutor.shutdown(); 115 eventExecutor.shutdown();
160 nodeStore.destroy(); 116 nodeStore.destroy();
161 - configRegistry.unregisterConfigFactory(configFactory); 117 +
162 log.info("Stopped"); 118 log.info("Stopped");
163 } 119 }
164 120
165 @Override 121 @Override
166 - public void addNode(String hostname, IpAddress ip, TpPort port) { 122 + public void addNode(OvsdbNode ovsdbNode) {
167 - DefaultOvsdbNode node = new DefaultOvsdbNode(hostname, ip, port, DeviceId.NONE, INIT); 123 + if (nodeStore.containsKey(ovsdbNode.deviceId())) {
168 - 124 + log.warn("Node {} already exists", ovsdbNode.host());
169 - if (nodeStore.containsKey(node.deviceId())) {
170 - log.warn("Node {} with ovsdb-server {}:{} already exists", hostname, ip, port);
171 return; 125 return;
172 } 126 }
173 - nodeStore.put(node.deviceId(), node); 127 + nodeStore.put(ovsdbNode.deviceId(), ovsdbNode);
174 - log.info("New node {} with ovsdb-server {}:{} has been added", hostname, ip, port); 128 + if (ovsdbNode.state() != INIT) {
129 + updateNode(ovsdbNode, INIT);
130 + }
175 } 131 }
176 132
177 @Override 133 @Override
178 - public void deleteNode(IpAddress ip, TpPort port) { 134 + public void deleteNode(OvsdbNode ovsdbNode) {
179 - DeviceId deviceId = DeviceId.deviceId("ovsdb:" + ip + ":" + port); 135 + if (!nodeStore.containsKey(ovsdbNode.deviceId())) {
180 - OvsdbNode node = nodeStore.get(deviceId); 136 + log.warn("Node {} does not exist", ovsdbNode.host());
137 + return;
138 + }
139 + updateNode(ovsdbNode, DISCONNECT);
140 + }
181 141
182 - if (node == null) { 142 + @Override
183 - log.warn("Node with ovsdb-server on {}:{} does not exist", ip, port); 143 + public void updateNode(OvsdbNode ovsdbNode, State state) {
144 + if (!nodeStore.containsKey(ovsdbNode.deviceId())) {
145 + log.warn("Node {} does not exist", ovsdbNode.host());
184 return; 146 return;
185 } 147 }
186 - nodeConnectionManager.disconnectNode(node); 148 + DefaultOvsdbNode updatedNode = new DefaultOvsdbNode(ovsdbNode.host(),
187 - nodeStore.remove(node.deviceId()); 149 + ovsdbNode.ip(),
150 + ovsdbNode.port(),
151 + state);
152 + nodeStore.put(ovsdbNode.deviceId(), updatedNode);
188 } 153 }
189 154
190 @Override 155 @Override
...@@ -193,58 +158,33 @@ public class CordVtn implements CordVtnService { ...@@ -193,58 +158,33 @@ public class CordVtn implements CordVtnService {
193 } 158 }
194 159
195 @Override 160 @Override
161 + public OvsdbNode getNode(DeviceId deviceId) {
162 + return nodeStore.get(deviceId);
163 + }
164 +
165 + @Override
196 public List<OvsdbNode> getNodes() { 166 public List<OvsdbNode> getNodes() {
197 return nodeStore.values() 167 return nodeStore.values()
198 .stream() 168 .stream()
199 .collect(Collectors.toList()); 169 .collect(Collectors.toList());
200 } 170 }
201 171
202 - private void initialSetup() {
203 - // Read ovsdb nodes from network config
204 - CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
205 - if (config == null) {
206 - log.warn("No configuration found");
207 - return;
208 - }
209 - config.ovsdbNodes().forEach(
210 - node -> addNode(node.hostname(), node.ip(), node.port()));
211 - }
212 -
213 - private synchronized void processLeadershipChange(NodeId leader) {
214 - // Only the leader performs the initial setup
215 - if (leader == null || !leader.equals(local)) {
216 - return;
217 - }
218 - initialSetup();
219 - }
220 -
221 - private class InternalLeadershipListener implements LeadershipEventListener {
222 -
223 - @Override
224 - public void event(LeadershipEvent event) {
225 - if (event.subject().topic().equals(appId.name())) {
226 - processLeadershipChange(event.subject().leader());
227 - }
228 - }
229 - }
230 -
231 private class InternalDeviceListener implements DeviceListener { 172 private class InternalDeviceListener implements DeviceListener {
232 173
233 @Override 174 @Override
234 public void event(DeviceEvent event) { 175 public void event(DeviceEvent event) {
235 Device device = event.subject(); 176 Device device = event.subject();
236 - ConnectionHandler handler = 177 + ConnectionHandler handler = (device.type() == SWITCH ? bridgeHandler : ovsdbHandler);
237 - (device.type() == Device.Type.CONTROLLER ? nodeHandler : bridgeHandler);
238 178
239 switch (event.type()) { 179 switch (event.type()) {
240 - case DEVICE_ADDED: 180 + case DEVICE_ADDED:
241 - eventExecutor.submit(() -> handler.connected(device)); 181 + eventExecutor.submit(() -> handler.connected(device));
242 - break; 182 + break;
243 - case DEVICE_AVAILABILITY_CHANGED: 183 + case DEVICE_AVAILABILITY_CHANGED:
244 - eventExecutor.submit(() -> handler.disconnected(device)); 184 + eventExecutor.submit(() -> handler.disconnected(device));
245 - break; 185 + break;
246 - default: 186 + default:
247 - break; 187 + break;
248 } 188 }
249 } 189 }
250 } 190 }
...@@ -268,7 +208,7 @@ public class CordVtn implements CordVtnService { ...@@ -268,7 +208,7 @@ public class CordVtn implements CordVtnService {
268 } 208 }
269 } 209 }
270 210
271 - private class NodeHandler implements ConnectionHandler<Device> { 211 + private class OvsdbHandler implements ConnectionHandler<Device> {
272 212
273 @Override 213 @Override
274 public void connected(Device device) { 214 public void connected(Device device) {
...@@ -296,7 +236,7 @@ public class CordVtn implements CordVtnService { ...@@ -296,7 +236,7 @@ public class CordVtn implements CordVtnService {
296 } 236 }
297 } 237 }
298 238
299 - private class VirtualMachineHandler implements ConnectionHandler<Host> { 239 + private class VmHandler implements ConnectionHandler<Host> {
300 240
301 @Override 241 @Override
302 public void connected(Host host) { 242 public void connected(Host host) {
......
...@@ -27,12 +27,12 @@ import java.util.Set; ...@@ -27,12 +27,12 @@ import java.util.Set;
27 import static com.google.common.base.Preconditions.checkNotNull; 27 import static com.google.common.base.Preconditions.checkNotNull;
28 28
29 /** 29 /**
30 - * Configuration object for CORD VTN service. 30 + * Configuration object for CordVtn service.
31 */ 31 */
32 public class CordVtnConfig extends Config<ApplicationId> { 32 public class CordVtnConfig extends Config<ApplicationId> {
33 33
34 public static final String OVSDB_NODES = "ovsdbNodes"; 34 public static final String OVSDB_NODES = "ovsdbNodes";
35 - public static final String HOSTNAME = "hostname"; 35 + public static final String HOST = "host";
36 public static final String IP = "ip"; 36 public static final String IP = "ip";
37 public static final String PORT = "port"; 37 public static final String PORT = "port";
38 38
...@@ -49,7 +49,7 @@ public class CordVtnConfig extends Config<ApplicationId> { ...@@ -49,7 +49,7 @@ public class CordVtnConfig extends Config<ApplicationId> {
49 return null; 49 return null;
50 } 50 }
51 nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig( 51 nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig(
52 - jsonNode.path(HOSTNAME).asText(), 52 + jsonNode.path(HOST).asText(),
53 IpAddress.valueOf(jsonNode.path(IP).asText()), 53 IpAddress.valueOf(jsonNode.path(IP).asText()),
54 TpPort.tpPort(jsonNode.path(PORT).asInt())))); 54 TpPort.tpPort(jsonNode.path(PORT).asInt()))));
55 55
...@@ -57,27 +57,27 @@ public class CordVtnConfig extends Config<ApplicationId> { ...@@ -57,27 +57,27 @@ public class CordVtnConfig extends Config<ApplicationId> {
57 } 57 }
58 58
59 /** 59 /**
60 - * Configuration for an OVSDB node. 60 + * Configuration for an ovsdb node.
61 */ 61 */
62 public static class OvsdbNodeConfig { 62 public static class OvsdbNodeConfig {
63 63
64 - private final String hostname; 64 + private final String host;
65 private final IpAddress ip; 65 private final IpAddress ip;
66 private final TpPort port; 66 private final TpPort port;
67 67
68 - public OvsdbNodeConfig(String hostname, IpAddress ip, TpPort port) { 68 + public OvsdbNodeConfig(String host, IpAddress ip, TpPort port) {
69 - this.hostname = checkNotNull(hostname); 69 + this.host = checkNotNull(host);
70 this.ip = checkNotNull(ip); 70 this.ip = checkNotNull(ip);
71 this.port = checkNotNull(port); 71 this.port = checkNotNull(port);
72 } 72 }
73 73
74 /** 74 /**
75 - * Returns hostname of the node. 75 + * Returns host information of the node.
76 * 76 *
77 - * @return hostname 77 + * @return host
78 */ 78 */
79 - public String hostname() { 79 + public String host() {
80 - return this.hostname; 80 + return this.host;
81 } 81 }
82 82
83 /** 83 /**
......
1 +/*
2 + * Copyright 2014-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 +package org.onosproject.cordvtn;
17 +
18 +import org.apache.felix.scr.annotations.Activate;
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Reference;
22 +import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.onosproject.cluster.ClusterService;
24 +import org.onosproject.cluster.LeadershipEvent;
25 +import org.onosproject.cluster.LeadershipEventListener;
26 +import org.onosproject.cluster.LeadershipService;
27 +import org.onosproject.cluster.NodeId;
28 +import org.onosproject.core.ApplicationId;
29 +import org.onosproject.core.CoreService;
30 +import org.onosproject.net.config.ConfigFactory;
31 +import org.onosproject.net.config.NetworkConfigEvent;
32 +import org.onosproject.net.config.NetworkConfigListener;
33 +import org.onosproject.net.config.NetworkConfigRegistry;
34 +import org.onosproject.net.config.NetworkConfigService;
35 +import org.onosproject.net.config.basics.SubjectFactories;
36 +import org.slf4j.Logger;
37 +
38 +import static org.onosproject.cordvtn.OvsdbNode.State.INIT;
39 +import static org.slf4j.LoggerFactory.getLogger;
40 +
41 +/**
42 + * Reads node information from the network config file and handles the config
43 + * update events.
44 + * Only a leader controller performs the node addition or deletion.
45 + */
46 +@Component(immediate = true)
47 +public class CordVtnConfigManager {
48 +
49 + protected final Logger log = getLogger(getClass());
50 +
51 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 + protected CoreService coreService;
53 +
54 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 + protected NetworkConfigRegistry configRegistry;
56 +
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + protected NetworkConfigService configService;
59 +
60 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 + protected LeadershipService leadershipService;
62 +
63 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 + protected ClusterService clusterService;
65 +
66 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 + protected CordVtnService cordVtnService;
68 +
69 + private final ConfigFactory configFactory =
70 + new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
71 + @Override
72 + public CordVtnConfig createConfig() {
73 + return new CordVtnConfig();
74 + }
75 + };
76 +
77 + private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
78 + private final NetworkConfigListener configListener = new InternalConfigListener();
79 +
80 + private NodeId local;
81 + private ApplicationId appId;
82 +
83 + @Activate
84 + protected void active() {
85 + local = clusterService.getLocalNode().id();
86 + appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID);
87 +
88 + configService.addListener(configListener);
89 + configRegistry.registerConfigFactory(configFactory);
90 +
91 + leadershipService.addListener(leadershipListener);
92 + leadershipService.runForLeadership(CordVtnService.CORDVTN_APP_ID);
93 + }
94 +
95 + @Deactivate
96 + protected void deactivate() {
97 + leadershipService.removeListener(leadershipListener);
98 + leadershipService.withdraw(appId.name());
99 +
100 + configRegistry.unregisterConfigFactory(configFactory);
101 + configService.removeListener(configListener);
102 + }
103 +
104 + private void readConfiguration() {
105 + CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
106 +
107 + if (config == null) {
108 + log.warn("No configuration found");
109 + return;
110 + }
111 +
112 + config.ovsdbNodes().forEach(node -> {
113 + DefaultOvsdbNode ovsdbNode =
114 + new DefaultOvsdbNode(node.host(), node.ip(), node.port(), INIT);
115 + cordVtnService.addNode(ovsdbNode);
116 + log.info("Add new node {}", node.host());
117 + });
118 + }
119 +
120 + private synchronized void processLeadershipChange(NodeId leader) {
121 + if (leader == null || !leader.equals(local)) {
122 + return;
123 + }
124 + readConfiguration();
125 + }
126 +
127 + private class InternalLeadershipListener implements LeadershipEventListener {
128 +
129 + @Override
130 + public void event(LeadershipEvent event) {
131 + if (event.subject().topic().equals(appId.name())) {
132 + processLeadershipChange(event.subject().leader());
133 + }
134 + }
135 + }
136 +
137 + private class InternalConfigListener implements NetworkConfigListener {
138 +
139 + @Override
140 + public void event(NetworkConfigEvent event) {
141 + // TODO handle update event
142 + }
143 + }
144 +}
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
15 */ 15 */
16 package org.onosproject.cordvtn; 16 package org.onosproject.cordvtn;
17 17
18 -import org.onlab.packet.IpAddress; 18 +import org.onosproject.cordvtn.OvsdbNode.State;
19 -import org.onlab.packet.TpPort; 19 +import org.onosproject.net.DeviceId;
20 20
21 import java.util.List; 21 import java.util.List;
22 22
...@@ -24,22 +24,30 @@ import java.util.List; ...@@ -24,22 +24,30 @@ import java.util.List;
24 * Service for provisioning overlay virtual networks on compute nodes. 24 * Service for provisioning overlay virtual networks on compute nodes.
25 */ 25 */
26 public interface CordVtnService { 26 public interface CordVtnService {
27 +
28 + String CORDVTN_APP_ID = "org.onosproject.cordvtn";
27 /** 29 /**
28 * Adds a new node to the service. 30 * Adds a new node to the service.
29 * 31 *
30 - * @param hostname hostname of the node 32 + * @param ovsdbNode ovsdb node
31 - * @param ip ip address to access the ovsdb server running on the node 33 + */
32 - * @param port port number to access the ovsdb server running on the node 34 + void addNode(OvsdbNode ovsdbNode);
35 +
36 + /**
37 + * Deletes a node from the service.
38 + *
39 + * @param ovsdbNode ovsdb node
33 */ 40 */
34 - void addNode(String hostname, IpAddress ip, TpPort port); 41 + void deleteNode(OvsdbNode ovsdbNode);
35 42
36 /** 43 /**
37 - * Deletes the node from the service. 44 + * Updates ovsdb node.
45 + * It only used for updating node's connection state.
38 * 46 *
39 - * @param ip ip address to access the ovsdb server running on the node 47 + * @param ovsdbNode ovsdb node
40 - * @param port port number to access the ovsdb server running on the node 48 + * @param state ovsdb connection state
41 */ 49 */
42 - void deleteNode(IpAddress ip, TpPort port); 50 + void updateNode(OvsdbNode ovsdbNode, State state);
43 51
44 /** 52 /**
45 * Returns the number of the nodes known to the service. 53 * Returns the number of the nodes known to the service.
...@@ -49,6 +57,14 @@ public interface CordVtnService { ...@@ -49,6 +57,14 @@ public interface CordVtnService {
49 int getNodeCount(); 57 int getNodeCount();
50 58
51 /** 59 /**
60 + * Returns OvsdbNode with given device id.
61 + *
62 + * @param deviceId device id
63 + * @return ovsdb node
64 + */
65 + OvsdbNode getNode(DeviceId deviceId);
66 +
67 + /**
52 * Returns all nodes known to the service. 68 * Returns all nodes known to the service.
53 * 69 *
54 * @return list of nodes 70 * @return list of nodes
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.cordvtn; 16 package org.onosproject.cordvtn;
17 17
18 +import com.google.common.base.MoreObjects;
18 import org.onlab.packet.IpAddress; 19 import org.onlab.packet.IpAddress;
19 import org.onlab.packet.TpPort; 20 import org.onlab.packet.TpPort;
20 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
...@@ -26,21 +27,15 @@ import java.util.Objects; ...@@ -26,21 +27,15 @@ import java.util.Objects;
26 */ 27 */
27 public class DefaultOvsdbNode implements OvsdbNode { 28 public class DefaultOvsdbNode implements OvsdbNode {
28 29
29 - private final String hostname; 30 + private final String host;
30 private final IpAddress ip; 31 private final IpAddress ip;
31 private final TpPort port; 32 private final TpPort port;
32 - private final DeviceId deviceId;
33 - private final DeviceId bridgeId;
34 private final State state; 33 private final State state;
35 34
36 - public DefaultOvsdbNode(String hostname, IpAddress ip, TpPort port, 35 + public DefaultOvsdbNode(String host, IpAddress ip, TpPort port, State state) {
37 - DeviceId bridgeId, State state) { 36 + this.host = host;
38 - this.hostname = hostname;
39 this.ip = ip; 37 this.ip = ip;
40 this.port = port; 38 this.port = port;
41 - this.deviceId = DeviceId.deviceId(
42 - "ovsdb:" + ip.toString() + ":" + port.toString());
43 - this.bridgeId = bridgeId;
44 this.state = state; 39 this.state = state;
45 } 40 }
46 41
...@@ -55,8 +50,8 @@ public class DefaultOvsdbNode implements OvsdbNode { ...@@ -55,8 +50,8 @@ public class DefaultOvsdbNode implements OvsdbNode {
55 } 50 }
56 51
57 @Override 52 @Override
58 - public String hostname() { 53 + public String host() {
59 - return this.hostname; 54 + return this.host;
60 } 55 }
61 56
62 @Override 57 @Override
...@@ -66,12 +61,12 @@ public class DefaultOvsdbNode implements OvsdbNode { ...@@ -66,12 +61,12 @@ public class DefaultOvsdbNode implements OvsdbNode {
66 61
67 @Override 62 @Override
68 public DeviceId deviceId() { 63 public DeviceId deviceId() {
69 - return this.deviceId; 64 + return DeviceId.deviceId("ovsdb:" + this.ip.toString() + ":" + this.port.toString());
70 } 65 }
71 66
72 @Override 67 @Override
73 - public DeviceId bridgeId() { 68 + public DeviceId intBrId() {
74 - return this.bridgeId; 69 + return DeviceId.deviceId("of:" + this.host);
75 } 70 }
76 71
77 @Override 72 @Override
...@@ -82,8 +77,9 @@ public class DefaultOvsdbNode implements OvsdbNode { ...@@ -82,8 +77,9 @@ public class DefaultOvsdbNode implements OvsdbNode {
82 77
83 if (o instanceof DefaultOvsdbNode) { 78 if (o instanceof DefaultOvsdbNode) {
84 DefaultOvsdbNode that = (DefaultOvsdbNode) o; 79 DefaultOvsdbNode that = (DefaultOvsdbNode) o;
85 - // We compare the ip and port only. 80 + if (this.host.equals(that.host) &&
86 - if (this.ip.equals(that.ip) && this.port.equals(that.port)) { 81 + this.ip.equals(that.ip) &&
82 + this.port.equals(that.port)) {
87 return true; 83 return true;
88 } 84 }
89 } 85 }
...@@ -92,6 +88,16 @@ public class DefaultOvsdbNode implements OvsdbNode { ...@@ -92,6 +88,16 @@ public class DefaultOvsdbNode implements OvsdbNode {
92 88
93 @Override 89 @Override
94 public int hashCode() { 90 public int hashCode() {
95 - return Objects.hash(ip, port); 91 + return Objects.hash(host, ip, port);
92 + }
93 +
94 + @Override
95 + public String toString() {
96 + return MoreObjects.toStringHelper(getClass())
97 + .add("host", host)
98 + .add("ip", ip)
99 + .add("port", port)
100 + .add("state", state)
101 + .toString();
96 } 102 }
97 } 103 }
......
...@@ -15,12 +15,19 @@ ...@@ -15,12 +15,19 @@
15 */ 15 */
16 package org.onosproject.cordvtn; 16 package org.onosproject.cordvtn;
17 17
18 +import org.apache.felix.scr.annotations.Activate;
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Reference;
22 +import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.onosproject.cluster.ClusterService;
18 import org.onosproject.cluster.LeadershipService; 24 import org.onosproject.cluster.LeadershipService;
19 import org.onosproject.cluster.NodeId; 25 import org.onosproject.cluster.NodeId;
20 -import org.onosproject.core.ApplicationId;
21 import org.onosproject.mastership.MastershipService; 26 import org.onosproject.mastership.MastershipService;
22 -import org.onosproject.net.DeviceId; 27 +import org.onosproject.net.Device;
23 -import org.onosproject.store.service.EventuallyConsistentMap; 28 +import org.onosproject.net.device.DeviceEvent;
29 +import org.onosproject.net.device.DeviceListener;
30 +import org.onosproject.net.device.DeviceService;
24 import org.slf4j.Logger; 31 import org.slf4j.Logger;
25 32
26 import java.util.concurrent.Executors; 33 import java.util.concurrent.Executors;
...@@ -28,120 +35,131 @@ import java.util.concurrent.ScheduledExecutorService; ...@@ -28,120 +35,131 @@ import java.util.concurrent.ScheduledExecutorService;
28 import java.util.concurrent.TimeUnit; 35 import java.util.concurrent.TimeUnit;
29 36
30 import static org.onlab.util.Tools.groupedThreads; 37 import static org.onlab.util.Tools.groupedThreads;
38 +import static org.onosproject.cordvtn.OvsdbNode.State.CONNECTED;
39 +import static org.onosproject.cordvtn.OvsdbNode.State.DISCONNECTED;
40 +import static org.onosproject.cordvtn.OvsdbNode.State.READY;
31 import static org.slf4j.LoggerFactory.getLogger; 41 import static org.slf4j.LoggerFactory.getLogger;
32 42
33 /** 43 /**
34 - * Node connection manager. 44 + * Provides the connection state management of all nodes registered to the service
45 + * so that the nodes keep connected unless it is requested to be deleted.
35 */ 46 */
47 +@Component(immediate = true)
36 public class NodeConnectionManager { 48 public class NodeConnectionManager {
37 protected final Logger log = getLogger(getClass()); 49 protected final Logger log = getLogger(getClass());
38 50
39 - private final ApplicationId appId; 51 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
40 - private final NodeId localId; 52 + MastershipService mastershipService;
41 - private final EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore; 53 +
42 - private final MastershipService mastershipService; 54 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 - private final LeadershipService leadershipService; 55 + LeadershipService leadershipService;
56 +
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + ClusterService clusterService;
59 +
60 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 + DeviceService deviceService;
62 +
63 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 + CordVtnService cordVtnService;
44 65
45 private static final int DELAY_SEC = 5; 66 private static final int DELAY_SEC = 5;
46 - private ScheduledExecutorService connectionExecutor;
47 -
48 - /**
49 - * Creates a new NodeConnectionManager.
50 - *
51 - * @param appId app id
52 - * @param localId local id
53 - * @param nodeStore node store
54 - * @param mastershipService mastership service
55 - * @param leadershipService leadership service
56 - */
57 - public NodeConnectionManager(ApplicationId appId, NodeId localId,
58 - EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore,
59 - MastershipService mastershipService,
60 - LeadershipService leadershipService) {
61 - this.appId = appId;
62 - this.localId = localId;
63 - this.nodeStore = nodeStore;
64 - this.mastershipService = mastershipService;
65 - this.leadershipService = leadershipService;
66 - }
67 67
68 - /** 68 + private final DeviceListener deviceListener = new InternalDeviceListener();
69 - * Starts the node connection manager. 69 + private final ScheduledExecutorService connectionExecutor = Executors
70 - */ 70 + .newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "connection-manager"));
71 - public void start() { 71 +
72 - connectionExecutor = Executors.newSingleThreadScheduledExecutor( 72 + private NodeId localId;
73 - groupedThreads("onos/cordvtn", "connection-executor")); 73 +
74 - connectionExecutor.scheduleWithFixedDelay(() -> nodeStore.values() 74 + @Activate
75 + protected void activate() {
76 + localId = clusterService.getLocalNode().id();
77 + deviceService.addListener(deviceListener);
78 +
79 + connectionExecutor.scheduleWithFixedDelay(() -> cordVtnService.getNodes()
75 .stream() 80 .stream()
76 .filter(node -> localId.equals(getMaster(node))) 81 .filter(node -> localId.equals(getMaster(node)))
77 - .forEach(this::connectNode), 0, DELAY_SEC, TimeUnit.SECONDS); 82 + .forEach(node -> {
83 + connect(node);
84 + disconnect(node);
85 + }), 0, DELAY_SEC, TimeUnit.SECONDS);
78 } 86 }
79 87
80 - /** 88 + @Deactivate
81 - * Stops the node connection manager.
82 - */
83 public void stop() { 89 public void stop() {
84 connectionExecutor.shutdown(); 90 connectionExecutor.shutdown();
91 + deviceService.removeListener(deviceListener);
85 } 92 }
86 93
87 - /** 94 + public void connect(OvsdbNode ovsdbNode) {
88 - * Adds a new node to the system.
89 - *
90 - * @param ovsdbNode ovsdb node
91 - */
92 - public void connectNode(OvsdbNode ovsdbNode) {
93 switch (ovsdbNode.state()) { 95 switch (ovsdbNode.state()) {
94 case INIT: 96 case INIT:
95 case DISCONNECTED: 97 case DISCONNECTED:
96 - // TODO: set the node to passive mode 98 + setPassiveMode(ovsdbNode);
97 case READY: 99 case READY:
98 - // TODO: initiate connection 100 + setupConnection(ovsdbNode);
99 - break;
100 - case CONNECTED:
101 break; 101 break;
102 default: 102 default:
103 + break;
103 } 104 }
104 } 105 }
105 106
106 - /** 107 + public void disconnect(OvsdbNode ovsdbNode) {
107 - * Deletes the ovsdb node.
108 - *
109 - * @param ovsdbNode ovsdb node
110 - */
111 - public void disconnectNode(OvsdbNode ovsdbNode) {
112 switch (ovsdbNode.state()) { 108 switch (ovsdbNode.state()) {
113 - case CONNECTED: 109 + case DISCONNECT:
114 // TODO: disconnect 110 // TODO: disconnect
115 break; 111 break;
116 - case INIT:
117 - case READY:
118 - case DISCONNECTED:
119 - break;
120 default: 112 default:
113 + break;
114 + }
115 + }
116 +
117 + private class InternalDeviceListener implements DeviceListener {
118 +
119 + @Override
120 + public void event(DeviceEvent event) {
121 + Device device = event.subject();
122 + if (device.type() != Device.Type.CONTROLLER) {
123 + return;
124 + }
125 +
126 + DefaultOvsdbNode node;
127 + switch (event.type()) {
128 + case DEVICE_ADDED:
129 + node = (DefaultOvsdbNode) cordVtnService.getNode(device.id());
130 + if (node != null) {
131 + cordVtnService.updateNode(node, CONNECTED);
132 + }
133 + break;
134 + case DEVICE_AVAILABILITY_CHANGED:
135 + node = (DefaultOvsdbNode) cordVtnService.getNode(device.id());
136 + if (node != null) {
137 + cordVtnService.updateNode(node, DISCONNECTED);
138 + }
139 + break;
140 + default:
141 + break;
142 + }
121 } 143 }
122 } 144 }
123 145
124 private NodeId getMaster(OvsdbNode ovsdbNode) { 146 private NodeId getMaster(OvsdbNode ovsdbNode) {
125 - // Return the master of the bridge(switch) if it exist or 147 + NodeId master = mastershipService.getMasterFor(ovsdbNode.intBrId());
126 - // return the current leader 148 +
127 - if (ovsdbNode.bridgeId() == DeviceId.NONE) { 149 + // master is null if there's no such device
128 - return leadershipService.getLeader(this.appId.name()); 150 + if (master == null) {
129 - } else { 151 + master = leadershipService.getLeader(CordVtnService.CORDVTN_APP_ID);
130 - return mastershipService.getMasterFor(ovsdbNode.bridgeId());
131 } 152 }
153 + return master;
132 } 154 }
133 155
134 private void setPassiveMode(OvsdbNode ovsdbNode) { 156 private void setPassiveMode(OvsdbNode ovsdbNode) {
135 // TODO: need ovsdb client implementation first 157 // TODO: need ovsdb client implementation first
136 // TODO: set the remove ovsdb server passive mode 158 // TODO: set the remove ovsdb server passive mode
137 - // TODO: set the node state READY if it succeed 159 + cordVtnService.updateNode(ovsdbNode, READY);
138 - }
139 -
140 - private void connect(OvsdbNode ovsdbNode) {
141 - // TODO: need ovsdb client implementation first
142 } 160 }
143 161
144 - private void disconnect(OvsdbNode ovsdbNode) { 162 + private void setupConnection(OvsdbNode ovsdbNode) {
145 - // TODO: need ovsdb client implementation first 163 + // TODO initiate connection
146 } 164 }
147 } 165 }
......
...@@ -24,51 +24,52 @@ import org.onosproject.net.DeviceId; ...@@ -24,51 +24,52 @@ import org.onosproject.net.DeviceId;
24 */ 24 */
25 public interface OvsdbNode { 25 public interface OvsdbNode {
26 /** 26 /**
27 - * State of the ovsdb node. 27 + * Ovsdb connection state.
28 */ 28 */
29 enum State { 29 enum State {
30 - INIT, READY, CONNECTED, DISCONNECTED 30 + INIT, READY, CONNECTED, DISCONNECT, DISCONNECTED
31 } 31 }
32 32
33 /** 33 /**
34 - * Returns the IP address of ovsdb server. 34 + * Returns the IP address of the ovsdb server.
35 * 35 *
36 * @return ip address 36 * @return ip address
37 */ 37 */
38 IpAddress ip(); 38 IpAddress ip();
39 39
40 /** 40 /**
41 - * Returns the port number of ovsdb server. 41 + * Returns the port number of the ovsdb server.
42 * 42 *
43 * @return port number 43 * @return port number
44 */ 44 */
45 TpPort port(); 45 TpPort port();
46 46
47 /** 47 /**
48 - * Returns the hostname of the node. 48 + * Returns the host information of the ovsdb server.
49 + * It could be hostname or ip address.
49 * 50 *
50 - * @return hostname 51 + * @return host
51 */ 52 */
52 - String hostname(); 53 + String host();
53 54
54 /** 55 /**
55 - * Returns the state of the node. 56 + * Returns the connection state of the ovsdb server.
56 * 57 *
57 - * @return state of the node 58 + * @return connection state
58 */ 59 */
59 State state(); 60 State state();
60 61
61 /** 62 /**
62 - * Returns the device ID of the node. 63 + * Returns the device id of the ovsdb server.
63 * 64 *
64 * @return device id 65 * @return device id
65 */ 66 */
66 DeviceId deviceId(); 67 DeviceId deviceId();
67 68
68 /** 69 /**
69 - * Returns the device ID of the bridge associated with this node. 70 + * Returns the device id of the integration bridge associated with the node.
70 * 71 *
71 * @return device id 72 * @return device id
72 */ 73 */
73 - DeviceId bridgeId(); 74 + DeviceId intBrId();
74 } 75 }
......