blob: c3bf77c533e4e35f977d9c5365049000feca6cc6 [file] [log] [blame]
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001/*
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 */
16package org.onosproject.cordvtn;
17
Hyunsun Moon1f145552015-10-08 22:25:30 -070018import com.google.common.collect.Sets;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Hyunsun Moond772f342015-10-28 20:28:16 -070025import org.onlab.util.ItemNotFoundException;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070026import org.onlab.util.KryoNamespace;
Hyunsun Moon1f145552015-10-08 22:25:30 -070027import org.onosproject.cluster.ClusterService;
28import org.onosproject.core.ApplicationId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070029import org.onosproject.core.CoreService;
Hyunsun Moond772f342015-10-28 20:28:16 -070030import org.onosproject.net.DefaultAnnotations;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070031import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.Host;
Hyunsun Moon8539b042015-11-07 22:08:43 -080034import org.onosproject.net.Port;
Hyunsun Moond772f342015-10-28 20:28:16 -070035import org.onosproject.net.behaviour.BridgeConfig;
36import org.onosproject.net.behaviour.BridgeName;
Hyunsun Moon1f145552015-10-08 22:25:30 -070037import org.onosproject.net.behaviour.ControllerInfo;
Hyunsun Moond772f342015-10-28 20:28:16 -070038import org.onosproject.net.behaviour.DefaultTunnelDescription;
39import org.onosproject.net.behaviour.TunnelConfig;
40import org.onosproject.net.behaviour.TunnelDescription;
41import org.onosproject.net.behaviour.TunnelName;
Hyunsun Moon8539b042015-11-07 22:08:43 -080042import org.onosproject.net.device.DeviceAdminService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070043import org.onosproject.net.device.DeviceEvent;
44import org.onosproject.net.device.DeviceListener;
45import org.onosproject.net.device.DeviceService;
Hyunsun Moond772f342015-10-28 20:28:16 -070046import org.onosproject.net.driver.DriverHandler;
47import org.onosproject.net.driver.DriverService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070048import org.onosproject.net.host.HostEvent;
49import org.onosproject.net.host.HostListener;
50import org.onosproject.net.host.HostService;
Hyunsun Moon1f145552015-10-08 22:25:30 -070051import org.onosproject.ovsdb.controller.OvsdbClientService;
52import org.onosproject.ovsdb.controller.OvsdbController;
53import org.onosproject.ovsdb.controller.OvsdbNodeId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070054import org.onosproject.store.serializers.KryoNamespaces;
Hyunsun Moon1f145552015-10-08 22:25:30 -070055import org.onosproject.store.service.ConsistentMap;
56import org.onosproject.store.service.Serializer;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070057import org.onosproject.store.service.StorageService;
58import org.slf4j.Logger;
59
Hyunsun Moon1f145552015-10-08 22:25:30 -070060import java.util.ArrayList;
61import java.util.HashMap;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070062import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070063import java.util.Map;
Hyunsun Moon523d9762015-10-19 12:38:21 -070064import java.util.NoSuchElementException;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070065import java.util.concurrent.ExecutorService;
66import java.util.concurrent.Executors;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070067
Hyunsun Moon1f145552015-10-08 22:25:30 -070068import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070069import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon2b530322015-09-23 13:24:35 -070070import static org.onosproject.net.Device.Type.SWITCH;
Hyunsun Moond772f342015-10-28 20:28:16 -070071import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070072import static org.slf4j.LoggerFactory.getLogger;
73
74/**
Hyunsun Moon2b530322015-09-23 13:24:35 -070075 * Provides initial setup or cleanup for provisioning virtual tenant networks
76 * on ovsdb, integration bridge and vm when they are added or deleted.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070077 */
78@Component(immediate = true)
79@Service
80public class CordVtn implements CordVtnService {
81
82 protected final Logger log = getLogger(getClass());
83
Hyunsun Moon2b530322015-09-23 13:24:35 -070084 private static final int NUM_THREADS = 1;
85 private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
86 .register(KryoNamespaces.API)
Hyunsun Moon8539b042015-11-07 22:08:43 -080087 .register(CordVtnNode.class)
88 .register(NodeState.class);
Hyunsun Moon1f145552015-10-08 22:25:30 -070089 private static final String DEFAULT_BRIDGE_NAME = "br-int";
Hyunsun Moon523d9762015-10-19 12:38:21 -070090 private static final String DEFAULT_TUNNEL = "vxlan";
91 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
Hyunsun Moon1f145552015-10-08 22:25:30 -070092 {
93 put("key", "flow");
Hyunsun Moon1f145552015-10-08 22:25:30 -070094 put("remote_ip", "flow");
95 }
96 };
97 private static final int DPID_BEGIN = 3;
98 private static final int OFPORT = 6653;
Hyunsun Moon2b530322015-09-23 13:24:35 -070099
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected CoreService coreService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected StorageService storageService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700107 protected DeviceService deviceService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected HostService hostService;
111
Hyunsun Moon1f145552015-10-08 22:25:30 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond772f342015-10-28 20:28:16 -0700113 protected DriverService driverService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800116 protected DeviceAdminService adminService;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1f145552015-10-08 22:25:30 -0700119 protected OvsdbController controller;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected ClusterService clusterService;
123
Hyunsun Moon2b530322015-09-23 13:24:35 -0700124 private final ExecutorService eventExecutor = Executors
125 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700126
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700127 private final DeviceListener deviceListener = new InternalDeviceListener();
128 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700129
130 private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700131 private final BridgeHandler bridgeHandler = new BridgeHandler();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700132 private final VmHandler vmHandler = new VmHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700133
Hyunsun Moon8539b042015-11-07 22:08:43 -0800134 private ConsistentMap<CordVtnNode, NodeState> nodeStore;
135
136 private enum NodeState {
137
138 INIT {
139 @Override
140 public void process(CordVtn cordVtn, CordVtnNode node) {
141 cordVtn.connect(node);
142 }
143 },
144 OVSDB_CONNECTED {
145 @Override
146 public void process(CordVtn cordVtn, CordVtnNode node) {
147 if (!cordVtn.getOvsdbConnectionState(node)) {
148 cordVtn.connect(node);
149 } else {
150 cordVtn.createIntegrationBridge(node);
151 }
152 }
153 },
154 BRIDGE_CREATED {
155 @Override
156 public void process(CordVtn cordVtn, CordVtnNode node) {
157 if (!cordVtn.getOvsdbConnectionState(node)) {
158 cordVtn.connect(node);
159 } else {
160 cordVtn.createTunnelInterface(node);
161 }
162 }
163 },
164 COMPLETE {
165 @Override
166 public void process(CordVtn cordVtn, CordVtnNode node) {
167 cordVtn.postInit(node);
168 }
169 },
170 INCOMPLETE {
171 @Override
172 public void process(CordVtn cordVtn, CordVtnNode node) {
173 }
174 };
175
176 public abstract void process(CordVtn cordVtn, CordVtnNode node);
177 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700178
179 @Activate
180 protected void activate() {
Hyunsun Moon523d9762015-10-19 12:38:21 -0700181 ApplicationId appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moon8539b042015-11-07 22:08:43 -0800182 nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
Hyunsun Moon1f145552015-10-08 22:25:30 -0700183 .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700184 .withName("cordvtn-nodestore")
Hyunsun Moon1f145552015-10-08 22:25:30 -0700185 .withApplicationId(appId)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700186 .build();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700187
188 deviceService.addListener(deviceListener);
189 hostService.addListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700190
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700191 log.info("Started");
192 }
193
194 @Deactivate
195 protected void deactivate() {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700196 deviceService.removeListener(deviceListener);
197 hostService.removeListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700198
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700199 eventExecutor.shutdown();
Hyunsun Moon1f145552015-10-08 22:25:30 -0700200 nodeStore.clear();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700201
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700202 log.info("Stopped");
203 }
204
205 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800206 public void addNode(CordVtnNode node) {
207 checkNotNull(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700208
Hyunsun Moon8539b042015-11-07 22:08:43 -0800209 nodeStore.putIfAbsent(node, checkNodeState(node));
210 initNode(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700211 }
212
213 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800214 public void deleteNode(CordVtnNode node) {
215 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700216
Hyunsun Moon8539b042015-11-07 22:08:43 -0800217 if (getOvsdbConnectionState(node)) {
218 disconnect(node);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700219 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700220
Hyunsun Moon8539b042015-11-07 22:08:43 -0800221 nodeStore.remove(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700222 }
223
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700224 @Override
225 public int getNodeCount() {
226 return nodeStore.size();
227 }
228
229 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800230 public List<CordVtnNode> getNodes() {
231 List<CordVtnNode> nodes = new ArrayList<>();
232 nodes.addAll(nodeStore.keySet());
233 return nodes;
234 }
235
236 @Override
237 public void initNode(CordVtnNode node) {
238 checkNotNull(node);
239
240 if (!nodeStore.containsKey(node)) {
241 log.warn("Node {} does not exist, add node first", node.hostname());
242 return;
243 }
244
245 NodeState state = getNodeState(node);
246 if (state == null) {
247 return;
248 } else if (state.equals(NodeState.INCOMPLETE)) {
249 state = checkNodeState(node);
250 }
251
252 state.process(this, node);
253 }
254
255 @Override
256 public boolean getNodeInitState(CordVtnNode node) {
257 checkNotNull(node);
258
259 NodeState state = getNodeState(node);
260 return state != null && state.equals(NodeState.COMPLETE);
261 }
262
263 /**
264 * Returns state of a given cordvtn node.
265 *
266 * @param node cordvtn node
267 * @return node state, or null if no such node exists
268 */
269 private NodeState getNodeState(CordVtnNode node) {
270 checkNotNull(node);
271
272 try {
273 return nodeStore.get(node).value();
274 } catch (NullPointerException e) {
275 log.error("Failed to get state of {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700276 return null;
277 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700278 }
279
Hyunsun Moon8539b042015-11-07 22:08:43 -0800280 /**
281 * Sets a new state for a given cordvtn node.
282 *
283 * @param node cordvtn node
284 * @param newState new node state
285 */
286 private void setNodeState(CordVtnNode node, NodeState newState) {
287 checkNotNull(node);
288
289 log.info("Changed {} state: {}", node.hostname(), newState.toString());
290
291 nodeStore.put(node, newState);
292 newState.process(this, node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700293 }
294
Hyunsun Moon8539b042015-11-07 22:08:43 -0800295 /**
296 * Checks current state of a given cordvtn node and returns it.
297 *
298 * @param node cordvtn node
299 * @return node state
300 */
301 private NodeState checkNodeState(CordVtnNode node) {
302 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700303
Hyunsun Moon8539b042015-11-07 22:08:43 -0800304 if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
305 return NodeState.COMPLETE;
306 } else if (checkIntegrationBridge(node)) {
307 return NodeState.BRIDGE_CREATED;
308 } else if (getOvsdbConnectionState(node)) {
309 return NodeState.OVSDB_CONNECTED;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700310 } else {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800311 return NodeState.INIT;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700312 }
313 }
314
Hyunsun Moon8539b042015-11-07 22:08:43 -0800315 /**
316 * Performs tasks after node initialization.
317 *
318 * @param node cordvtn node
319 */
320 private void postInit(CordVtnNode node) {
321 disconnect(node);
322 }
323
324 /**
325 * Returns connection state of OVSDB server for a given node.
326 *
327 * @param node cordvtn node
328 * @return true if it is connected, false otherwise
329 */
330 private boolean getOvsdbConnectionState(CordVtnNode node) {
331 checkNotNull(node);
332
333 OvsdbClientService ovsdbClient = getOvsdbClient(node);
334 return deviceService.isAvailable(node.ovsdbId()) &&
335 ovsdbClient != null && ovsdbClient.isConnected();
336 }
337
338 /**
339 * Connects to OVSDB server for a given node.
340 *
341 * @param node cordvtn node
342 */
343 private void connect(CordVtnNode node) {
344 checkNotNull(node);
345
346 if (!nodeStore.containsKey(node)) {
347 log.warn("Node {} does not exist", node.hostname());
348 return;
349 }
350
351 if (!getOvsdbConnectionState(node)) {
352 // FIXME remove existing OVSDB device to work around OVSDB device re-connect issue
353 if (deviceService.getDevice(node.ovsdbId()) != null) {
354 adminService.removeDevice(node.ovsdbId());
355 }
356 controller.connect(node.ovsdbIp(), node.ovsdbPort());
357 }
358 }
359
360 /**
361 * Disconnects OVSDB server for a given node.
362 *
363 * @param node cordvtn node
364 */
365 private void disconnect(CordVtnNode node) {
366 checkNotNull(node);
367
368 if (!nodeStore.containsKey(node)) {
369 log.warn("Node {} does not exist", node.hostname());
370 return;
371 }
372
373 if (getOvsdbConnectionState(node)) {
374 OvsdbClientService ovsdbClient = getOvsdbClient(node);
375 ovsdbClient.disconnect();
376 }
377
378 // FIXME remove existing OVSDB device to work around OVSDB device re-connect issue
379 if (deviceService.getDevice(node.ovsdbId()) != null) {
380 adminService.removeDevice(node.ovsdbId());
381 }
382 }
383
384 /**
385 * Returns cordvtn node associated with a given OVSDB device.
386 *
387 * @param ovsdbId OVSDB device id
388 * @return cordvtn node, null if it fails to find the node
389 */
390 private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) {
391 try {
392 return getNodes().stream()
393 .filter(node -> node.ovsdbId().equals(ovsdbId))
394 .findFirst().get();
395 } catch (NoSuchElementException e) {
396 log.debug("Couldn't find node information for {}", ovsdbId);
397 return null;
398 }
399 }
400
401 /**
402 * Returns cordvtn node associated with a given integration bridge.
403 *
404 * @param bridgeId device id of integration bridge
405 * @return cordvtn node, null if it fails to find the node
406 */
407 private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) {
408 try {
409 return getNodes().stream()
410 .filter(node -> node.intBrId().equals(bridgeId))
411 .findFirst().get();
412 } catch (NoSuchElementException e) {
413 log.debug("Couldn't find node information for {}", bridgeId);
414 return null;
415 }
416 }
417
418 /**
419 * Returns OVSDB client for a given node.
420 *
421 * @param node cordvtn node
422 * @return OVSDB client, or null if it fails to get OVSDB client
423 */
424 private OvsdbClientService getOvsdbClient(CordVtnNode node) {
425 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700426
427 OvsdbClientService ovsdbClient = controller.getOvsdbClient(
Hyunsun Moon8539b042015-11-07 22:08:43 -0800428 new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700429 if (ovsdbClient == null) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800430 log.debug("Couldn't find OVSDB client for {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700431 }
432 return ovsdbClient;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700433 }
434
Hyunsun Moon8539b042015-11-07 22:08:43 -0800435 /**
436 * Creates an integration bridge for a given node.
437 *
438 * @param node cordvtn node
439 */
440 private void createIntegrationBridge(CordVtnNode node) {
441 if (checkIntegrationBridge(node)) {
442 return;
443 }
444
Hyunsun Moon523d9762015-10-19 12:38:21 -0700445 List<ControllerInfo> controllers = new ArrayList<>();
446 Sets.newHashSet(clusterService.getNodes())
447 .forEach(controller -> {
448 ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
449 controllers.add(ctrlInfo);
450 });
Hyunsun Moon8539b042015-11-07 22:08:43 -0800451 String dpid = node.intBrId().toString().substring(DPID_BEGIN);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700452
Hyunsun Moon523d9762015-10-19 12:38:21 -0700453 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800454 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700455 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
456 bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, controllers);
457 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800458 log.warn("Failed to create integration bridge on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700459 }
460 }
461
Hyunsun Moon8539b042015-11-07 22:08:43 -0800462 /**
463 * Creates tunnel interface to the integration bridge for a given node.
464 *
465 * @param node cordvtn node
466 */
467 private void createTunnelInterface(CordVtnNode node) {
468 if (checkTunnelInterface(node)) {
469 return;
470 }
471
Hyunsun Moond772f342015-10-28 20:28:16 -0700472 DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
473 for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
474 optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
475 }
476 TunnelDescription description =
477 new DefaultTunnelDescription(null, null, VXLAN,
478 TunnelName.tunnelName(DEFAULT_TUNNEL),
479 optionBuilder.build());
480 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800481 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700482 TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
483 tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), description);
484 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800485 log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700486 }
487 }
488
Hyunsun Moon8539b042015-11-07 22:08:43 -0800489 /**
490 * Checks if integration bridge exists and available.
491 *
492 * @param node cordvtn node
493 * @return true if the bridge is available, false otherwise
494 */
495 private boolean checkIntegrationBridge(CordVtnNode node) {
496 return (deviceService.getDevice(node.intBrId()) != null
497 && deviceService.isAvailable(node.intBrId()));
498 }
499
500 /**
501 * Checks if tunnel interface exists.
502 *
503 * @param node cordvtn node
504 * @return true if the interface exists, false otherwise
505 */
506 private boolean checkTunnelInterface(CordVtnNode node) {
Hyunsun Moond772f342015-10-28 20:28:16 -0700507 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800508 deviceService.getPorts(node.intBrId())
509 .stream()
510 .filter(p -> p.annotations().value("portName").contains(DEFAULT_TUNNEL)
511 && p.isEnabled())
Hyunsun Moond772f342015-10-28 20:28:16 -0700512 .findAny().get();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800513 return true;
514 } catch (NoSuchElementException e) {
Hyunsun Moon523d9762015-10-19 12:38:21 -0700515 return false;
516 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700517 }
518
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700519 private class InternalDeviceListener implements DeviceListener {
520
521 @Override
522 public void event(DeviceEvent event) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800523
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700524 Device device = event.subject();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800525 ConnectionHandler<Device> handler =
526 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700527
528 switch (event.type()) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800529 case PORT_ADDED:
530 eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
Hyunsun Moon2b530322015-09-23 13:24:35 -0700531 break;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800532 case PORT_UPDATED:
533 if (!event.port().isEnabled()) {
534 eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
535 }
536 break;
537 case DEVICE_ADDED:
Hyunsun Moon2b530322015-09-23 13:24:35 -0700538 case DEVICE_AVAILABILITY_CHANGED:
Hyunsun Moon523d9762015-10-19 12:38:21 -0700539 if (deviceService.isAvailable(device.id())) {
540 eventExecutor.submit(() -> handler.connected(device));
541 } else {
542 eventExecutor.submit(() -> handler.disconnected(device));
543 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700544 break;
545 default:
546 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700547 }
548 }
549 }
550
551 private class InternalHostListener implements HostListener {
552
553 @Override
554 public void event(HostEvent event) {
555 Host vm = event.subject();
556
557 switch (event.type()) {
558 case HOST_ADDED:
559 eventExecutor.submit(() -> vmHandler.connected(vm));
560 break;
561 case HOST_REMOVED:
562 eventExecutor.submit(() -> vmHandler.disconnected(vm));
563 break;
564 default:
565 break;
566 }
567 }
568 }
569
Hyunsun Moon2b530322015-09-23 13:24:35 -0700570 private class OvsdbHandler implements ConnectionHandler<Device> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700571
572 @Override
573 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800574 CordVtnNode node = getNodeByOvsdbId(device.id());
575 if (node != null) {
576 setNodeState(node, checkNodeState(node));
Hyunsun Moon523d9762015-10-19 12:38:21 -0700577 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700578 }
579
580 @Override
581 public void disconnected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800582 log.info("OVSDB {} is disconnected", device.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700583 }
584 }
585
586 private class BridgeHandler implements ConnectionHandler<Device> {
587
588 @Override
589 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800590 CordVtnNode node = getNodeByBridgeId(device.id());
591 if (node != null) {
592 setNodeState(node, checkNodeState(node));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700593 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700594 }
595
596 @Override
597 public void disconnected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800598 CordVtnNode node = getNodeByBridgeId(device.id());
599 if (node != null) {
600 log.info("Integration Bridge is disconnected from {}", node.hostname());
601 setNodeState(node, NodeState.INCOMPLETE);
602 }
603 }
604
605 /**
606 * Handles port added situation.
607 * If the added port is tunnel port, proceed remaining node initialization.
608 * Otherwise, do nothing.
609 *
610 * @param port port
611 */
612 public void portAdded(Port port) {
613 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
614 return;
615 }
616
617 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
618 if (node != null) {
619 setNodeState(node, checkNodeState(node));
620 }
621 }
622
623 /**
624 * Handles port removed situation.
625 * If the removed port is tunnel port, proceed remaining node initialization.
626 * Others, do nothing.
627 *
628 * @param port port
629 */
630 public void portRemoved(Port port) {
631 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
632 return;
633 }
634
635 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
636 if (node != null) {
637 log.info("Tunnel interface is removed from {}", node.hostname());
638 setNodeState(node, NodeState.INCOMPLETE);
639 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700640 }
641 }
642
Hyunsun Moon2b530322015-09-23 13:24:35 -0700643 private class VmHandler implements ConnectionHandler<Host> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700644
645 @Override
646 public void connected(Host host) {
Hyunsun Moon1f145552015-10-08 22:25:30 -0700647 log.info("VM {} is detected", host.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700648 }
649
650 @Override
651 public void disconnected(Host host) {
Hyunsun Moon1f145552015-10-08 22:25:30 -0700652 log.info("VM {} is vanished", host.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700653 }
654 }
655}