Committed by
Gerrit Code Review
CORD-151 add initial skeleton for cord-vtn application
Change-Id: I57bf17445f1e571b51bca2fe7c2631e65cd43145
Showing
8 changed files
with
726 additions
and
34 deletions
... | @@ -36,6 +36,19 @@ | ... | @@ -36,6 +36,19 @@ |
36 | </properties> | 36 | </properties> |
37 | 37 | ||
38 | <dependencies> | 38 | <dependencies> |
39 | + <dependency> | ||
40 | + <groupId>org.osgi</groupId> | ||
41 | + <artifactId>org.osgi.compendium</artifactId> | ||
42 | + </dependency> | ||
43 | + <dependency> | ||
44 | + <groupId>org.onosproject</groupId> | ||
45 | + <artifactId>onos-api</artifactId> | ||
46 | + </dependency> | ||
47 | + <dependency> | ||
48 | + <groupId>org.onosproject</groupId> | ||
49 | + <artifactId>onos-core-serializers</artifactId> | ||
50 | + <version>${project.version}</version> | ||
51 | + </dependency> | ||
39 | </dependencies> | 52 | </dependencies> |
40 | 53 | ||
41 | </project> | 54 | </project> | ... | ... |
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 | +/** | ||
19 | + * Entity capable of handling a subject connected and disconnected situation. | ||
20 | + */ | ||
21 | +public interface ConnectionHandler<T> { | ||
22 | + | ||
23 | + /** | ||
24 | + * Processes the connected subject. | ||
25 | + * | ||
26 | + * @param subject subject | ||
27 | + */ | ||
28 | + void connected(T subject); | ||
29 | + | ||
30 | + /** | ||
31 | + * Processes the disconnected subject. | ||
32 | + * | ||
33 | + * @param subject subject. | ||
34 | + */ | ||
35 | + void disconnected(T subject); | ||
36 | +} |
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.apache.felix.scr.annotations.Service; | ||
24 | +import org.onlab.packet.IpAddress; | ||
25 | +import org.onlab.packet.TpPort; | ||
26 | +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; | ||
34 | +import org.onosproject.mastership.MastershipService; | ||
35 | +import org.onosproject.net.Device; | ||
36 | +import org.onosproject.net.DeviceId; | ||
37 | +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; | ||
43 | +import org.onosproject.net.device.DeviceListener; | ||
44 | +import org.onosproject.net.device.DeviceService; | ||
45 | +import org.onosproject.net.host.HostEvent; | ||
46 | +import org.onosproject.net.host.HostListener; | ||
47 | +import org.onosproject.net.host.HostService; | ||
48 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
49 | +import org.onosproject.store.service.EventuallyConsistentMap; | ||
50 | +import org.onosproject.store.service.LogicalClockService; | ||
51 | +import org.onosproject.store.service.StorageService; | ||
52 | +import org.slf4j.Logger; | ||
53 | + | ||
54 | +import java.util.List; | ||
55 | +import java.util.concurrent.ExecutorService; | ||
56 | +import java.util.concurrent.Executors; | ||
57 | +import java.util.stream.Collectors; | ||
58 | + | ||
59 | +import static org.onlab.util.Tools.groupedThreads; | ||
60 | +import static org.onosproject.cordvtn.OvsdbNode.State.INIT; | ||
61 | +import static org.slf4j.LoggerFactory.getLogger; | ||
62 | + | ||
63 | +/** | ||
64 | + * CORD VTN Application that provisions overlay virtual tenant networks. | ||
65 | + */ | ||
66 | +@Component(immediate = true) | ||
67 | +@Service | ||
68 | +public class CordVtn implements CordVtnService { | ||
69 | + | ||
70 | + protected final Logger log = getLogger(getClass()); | ||
71 | + | ||
72 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
73 | + protected CoreService coreService; | ||
74 | + | ||
75 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
76 | + protected StorageService storageService; | ||
77 | + | ||
78 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
79 | + protected LogicalClockService clockService; | ||
80 | + | ||
81 | + @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; | ||
95 | + | ||
96 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
97 | + protected HostService hostService; | ||
98 | + | ||
99 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
100 | + protected MastershipService mastershipService; | ||
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 | + | ||
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(); | ||
112 | + private final HostListener hostListener = new InternalHostListener(); | ||
113 | + private final NodeHandler nodeHandler = new NodeHandler(); | ||
114 | + private final BridgeHandler bridgeHandler = new BridgeHandler(); | ||
115 | + private final VirtualMachineHandler vmHandler = new VirtualMachineHandler(); | ||
116 | + | ||
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; | ||
128 | + private NodeConnectionManager nodeConnectionManager; | ||
129 | + | ||
130 | + @Activate | ||
131 | + protected void activate() { | ||
132 | + appId = coreService.registerApplication("org.onosproject.cordvtn"); | ||
133 | + | ||
134 | + local = clusterService.getLocalNode().id(); | ||
135 | + nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder() | ||
136 | + .withName("cordvtn-nodestore") | ||
137 | + .withSerializer(NODE_SERIALIZER) | ||
138 | + .withTimestampProvider((k, v) -> clockService.getTimestamp()) | ||
139 | + .build(); | ||
140 | + configRegistry.registerConfigFactory(configFactory); | ||
141 | + | ||
142 | + deviceService.addListener(deviceListener); | ||
143 | + hostService.addListener(hostListener); | ||
144 | + leadershipService.addListener(leadershipListener); | ||
145 | + leadershipService.runForLeadership(appId.name()); | ||
146 | + nodeConnectionManager = new NodeConnectionManager(appId, local, nodeStore, | ||
147 | + mastershipService, leadershipService); | ||
148 | + nodeConnectionManager.start(); | ||
149 | + log.info("Started"); | ||
150 | + } | ||
151 | + | ||
152 | + @Deactivate | ||
153 | + protected void deactivate() { | ||
154 | + nodeConnectionManager.stop(); | ||
155 | + leadershipService.removeListener(leadershipListener); | ||
156 | + leadershipService.withdraw(appId.name()); | ||
157 | + deviceService.removeListener(deviceListener); | ||
158 | + hostService.removeListener(hostListener); | ||
159 | + eventExecutor.shutdown(); | ||
160 | + nodeStore.destroy(); | ||
161 | + configRegistry.unregisterConfigFactory(configFactory); | ||
162 | + log.info("Stopped"); | ||
163 | + } | ||
164 | + | ||
165 | + @Override | ||
166 | + public void addNode(String hostname, IpAddress ip, TpPort port) { | ||
167 | + DefaultOvsdbNode node = new DefaultOvsdbNode(hostname, ip, port, DeviceId.NONE, INIT); | ||
168 | + | ||
169 | + if (nodeStore.containsKey(node.deviceId())) { | ||
170 | + log.warn("Node {} with ovsdb-server {}:{} already exists", hostname, ip, port); | ||
171 | + return; | ||
172 | + } | ||
173 | + nodeStore.put(node.deviceId(), node); | ||
174 | + log.info("New node {} with ovsdb-server {}:{} has been added", hostname, ip, port); | ||
175 | + } | ||
176 | + | ||
177 | + @Override | ||
178 | + public void deleteNode(IpAddress ip, TpPort port) { | ||
179 | + DeviceId deviceId = DeviceId.deviceId("ovsdb:" + ip + ":" + port); | ||
180 | + OvsdbNode node = nodeStore.get(deviceId); | ||
181 | + | ||
182 | + if (node == null) { | ||
183 | + log.warn("Node with ovsdb-server on {}:{} does not exist", ip, port); | ||
184 | + return; | ||
185 | + } | ||
186 | + nodeConnectionManager.disconnectNode(node); | ||
187 | + nodeStore.remove(node.deviceId()); | ||
188 | + } | ||
189 | + | ||
190 | + @Override | ||
191 | + public int getNodeCount() { | ||
192 | + return nodeStore.size(); | ||
193 | + } | ||
194 | + | ||
195 | + @Override | ||
196 | + public List<OvsdbNode> getNodes() { | ||
197 | + return nodeStore.values() | ||
198 | + .stream() | ||
199 | + .collect(Collectors.toList()); | ||
200 | + } | ||
201 | + | ||
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 { | ||
232 | + | ||
233 | + @Override | ||
234 | + public void event(DeviceEvent event) { | ||
235 | + Device device = event.subject(); | ||
236 | + ConnectionHandler handler = | ||
237 | + (device.type() == Device.Type.CONTROLLER ? nodeHandler : bridgeHandler); | ||
238 | + | ||
239 | + switch (event.type()) { | ||
240 | + case DEVICE_ADDED: | ||
241 | + eventExecutor.submit(() -> handler.connected(device)); | ||
242 | + break; | ||
243 | + case DEVICE_AVAILABILITY_CHANGED: | ||
244 | + eventExecutor.submit(() -> handler.disconnected(device)); | ||
245 | + break; | ||
246 | + default: | ||
247 | + break; | ||
248 | + } | ||
249 | + } | ||
250 | + } | ||
251 | + | ||
252 | + private class InternalHostListener implements HostListener { | ||
253 | + | ||
254 | + @Override | ||
255 | + public void event(HostEvent event) { | ||
256 | + Host vm = event.subject(); | ||
257 | + | ||
258 | + switch (event.type()) { | ||
259 | + case HOST_ADDED: | ||
260 | + eventExecutor.submit(() -> vmHandler.connected(vm)); | ||
261 | + break; | ||
262 | + case HOST_REMOVED: | ||
263 | + eventExecutor.submit(() -> vmHandler.disconnected(vm)); | ||
264 | + break; | ||
265 | + default: | ||
266 | + break; | ||
267 | + } | ||
268 | + } | ||
269 | + } | ||
270 | + | ||
271 | + private class NodeHandler implements ConnectionHandler<Device> { | ||
272 | + | ||
273 | + @Override | ||
274 | + public void connected(Device device) { | ||
275 | + // create bridge and set bridgeId | ||
276 | + // set node state connected | ||
277 | + } | ||
278 | + | ||
279 | + @Override | ||
280 | + public void disconnected(Device device) { | ||
281 | + // set node state disconnected if the node exists | ||
282 | + // which means that the node is not deleted explicitly | ||
283 | + } | ||
284 | + } | ||
285 | + | ||
286 | + private class BridgeHandler implements ConnectionHandler<Device> { | ||
287 | + | ||
288 | + @Override | ||
289 | + public void connected(Device device) { | ||
290 | + // create vxlan port | ||
291 | + } | ||
292 | + | ||
293 | + @Override | ||
294 | + public void disconnected(Device device) { | ||
295 | + | ||
296 | + } | ||
297 | + } | ||
298 | + | ||
299 | + private class VirtualMachineHandler implements ConnectionHandler<Host> { | ||
300 | + | ||
301 | + @Override | ||
302 | + public void connected(Host host) { | ||
303 | + // install flow rules for this vm | ||
304 | + } | ||
305 | + | ||
306 | + @Override | ||
307 | + public void disconnected(Host host) { | ||
308 | + // uninstall flow rules associated with this vm | ||
309 | + } | ||
310 | + } | ||
311 | +} |
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 com.fasterxml.jackson.databind.JsonNode; | ||
19 | +import com.google.common.collect.Sets; | ||
20 | +import org.onlab.packet.IpAddress; | ||
21 | +import org.onlab.packet.TpPort; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | +import org.onosproject.net.config.Config; | ||
24 | + | ||
25 | +import java.util.Set; | ||
26 | + | ||
27 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
28 | + | ||
29 | +/** | ||
30 | + * Configuration object for CORD VTN service. | ||
31 | + */ | ||
32 | +public class CordVtnConfig extends Config<ApplicationId> { | ||
33 | + | ||
34 | + public static final String OVSDB_NODES = "ovsdbNodes"; | ||
35 | + public static final String HOSTNAME = "hostname"; | ||
36 | + public static final String IP = "ip"; | ||
37 | + public static final String PORT = "port"; | ||
38 | + | ||
39 | + /** | ||
40 | + * Returns the set of ovsdb nodes read from network config. | ||
41 | + * | ||
42 | + * @return set of OvsdbNodeConfig or null | ||
43 | + */ | ||
44 | + public Set<OvsdbNodeConfig> ovsdbNodes() { | ||
45 | + Set<OvsdbNodeConfig> ovsdbNodes = Sets.newHashSet(); | ||
46 | + | ||
47 | + JsonNode nodes = object.get(OVSDB_NODES); | ||
48 | + if (nodes == null) { | ||
49 | + return null; | ||
50 | + } | ||
51 | + nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig( | ||
52 | + jsonNode.path(HOSTNAME).asText(), | ||
53 | + IpAddress.valueOf(jsonNode.path(IP).asText()), | ||
54 | + TpPort.tpPort(jsonNode.path(PORT).asInt())))); | ||
55 | + | ||
56 | + return ovsdbNodes; | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * Configuration for an OVSDB node. | ||
61 | + */ | ||
62 | + public static class OvsdbNodeConfig { | ||
63 | + | ||
64 | + private final String hostname; | ||
65 | + private final IpAddress ip; | ||
66 | + private final TpPort port; | ||
67 | + | ||
68 | + public OvsdbNodeConfig(String hostname, IpAddress ip, TpPort port) { | ||
69 | + this.hostname = checkNotNull(hostname); | ||
70 | + this.ip = checkNotNull(ip); | ||
71 | + this.port = checkNotNull(port); | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * Returns hostname of the node. | ||
76 | + * | ||
77 | + * @return hostname | ||
78 | + */ | ||
79 | + public String hostname() { | ||
80 | + return this.hostname; | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Returns ip address to access ovsdb-server of the node. | ||
85 | + * | ||
86 | + * @return ip address | ||
87 | + */ | ||
88 | + public IpAddress ip() { | ||
89 | + return this.ip; | ||
90 | + } | ||
91 | + | ||
92 | + /** | ||
93 | + * Returns port number to access ovsdb-server of the node. | ||
94 | + * | ||
95 | + * @return port number | ||
96 | + */ | ||
97 | + public TpPort port() { | ||
98 | + return this.port; | ||
99 | + } | ||
100 | + } | ||
101 | +} |
... | @@ -15,6 +15,9 @@ | ... | @@ -15,6 +15,9 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.cordvtn; | 16 | package org.onosproject.cordvtn; |
17 | 17 | ||
18 | +import org.onlab.packet.IpAddress; | ||
19 | +import org.onlab.packet.TpPort; | ||
20 | + | ||
18 | import java.util.List; | 21 | import java.util.List; |
19 | 22 | ||
20 | /** | 23 | /** |
... | @@ -22,19 +25,21 @@ import java.util.List; | ... | @@ -22,19 +25,21 @@ import java.util.List; |
22 | */ | 25 | */ |
23 | public interface CordVtnService { | 26 | public interface CordVtnService { |
24 | /** | 27 | /** |
25 | - * Adds new nodes to the service and processes initial setup. | 28 | + * Adds a new node to the service. |
26 | * | 29 | * |
27 | - * @param ovsdbNodes list of nodes | 30 | + * @param hostname hostname of the node |
31 | + * @param ip ip address to access the ovsdb server running on the node | ||
32 | + * @param port port number to access the ovsdb server running on the node | ||
28 | */ | 33 | */ |
29 | - void addNodes(List<OvsdbNode> ovsdbNodes); | 34 | + void addNode(String hostname, IpAddress ip, TpPort port); |
30 | 35 | ||
31 | /** | 36 | /** |
32 | - * Deletes the nodes from the service and cleans up unnecessary configurations | 37 | + * Deletes the node from the service. |
33 | - * associated with the deleted nodes. | ||
34 | * | 38 | * |
35 | - * @param ovsdbNodes list of nodes | 39 | + * @param ip ip address to access the ovsdb server running on the node |
40 | + * @param port port number to access the ovsdb server running on the node | ||
36 | */ | 41 | */ |
37 | - void deleteNodes(List<OvsdbNode> ovsdbNodes); | 42 | + void deleteNode(IpAddress ip, TpPort port); |
38 | 43 | ||
39 | /** | 44 | /** |
40 | * Returns the number of the nodes known to the service. | 45 | * Returns the number of the nodes known to the service. | ... | ... |
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.onlab.packet.IpAddress; | ||
19 | +import org.onlab.packet.TpPort; | ||
20 | +import org.onosproject.net.DeviceId; | ||
21 | + | ||
22 | +import java.util.Objects; | ||
23 | + | ||
24 | +/** | ||
25 | + * OvsdbNode implementation. | ||
26 | + */ | ||
27 | +public class DefaultOvsdbNode implements OvsdbNode { | ||
28 | + | ||
29 | + private final String hostname; | ||
30 | + private final IpAddress ip; | ||
31 | + private final TpPort port; | ||
32 | + private final DeviceId deviceId; | ||
33 | + private final DeviceId bridgeId; | ||
34 | + private final State state; | ||
35 | + | ||
36 | + public DefaultOvsdbNode(String hostname, IpAddress ip, TpPort port, | ||
37 | + DeviceId bridgeId, State state) { | ||
38 | + this.hostname = hostname; | ||
39 | + this.ip = ip; | ||
40 | + this.port = port; | ||
41 | + this.deviceId = DeviceId.deviceId( | ||
42 | + "ovsdb:" + ip.toString() + ":" + port.toString()); | ||
43 | + this.bridgeId = bridgeId; | ||
44 | + this.state = state; | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public IpAddress ip() { | ||
49 | + return this.ip; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public TpPort port() { | ||
54 | + return this.port; | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + public String hostname() { | ||
59 | + return this.hostname; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public State state() { | ||
64 | + return this.state; | ||
65 | + } | ||
66 | + | ||
67 | + @Override | ||
68 | + public DeviceId deviceId() { | ||
69 | + return this.deviceId; | ||
70 | + } | ||
71 | + | ||
72 | + @Override | ||
73 | + public DeviceId bridgeId() { | ||
74 | + return this.bridgeId; | ||
75 | + } | ||
76 | + | ||
77 | + @Override | ||
78 | + public boolean equals(Object o) { | ||
79 | + if (this == o) { | ||
80 | + return true; | ||
81 | + } | ||
82 | + | ||
83 | + if (o instanceof DefaultOvsdbNode) { | ||
84 | + DefaultOvsdbNode that = (DefaultOvsdbNode) o; | ||
85 | + // We compare the ip and port only. | ||
86 | + if (this.ip.equals(that.ip) && this.port.equals(that.port)) { | ||
87 | + return true; | ||
88 | + } | ||
89 | + } | ||
90 | + return false; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public int hashCode() { | ||
95 | + return Objects.hash(ip, port); | ||
96 | + } | ||
97 | +} |
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.onosproject.cluster.LeadershipService; | ||
19 | +import org.onosproject.cluster.NodeId; | ||
20 | +import org.onosproject.core.ApplicationId; | ||
21 | +import org.onosproject.mastership.MastershipService; | ||
22 | +import org.onosproject.net.DeviceId; | ||
23 | +import org.onosproject.store.service.EventuallyConsistentMap; | ||
24 | +import org.slf4j.Logger; | ||
25 | + | ||
26 | +import java.util.concurrent.Executors; | ||
27 | +import java.util.concurrent.ScheduledExecutorService; | ||
28 | +import java.util.concurrent.TimeUnit; | ||
29 | + | ||
30 | +import static org.onlab.util.Tools.groupedThreads; | ||
31 | +import static org.slf4j.LoggerFactory.getLogger; | ||
32 | + | ||
33 | +/** | ||
34 | + * Node connection manager. | ||
35 | + */ | ||
36 | +public class NodeConnectionManager { | ||
37 | + protected final Logger log = getLogger(getClass()); | ||
38 | + | ||
39 | + private final ApplicationId appId; | ||
40 | + private final NodeId localId; | ||
41 | + private final EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore; | ||
42 | + private final MastershipService mastershipService; | ||
43 | + private final LeadershipService leadershipService; | ||
44 | + | ||
45 | + private static final int DELAY_SEC = 5; | ||
46 | + private ScheduledExecutorService connectionExecutor; | ||
47 | + | ||
48 | + /** | ||
49 | + * Creates a new NodeConnectionManager. | ||
50 | + * | ||
51 | + * @param localId local id | ||
52 | + * @param nodeStore node store | ||
53 | + * @param mastershipService mastership service | ||
54 | + */ | ||
55 | + public NodeConnectionManager(ApplicationId appId, NodeId localId, | ||
56 | + EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore, | ||
57 | + MastershipService mastershipService, | ||
58 | + LeadershipService leadershipService) { | ||
59 | + this.appId = appId; | ||
60 | + this.localId = localId; | ||
61 | + this.nodeStore = nodeStore; | ||
62 | + this.mastershipService = mastershipService; | ||
63 | + this.leadershipService = leadershipService; | ||
64 | + } | ||
65 | + | ||
66 | + /** | ||
67 | + * Starts the node connection manager. | ||
68 | + */ | ||
69 | + public void start() { | ||
70 | + connectionExecutor = Executors.newSingleThreadScheduledExecutor( | ||
71 | + groupedThreads("onos/cordvtn", "connection-executor")); | ||
72 | + connectionExecutor.scheduleWithFixedDelay(() -> nodeStore.values() | ||
73 | + .stream() | ||
74 | + .filter(node -> localId.equals(getMaster(node))) | ||
75 | + .forEach(node -> connectNode(node)), 0, DELAY_SEC, TimeUnit.SECONDS); | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
79 | + * Stops the node connection manager. | ||
80 | + */ | ||
81 | + public void stop() { | ||
82 | + connectionExecutor.shutdown(); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Adds a new node to the system. | ||
87 | + * | ||
88 | + * @param ovsdbNode ovsdb node | ||
89 | + */ | ||
90 | + public void connectNode(OvsdbNode ovsdbNode) { | ||
91 | + switch (ovsdbNode.state()) { | ||
92 | + case INIT: | ||
93 | + case DISCONNECTED: | ||
94 | + // TODO: set the node to passive mode | ||
95 | + case READY: | ||
96 | + // TODO: initiate connection | ||
97 | + break; | ||
98 | + case CONNECTED: | ||
99 | + break; | ||
100 | + default: | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * Deletes the ovsdb node. | ||
106 | + * | ||
107 | + * @param ovsdbNode ovsdb node | ||
108 | + */ | ||
109 | + public void disconnectNode(OvsdbNode ovsdbNode) { | ||
110 | + switch (ovsdbNode.state()) { | ||
111 | + case CONNECTED: | ||
112 | + // TODO: disconnect | ||
113 | + break; | ||
114 | + case INIT: | ||
115 | + case READY: | ||
116 | + case DISCONNECTED: | ||
117 | + break; | ||
118 | + default: | ||
119 | + } | ||
120 | + } | ||
121 | + | ||
122 | + private NodeId getMaster(OvsdbNode ovsdbNode) { | ||
123 | + // Return the master of the bridge(switch) if it exist or | ||
124 | + // return the current leader | ||
125 | + if (ovsdbNode.bridgeId() == DeviceId.NONE) { | ||
126 | + return leadershipService.getLeader(this.appId.name()); | ||
127 | + } else { | ||
128 | + return mastershipService.getMasterFor(ovsdbNode.bridgeId()); | ||
129 | + } | ||
130 | + } | ||
131 | + | ||
132 | + private void setPassiveMode(OvsdbNode ovsdbNode) { | ||
133 | + // TODO: need ovsdb client implementation first | ||
134 | + // TODO: set the remove ovsdb server passive mode | ||
135 | + // TODO: set the node state READY if it succeed | ||
136 | + } | ||
137 | + | ||
138 | + private void connect(OvsdbNode ovsdbNode) { | ||
139 | + // TODO: need ovsdb client implementation first | ||
140 | + } | ||
141 | + | ||
142 | + private void disconnect(OvsdbNode ovsdbNode) { | ||
143 | + // TODO: need ovsdb client implementation first | ||
144 | + } | ||
145 | +} |
... | @@ -18,8 +18,6 @@ package org.onosproject.cordvtn; | ... | @@ -18,8 +18,6 @@ package org.onosproject.cordvtn; |
18 | import org.onlab.packet.IpAddress; | 18 | import org.onlab.packet.IpAddress; |
19 | import org.onlab.packet.TpPort; | 19 | import org.onlab.packet.TpPort; |
20 | import org.onosproject.net.DeviceId; | 20 | import org.onosproject.net.DeviceId; |
21 | -import org.onosproject.net.behaviour.BridgeConfig; | ||
22 | -import org.onosproject.net.behaviour.TunnelConfig; | ||
23 | 21 | ||
24 | /** | 22 | /** |
25 | * Representation of a node with ovsdb server. | 23 | * Representation of a node with ovsdb server. |
... | @@ -29,7 +27,7 @@ public interface OvsdbNode { | ... | @@ -29,7 +27,7 @@ public interface OvsdbNode { |
29 | * State of the ovsdb node. | 27 | * State of the ovsdb node. |
30 | */ | 28 | */ |
31 | enum State { | 29 | enum State { |
32 | - READY, CONNECTED, DISCONNECTED | 30 | + INIT, READY, CONNECTED, DISCONNECTED |
33 | } | 31 | } |
34 | 32 | ||
35 | /** | 33 | /** |
... | @@ -47,44 +45,30 @@ public interface OvsdbNode { | ... | @@ -47,44 +45,30 @@ public interface OvsdbNode { |
47 | TpPort port(); | 45 | TpPort port(); |
48 | 46 | ||
49 | /** | 47 | /** |
50 | - * Returns the state of the node. | 48 | + * Returns the hostname of the node. |
51 | * | 49 | * |
52 | - * @return state of the node | 50 | + * @return hostname |
53 | */ | 51 | */ |
54 | - State getState(); | 52 | + String hostname(); |
55 | 53 | ||
56 | /** | 54 | /** |
57 | - * Sets the state of the node. | 55 | + * Returns the state of the node. |
58 | * | 56 | * |
59 | - * @param state state of the node | 57 | + * @return state of the node |
60 | */ | 58 | */ |
61 | - void setState(State state); | 59 | + State state(); |
62 | 60 | ||
63 | /** | 61 | /** |
64 | * Returns the device ID of the node. | 62 | * Returns the device ID of the node. |
65 | * | 63 | * |
66 | * @return device id | 64 | * @return device id |
67 | */ | 65 | */ |
68 | - DeviceId getDeviceId(); | 66 | + DeviceId deviceId(); |
69 | 67 | ||
70 | /** | 68 | /** |
71 | - * Sets the device id of the node. | 69 | + * Returns the device ID of the bridge associated with this node. |
72 | * | 70 | * |
73 | - * @param deviceId device identifier | 71 | + * @return device id |
74 | - */ | ||
75 | - void setDeviceId(DeviceId deviceId); | ||
76 | - | ||
77 | - /** | ||
78 | - * Returns the bridge configuration handler of the node. | ||
79 | - * | ||
80 | - * @return bridge config behavior instance | ||
81 | - */ | ||
82 | - BridgeConfig getBridgeConfig(); | ||
83 | - | ||
84 | - /** | ||
85 | - * Returns the tunnel configuration handler of the node. | ||
86 | - * | ||
87 | - * @return tunnel config behavior instance | ||
88 | */ | 72 | */ |
89 | - TunnelConfig getTunnelConfig(); | 73 | + DeviceId bridgeId(); |
90 | } | 74 | } | ... | ... |
-
Please register or login to post a comment