blob: c7a7c79920e876407e201e23d98ad047a00425c8 [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 Moon9f0814b2015-11-04 17:34:35 -080018import com.google.common.collect.Maps;
Hyunsun Moon1f145552015-10-08 22:25:30 -070019import com.google.common.collect.Sets;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -080026import org.onlab.packet.Ethernet;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080027import org.onlab.packet.Ip4Address;
Hyunsun Moond772f342015-10-28 20:28:16 -070028import org.onlab.util.ItemNotFoundException;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080029import org.onlab.packet.IpAddress;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070030import org.onlab.util.KryoNamespace;
Hyunsun Moon1f145552015-10-08 22:25:30 -070031import org.onosproject.cluster.ClusterService;
32import org.onosproject.core.ApplicationId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070033import org.onosproject.core.CoreService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080034import org.onosproject.mastership.MastershipService;
Hyunsun Moond772f342015-10-28 20:28:16 -070035import org.onosproject.net.DefaultAnnotations;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070036import org.onosproject.net.Device;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.Host;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080039import org.onosproject.net.HostId;
Hyunsun Moon8539b042015-11-07 22:08:43 -080040import org.onosproject.net.Port;
Hyunsun Moond772f342015-10-28 20:28:16 -070041import org.onosproject.net.behaviour.BridgeConfig;
42import org.onosproject.net.behaviour.BridgeName;
Hyunsun Moon1f145552015-10-08 22:25:30 -070043import org.onosproject.net.behaviour.ControllerInfo;
Hyunsun Moond772f342015-10-28 20:28:16 -070044import org.onosproject.net.behaviour.DefaultTunnelDescription;
45import org.onosproject.net.behaviour.TunnelConfig;
46import org.onosproject.net.behaviour.TunnelDescription;
47import org.onosproject.net.behaviour.TunnelName;
Hyunsun Moon8539b042015-11-07 22:08:43 -080048import org.onosproject.net.device.DeviceAdminService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070049import org.onosproject.net.device.DeviceEvent;
50import org.onosproject.net.device.DeviceListener;
51import org.onosproject.net.device.DeviceService;
Hyunsun Moond772f342015-10-28 20:28:16 -070052import org.onosproject.net.driver.DriverHandler;
53import org.onosproject.net.driver.DriverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080054import org.onosproject.net.flow.FlowRuleService;
55import org.onosproject.net.group.GroupService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070056import org.onosproject.net.host.HostEvent;
57import org.onosproject.net.host.HostListener;
58import org.onosproject.net.host.HostService;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -080059import org.onosproject.net.packet.PacketContext;
60import org.onosproject.net.packet.PacketProcessor;
61import org.onosproject.net.packet.PacketService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080062import org.onosproject.openstackswitching.OpenstackNetwork;
63import org.onosproject.openstackswitching.OpenstackPort;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080064import org.onosproject.openstackswitching.OpenstackSubnet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080065import org.onosproject.openstackswitching.OpenstackSwitchingService;
Hyunsun Moon1f145552015-10-08 22:25:30 -070066import org.onosproject.ovsdb.controller.OvsdbClientService;
67import org.onosproject.ovsdb.controller.OvsdbController;
68import org.onosproject.ovsdb.controller.OvsdbNodeId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070069import org.onosproject.store.serializers.KryoNamespaces;
Hyunsun Moon1f145552015-10-08 22:25:30 -070070import org.onosproject.store.service.ConsistentMap;
71import org.onosproject.store.service.Serializer;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070072import org.onosproject.store.service.StorageService;
73import org.slf4j.Logger;
74
Hyunsun Moon1f145552015-10-08 22:25:30 -070075import java.util.ArrayList;
76import java.util.HashMap;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070077import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070078import java.util.Map;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080079import java.util.Objects;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080080import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070081import java.util.concurrent.ExecutorService;
82import java.util.concurrent.Executors;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080083import java.util.stream.Collectors;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070084
Hyunsun Moon1f145552015-10-08 22:25:30 -070085import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070086import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon2b530322015-09-23 13:24:35 -070087import static org.onosproject.net.Device.Type.SWITCH;
Hyunsun Moond772f342015-10-28 20:28:16 -070088import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070089import static org.slf4j.LoggerFactory.getLogger;
90
91/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080092 * Provisions virtual tenant networks with service chaining capability
93 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070094 */
95@Component(immediate = true)
96@Service
97public class CordVtn implements CordVtnService {
98
99 protected final Logger log = getLogger(getClass());
100
Hyunsun Moon2b530322015-09-23 13:24:35 -0700101 private static final int NUM_THREADS = 1;
102 private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
103 .register(KryoNamespaces.API)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800104 .register(CordVtnNode.class)
105 .register(NodeState.class);
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800106
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800107 private static final String DEFAULT_BRIDGE = "br-int";
108 private static final String VPORT_PREFIX = "tap";
Hyunsun Moon523d9762015-10-19 12:38:21 -0700109 private static final String DEFAULT_TUNNEL = "vxlan";
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800110 private static final String OK = "OK";
111 private static final String NO = "NO";
112
Hyunsun Moon523d9762015-10-19 12:38:21 -0700113 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
Hyunsun Moon1f145552015-10-08 22:25:30 -0700114 {
115 put("key", "flow");
Hyunsun Moon1f145552015-10-08 22:25:30 -0700116 put("remote_ip", "flow");
117 }
118 };
119 private static final int DPID_BEGIN = 3;
120 private static final int OFPORT = 6653;
Hyunsun Moon2b530322015-09-23 13:24:35 -0700121
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected CoreService coreService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected StorageService storageService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700129 protected DeviceService deviceService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected HostService hostService;
133
Hyunsun Moon1f145552015-10-08 22:25:30 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond772f342015-10-28 20:28:16 -0700135 protected DriverService driverService;
136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800138 protected DeviceAdminService adminService;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800141 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800144 protected PacketService packetService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1f145552015-10-08 22:25:30 -0700147 protected OvsdbController controller;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected ClusterService clusterService;
151
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800153 protected MastershipService mastershipService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
156 protected GroupService groupService;
157
158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800159 protected OpenstackSwitchingService openstackService;
160
Hyunsun Moon2b530322015-09-23 13:24:35 -0700161 private final ExecutorService eventExecutor = Executors
162 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700163
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700164 private final DeviceListener deviceListener = new InternalDeviceListener();
165 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800166 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700167
168 private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700169 private final BridgeHandler bridgeHandler = new BridgeHandler();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700170 private final VmHandler vmHandler = new VmHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700171
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800172 private ApplicationId appId;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800173 private ConsistentMap<CordVtnNode, NodeState> nodeStore;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800174 private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800175 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800176 private CordVtnArpProxy arpProxy;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800177
178 private enum NodeState {
179
180 INIT {
181 @Override
182 public void process(CordVtn cordVtn, CordVtnNode node) {
183 cordVtn.connect(node);
184 }
185 },
186 OVSDB_CONNECTED {
187 @Override
188 public void process(CordVtn cordVtn, CordVtnNode node) {
189 if (!cordVtn.getOvsdbConnectionState(node)) {
190 cordVtn.connect(node);
191 } else {
192 cordVtn.createIntegrationBridge(node);
193 }
194 }
195 },
196 BRIDGE_CREATED {
197 @Override
198 public void process(CordVtn cordVtn, CordVtnNode node) {
199 if (!cordVtn.getOvsdbConnectionState(node)) {
200 cordVtn.connect(node);
201 } else {
202 cordVtn.createTunnelInterface(node);
203 }
204 }
205 },
206 COMPLETE {
207 @Override
208 public void process(CordVtn cordVtn, CordVtnNode node) {
209 cordVtn.postInit(node);
210 }
211 },
212 INCOMPLETE {
213 @Override
214 public void process(CordVtn cordVtn, CordVtnNode node) {
215 }
216 };
217
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800218 // TODO Add physical port add state
219
Hyunsun Moon8539b042015-11-07 22:08:43 -0800220 public abstract void process(CordVtn cordVtn, CordVtnNode node);
221 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700222
223 @Activate
224 protected void activate() {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800225 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moon8539b042015-11-07 22:08:43 -0800226 nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
Hyunsun Moon1f145552015-10-08 22:25:30 -0700227 .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700228 .withName("cordvtn-nodestore")
Hyunsun Moon1f145552015-10-08 22:25:30 -0700229 .withApplicationId(appId)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700230 .build();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700231
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800232 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
233 deviceService,
234 driverService,
235 groupService,
236 mastershipService,
237 DEFAULT_TUNNEL);
238
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800239 arpProxy = new CordVtnArpProxy(appId, packetService);
240 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
241 arpProxy.requestPacket();
242
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700243 deviceService.addListener(deviceListener);
244 hostService.addListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700245
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700246 log.info("Started");
247 }
248
249 @Deactivate
250 protected void deactivate() {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700251 deviceService.removeListener(deviceListener);
252 hostService.removeListener(hostListener);
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800253 packetService.removeProcessor(packetProcessor);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700254
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700255 eventExecutor.shutdown();
Hyunsun Moon1f145552015-10-08 22:25:30 -0700256 nodeStore.clear();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700257
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700258 log.info("Stopped");
259 }
260
261 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800262 public void addNode(CordVtnNode node) {
263 checkNotNull(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700264
Hyunsun Moon8539b042015-11-07 22:08:43 -0800265 nodeStore.putIfAbsent(node, checkNodeState(node));
266 initNode(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700267 }
268
269 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800270 public void deleteNode(CordVtnNode node) {
271 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700272
Hyunsun Moon8539b042015-11-07 22:08:43 -0800273 if (getOvsdbConnectionState(node)) {
274 disconnect(node);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700275 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700276
Hyunsun Moon8539b042015-11-07 22:08:43 -0800277 nodeStore.remove(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700278 }
279
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700280 @Override
281 public int getNodeCount() {
282 return nodeStore.size();
283 }
284
285 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800286 public List<CordVtnNode> getNodes() {
287 List<CordVtnNode> nodes = new ArrayList<>();
288 nodes.addAll(nodeStore.keySet());
289 return nodes;
290 }
291
292 @Override
293 public void initNode(CordVtnNode node) {
294 checkNotNull(node);
295
296 if (!nodeStore.containsKey(node)) {
297 log.warn("Node {} does not exist, add node first", node.hostname());
298 return;
299 }
300
Hyunsun Moonbaf70542015-12-16 14:29:36 -0800301 NodeState state = checkNodeState(node);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800302 state.process(this, node);
303 }
304
305 @Override
306 public boolean getNodeInitState(CordVtnNode node) {
307 checkNotNull(node);
308
309 NodeState state = getNodeState(node);
310 return state != null && state.equals(NodeState.COMPLETE);
311 }
312
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800313 @Override
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800314 public String checkNodeInitState(CordVtnNode node) {
315 checkNotNull(node);
316
317 NodeState state = getNodeState(node);
318 if (state == null) {
319 log.warn("Failed to get init state of {}", node.hostname());
320 return null;
321 }
322
323 String result = String.format(
324 "Integration bridge created/connected : %s (%s)%n" +
325 "VXLAN interface created : %s%n" +
326 "Physical interface added : %s (%s)",
327 checkIntegrationBridge(node) ? OK : NO, DEFAULT_BRIDGE,
328 checkTunnelInterface(node) ? OK : NO,
329 checkPhyInterface(node) ? OK : NO, node.phyPortName());
330
331 return result;
332 }
333
334 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800335 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
336 CordService tService = getCordService(tServiceId);
337 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800338
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800339 if (tService == null || pService == null) {
340 log.error("Failed to create CordService for {}", tServiceId.id());
341 return;
342 }
343
344 ruleInstaller.populateServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800345 }
346
347 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800348 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
349 CordService tService = getCordService(tServiceId);
350 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800351
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800352 if (tService == null || pService == null) {
353 log.error("Failed to create CordService for {}", tServiceId.id());
354 return;
355 }
356
357 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800358 }
359
Hyunsun Moon8539b042015-11-07 22:08:43 -0800360 /**
361 * Returns state of a given cordvtn node.
362 *
363 * @param node cordvtn node
364 * @return node state, or null if no such node exists
365 */
366 private NodeState getNodeState(CordVtnNode node) {
367 checkNotNull(node);
368
369 try {
370 return nodeStore.get(node).value();
371 } catch (NullPointerException e) {
372 log.error("Failed to get state of {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700373 return null;
374 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700375 }
376
Hyunsun Moon8539b042015-11-07 22:08:43 -0800377 /**
378 * Sets a new state for a given cordvtn node.
379 *
380 * @param node cordvtn node
381 * @param newState new node state
382 */
383 private void setNodeState(CordVtnNode node, NodeState newState) {
384 checkNotNull(node);
385
386 log.info("Changed {} state: {}", node.hostname(), newState.toString());
387
388 nodeStore.put(node, newState);
389 newState.process(this, node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700390 }
391
Hyunsun Moon8539b042015-11-07 22:08:43 -0800392 /**
393 * Checks current state of a given cordvtn node and returns it.
394 *
395 * @param node cordvtn node
396 * @return node state
397 */
398 private NodeState checkNodeState(CordVtnNode node) {
399 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700400
Hyunsun Moon8539b042015-11-07 22:08:43 -0800401 if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800402 // TODO add physical port add state
403 if (checkPhyInterface(node)) {
404 return NodeState.COMPLETE;
405 } else {
406 return NodeState.INCOMPLETE;
407 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800408 } else if (checkIntegrationBridge(node)) {
409 return NodeState.BRIDGE_CREATED;
410 } else if (getOvsdbConnectionState(node)) {
411 return NodeState.OVSDB_CONNECTED;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700412 } else {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800413 return NodeState.INIT;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700414 }
415 }
416
Hyunsun Moon8539b042015-11-07 22:08:43 -0800417 /**
418 * Performs tasks after node initialization.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800419 * First disconnect unnecessary OVSDB connection and then installs flow rules
420 * for existing VMs if there are any.
Hyunsun Moon8539b042015-11-07 22:08:43 -0800421 *
422 * @param node cordvtn node
423 */
424 private void postInit(CordVtnNode node) {
425 disconnect(node);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800426
Hyunsun Moon4a915152016-01-14 16:56:26 -0800427 ruleInstaller.init(node.intBrId(), node.phyPortName(), node.localIp());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800428 hostService.getConnectedHosts(node.intBrId())
429 .stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800430 .forEach(vmHandler::connected);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800431
432 log.info("Finished initializing {}", node.hostname());
Hyunsun Moon8539b042015-11-07 22:08:43 -0800433 }
434
435 /**
436 * Returns connection state of OVSDB server for a given node.
437 *
438 * @param node cordvtn node
439 * @return true if it is connected, false otherwise
440 */
441 private boolean getOvsdbConnectionState(CordVtnNode node) {
442 checkNotNull(node);
443
444 OvsdbClientService ovsdbClient = getOvsdbClient(node);
445 return deviceService.isAvailable(node.ovsdbId()) &&
446 ovsdbClient != null && ovsdbClient.isConnected();
447 }
448
449 /**
450 * Connects to OVSDB server for a given node.
451 *
452 * @param node cordvtn node
453 */
454 private void connect(CordVtnNode node) {
455 checkNotNull(node);
456
457 if (!nodeStore.containsKey(node)) {
458 log.warn("Node {} does not exist", node.hostname());
459 return;
460 }
461
462 if (!getOvsdbConnectionState(node)) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800463 controller.connect(node.ovsdbIp(), node.ovsdbPort());
464 }
465 }
466
467 /**
468 * Disconnects OVSDB server for a given node.
469 *
470 * @param node cordvtn node
471 */
472 private void disconnect(CordVtnNode node) {
473 checkNotNull(node);
474
475 if (!nodeStore.containsKey(node)) {
476 log.warn("Node {} does not exist", node.hostname());
477 return;
478 }
479
480 if (getOvsdbConnectionState(node)) {
481 OvsdbClientService ovsdbClient = getOvsdbClient(node);
482 ovsdbClient.disconnect();
483 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800484 }
485
486 /**
487 * Returns cordvtn node associated with a given OVSDB device.
488 *
489 * @param ovsdbId OVSDB device id
490 * @return cordvtn node, null if it fails to find the node
491 */
492 private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800493 return getNodes().stream()
494 .filter(node -> node.ovsdbId().equals(ovsdbId))
495 .findFirst().orElse(null);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800496 }
497
498 /**
499 * Returns cordvtn node associated with a given integration bridge.
500 *
501 * @param bridgeId device id of integration bridge
502 * @return cordvtn node, null if it fails to find the node
503 */
504 private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800505 return getNodes().stream()
506 .filter(node -> node.intBrId().equals(bridgeId))
507 .findFirst().orElse(null);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800508 }
509
510 /**
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800511 * Returns port name.
512 *
513 * @param port port
514 * @return port name
515 */
516 private String getPortName(Port port) {
517 return port.annotations().value("portName");
518 }
519
520 /**
Hyunsun Moon8539b042015-11-07 22:08:43 -0800521 * Returns OVSDB client for a given node.
522 *
523 * @param node cordvtn node
524 * @return OVSDB client, or null if it fails to get OVSDB client
525 */
526 private OvsdbClientService getOvsdbClient(CordVtnNode node) {
527 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700528
529 OvsdbClientService ovsdbClient = controller.getOvsdbClient(
Hyunsun Moon8539b042015-11-07 22:08:43 -0800530 new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700531 if (ovsdbClient == null) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800532 log.debug("Couldn't find OVSDB client for {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700533 }
534 return ovsdbClient;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700535 }
536
Hyunsun Moon8539b042015-11-07 22:08:43 -0800537 /**
538 * Creates an integration bridge for a given node.
539 *
540 * @param node cordvtn node
541 */
542 private void createIntegrationBridge(CordVtnNode node) {
543 if (checkIntegrationBridge(node)) {
544 return;
545 }
546
Hyunsun Moon523d9762015-10-19 12:38:21 -0700547 List<ControllerInfo> controllers = new ArrayList<>();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800548 Sets.newHashSet(clusterService.getNodes()).stream()
Hyunsun Moon523d9762015-10-19 12:38:21 -0700549 .forEach(controller -> {
550 ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
551 controllers.add(ctrlInfo);
552 });
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800553
Hyunsun Moon8539b042015-11-07 22:08:43 -0800554 String dpid = node.intBrId().toString().substring(DPID_BEGIN);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700555
Hyunsun Moon523d9762015-10-19 12:38:21 -0700556 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800557 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700558 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800559 bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
Hyunsun Moond772f342015-10-28 20:28:16 -0700560 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800561 log.warn("Failed to create integration bridge on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700562 }
563 }
564
Hyunsun Moon8539b042015-11-07 22:08:43 -0800565 /**
566 * Creates tunnel interface to the integration bridge for a given node.
567 *
568 * @param node cordvtn node
569 */
570 private void createTunnelInterface(CordVtnNode node) {
571 if (checkTunnelInterface(node)) {
572 return;
573 }
574
Hyunsun Moond772f342015-10-28 20:28:16 -0700575 DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
576 for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
577 optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
578 }
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800579
580 TunnelDescription description = new DefaultTunnelDescription(
581 null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
582 optionBuilder.build());
583
Hyunsun Moond772f342015-10-28 20:28:16 -0700584 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800585 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700586 TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800587 tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
Hyunsun Moond772f342015-10-28 20:28:16 -0700588 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800589 log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700590 }
591 }
592
Hyunsun Moon8539b042015-11-07 22:08:43 -0800593 /**
594 * Checks if integration bridge exists and available.
595 *
596 * @param node cordvtn node
597 * @return true if the bridge is available, false otherwise
598 */
599 private boolean checkIntegrationBridge(CordVtnNode node) {
600 return (deviceService.getDevice(node.intBrId()) != null
601 && deviceService.isAvailable(node.intBrId()));
602 }
603
604 /**
605 * Checks if tunnel interface exists.
606 *
607 * @param node cordvtn node
608 * @return true if the interface exists, false otherwise
609 */
610 private boolean checkTunnelInterface(CordVtnNode node) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800611 return deviceService.getPorts(node.intBrId())
612 .stream()
613 .filter(p -> getPortName(p).contains(DEFAULT_TUNNEL)
614 && p.isEnabled())
615 .findAny().isPresent();
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800616 }
617
618 /**
619 * Checks if physical interface exists.
620 *
621 * @param node cordvtn node
622 * @return true if the interface exists, false otherwise
623 */
624 private boolean checkPhyInterface(CordVtnNode node) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800625 return deviceService.getPorts(node.intBrId())
626 .stream()
627 .filter(p -> getPortName(p).contains(node.phyPortName())
628 && p.isEnabled())
629 .findAny().isPresent();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800630 }
631
632 /**
633 * Returns remote ip address for tunneling.
634 *
635 * @param bridgeId device id
636 * @return ip address, null if no such device exists
637 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800638 private Ip4Address getRemoteIp(DeviceId bridgeId) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800639 CordVtnNode node = getNodeByBridgeId(bridgeId);
640 if (node != null) {
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800641 return node.localIp().getIp4Address();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800642 } else {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800643 log.debug("Couldn't find node information for {}", bridgeId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800644 return null;
645 }
646 }
647
648 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800649 * Returns OpenStack port associated with a given host.
650 *
651 * @param host host
652 * @return OpenStack port, or null if no port has been found
653 */
654 private OpenstackPort getOpenstackPortByHost(Host host) {
655 Port port = deviceService.getPort(host.location().deviceId(),
656 host.location().port());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800657 if (port == null) {
658 log.debug("Failed to get port for {}", host.id());
659 return null;
660 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800661 return openstackService.port(port);
662 }
663
664 /**
665 * Returns OpenStack network associated with a given host.
666 *
667 * @param host host
668 * @return OpenStack network, or null if no network has been found
669 */
670 private OpenstackNetwork getOpenstackNetworkByHost(Host host) {
671 OpenstackPort vPort = getOpenstackPortByHost(host);
672 if (vPort != null) {
673 return openstackService.network(vPort.networkId());
674 } else {
675 return null;
676 }
677 }
678
679 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800680 * Returns hosts associated with a given OpenStack network.
681 *
682 * @param vNet openstack network
683 * @return set of hosts
684 */
685 private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
686 checkNotNull(vNet);
687
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800688 Set<Host> hosts = openstackService.ports(vNet.id()).stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800689 .filter(port -> port.deviceOwner().contains("compute"))
690 .map(port -> hostService.getHostsByMac(port.macAddress())
691 .stream()
692 .findFirst()
693 .orElse(null))
694 .collect(Collectors.toSet());
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800695
696 hosts.remove(null);
697 return hosts;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800698 }
699
700 /**
701 * Returns host IP assigned by OpenStack.
702 *
703 * @param host host
704 * @return IPv4 prefix, or null if it fails to get IP from OpenStack
705 */
706 private IpAddress getHostIpFromOpenstack(Host host) {
707 OpenstackPort vPort = getOpenstackPortByHost(host);
708
709 if (vPort == null || vPort.fixedIps().isEmpty()) {
710 log.error("Failed to get VM IP for {}", host.id());
711 return null;
712 }
713 // Assumes there's only one fixed IP is assigned to a port
714 return (Ip4Address) vPort.fixedIps().values()
715 .stream()
716 .findFirst()
717 .orElse(null);
718 }
719
720 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800721 * Returns port name with OpenStack port information.
722 *
723 * @param vPort OpenStack port
724 * @return port name
725 */
726 private String getPortName(OpenstackPort vPort) {
727 checkNotNull(vPort);
728 return VPORT_PREFIX + vPort.id().substring(0, 10);
729 }
730
731 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800732 * Returns if the host is VM or not.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800733 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800734 * @param host host
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800735 * @return true if the host is a VM.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800736 */
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800737 private boolean isVm(Host host) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800738 Port port = deviceService.getPort(host.location().deviceId(),
739 host.location().port());
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800740 return getPortName(port).contains(VPORT_PREFIX);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800741 }
742
743 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800744 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800745 *
746 * @param serviceId service id
747 * @return cord service, or null if it fails to get network from OpenStack
748 */
749 private CordService getCordService(CordServiceId serviceId) {
750 OpenstackNetwork vNet = openstackService.network(serviceId.id());
751 if (vNet == null) {
752 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
753 return null;
754 }
755
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800756 OpenstackSubnet subnet = vNet.subnets().stream()
757 .findFirst()
758 .orElse(null);
759 if (subnet == null) {
760 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
761 return null;
762 }
763
764 Set<CordServiceId> tServices = Sets.newHashSet();
765 // TODO get tenant services from XOS
766
767 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
768 .stream()
769 .collect(Collectors.toMap(host -> host,
770 host -> getRemoteIp(host.location().deviceId())));
771
772 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800773 }
774
775 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800776 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800777 *
778 * @param vNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800779 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800780 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800781 private CordService getCordService(OpenstackNetwork vNet) {
782 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800783
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800784 CordServiceId serviceId = CordServiceId.of(vNet.id());
785 OpenstackSubnet subnet = vNet.subnets().stream()
786 .findFirst()
787 .orElse(null);
788 if (subnet == null) {
789 log.warn("Couldn't find OpenStack subnet for service {}", serviceId);
790 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800791 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800792
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800793 Set<CordServiceId> tServices = Sets.newHashSet();
794 // TODO get tenant services from XOS
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800795
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800796 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
797 .stream()
798 .collect(Collectors.toMap(host -> host,
799 host -> getRemoteIp(host.location().deviceId())));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800800
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800801 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800802 }
803
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700804 private class InternalDeviceListener implements DeviceListener {
805
806 @Override
807 public void event(DeviceEvent event) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800808
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700809 Device device = event.subject();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800810 ConnectionHandler<Device> handler =
811 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700812
813 switch (event.type()) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800814 case PORT_ADDED:
815 eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
Hyunsun Moon2b530322015-09-23 13:24:35 -0700816 break;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800817 case PORT_UPDATED:
818 if (!event.port().isEnabled()) {
819 eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
820 }
821 break;
822 case DEVICE_ADDED:
Hyunsun Moon2b530322015-09-23 13:24:35 -0700823 case DEVICE_AVAILABILITY_CHANGED:
Hyunsun Moon523d9762015-10-19 12:38:21 -0700824 if (deviceService.isAvailable(device.id())) {
825 eventExecutor.submit(() -> handler.connected(device));
826 } else {
827 eventExecutor.submit(() -> handler.disconnected(device));
828 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700829 break;
830 default:
831 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700832 }
833 }
834 }
835
836 private class InternalHostListener implements HostListener {
837
838 @Override
839 public void event(HostEvent event) {
840 Host vm = event.subject();
841
842 switch (event.type()) {
843 case HOST_ADDED:
844 eventExecutor.submit(() -> vmHandler.connected(vm));
845 break;
846 case HOST_REMOVED:
847 eventExecutor.submit(() -> vmHandler.disconnected(vm));
848 break;
849 default:
850 break;
851 }
852 }
853 }
854
Hyunsun Moon2b530322015-09-23 13:24:35 -0700855 private class OvsdbHandler implements ConnectionHandler<Device> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700856
857 @Override
858 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800859 CordVtnNode node = getNodeByOvsdbId(device.id());
860 if (node != null) {
861 setNodeState(node, checkNodeState(node));
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800862 } else {
863 log.debug("Unregistered device {} connected, ignore it.", device.id());
Hyunsun Moon523d9762015-10-19 12:38:21 -0700864 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700865 }
866
867 @Override
868 public void disconnected(Device device) {
Hyunsun Moonba225722015-12-10 13:14:05 -0800869 if (!deviceService.isAvailable(device.id())) {
870 adminService.removeDevice(device.id());
871 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700872 }
873 }
874
875 private class BridgeHandler implements ConnectionHandler<Device> {
876
877 @Override
878 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800879 CordVtnNode node = getNodeByBridgeId(device.id());
880 if (node != null) {
881 setNodeState(node, checkNodeState(node));
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800882 } else {
883 log.debug("Unregistered device {} connected, ignore it.", device.id());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700884 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700885 }
886
887 @Override
888 public void disconnected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800889 CordVtnNode node = getNodeByBridgeId(device.id());
890 if (node != null) {
891 log.info("Integration Bridge is disconnected from {}", node.hostname());
892 setNodeState(node, NodeState.INCOMPLETE);
893 }
894 }
895
896 /**
897 * Handles port added situation.
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800898 * If the added port is tunnel or physical port, proceed remaining node
899 * initialization. Otherwise, do nothing.
Hyunsun Moon8539b042015-11-07 22:08:43 -0800900 *
901 * @param port port
902 */
903 public void portAdded(Port port) {
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800904 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
905 if (node == null) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800906 return;
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800907 } else {
908 log.debug("Port {} added to unregistered device, ignore it.", getPortName(port));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800909 }
910
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800911 // TODO add host by updating network config
912 String portName = getPortName(port);
913 if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) {
914 return;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800915 }
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800916
917 log.info("Port {} is added to {}", portName, node.hostname());
918 setNodeState(node, checkNodeState(node));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800919 }
920
921 /**
922 * Handles port removed situation.
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800923 * If the removed port is tunnel or physical port, proceed remaining node
924 * initialization.Others, do nothing.
Hyunsun Moon8539b042015-11-07 22:08:43 -0800925 *
926 * @param port port
927 */
928 public void portRemoved(Port port) {
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800929 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
930 if (node == null) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800931 return;
932 }
933
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800934 // TODO remove host by updating network config
935 String portName = getPortName(port);
936 if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) {
937 return;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800938 }
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800939
940 log.info("Port {} is removed from {}", portName, node.hostname());
941 setNodeState(node, NodeState.INCOMPLETE);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700942 }
943 }
944
Hyunsun Moon2b530322015-09-23 13:24:35 -0700945 private class VmHandler implements ConnectionHandler<Host> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700946
947 @Override
948 public void connected(Host host) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800949 // TODO remove check VM here after applying network config host provider
950 if (!isVm(host)) {
Hyunsun Moonbe8edcb2016-01-12 10:13:00 -0800951 log.debug("Host {} is not a VM, ignore it.", host.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800952 return;
953 }
954
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800955 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800956 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moonbe8edcb2016-01-12 10:13:00 -0800957 log.debug("VM {} is detected unknown or incomplete device, ignore it.", host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800958 return;
959 }
960
961 OpenstackNetwork vNet = getOpenstackNetworkByHost(host);
962 if (vNet == null) {
Hyunsun Moonbe8edcb2016-01-12 10:13:00 -0800963 log.debug("Failed to get OpenStack network for VM {}, ignore it.", host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800964 return;
965 }
966
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800967 // TODO host ip should be set in host information after applying network config host provider
968 IpAddress hostIp = getHostIpFromOpenstack(host);
969 if (hostIp == null) {
Hyunsun Moonbe8edcb2016-01-12 10:13:00 -0800970 log.debug("Failed to get host IP of {}, ignore it.", host.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800971 return;
972 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800973
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800974 log.info("VM {} is detected", host.id());
975 hostNetMap.put(host.id(), vNet);
976
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800977 CordService service = getCordService(vNet);
978 if (service != null) {
979 // TODO check if the service needs an update on its group buckets after done CORD-433
980 ruleInstaller.updateServiceGroup(service);
981 arpProxy.addServiceIp(service.serviceIp());
982 }
983
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800984 ruleInstaller.populateBasicConnectionRules(
985 host,
986 hostIp,
987 checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
988 vNet);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700989 }
990
991 @Override
992 public void disconnected(Host host) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800993 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800994 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800995 // do nothing for the host on unregistered or unprepared device
996 return;
997 }
998
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800999 OpenstackNetwork vNet = hostNetMap.get(host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001000 if (vNet == null) {
1001 return;
1002 }
1003
Hyunsun Moon1f145552015-10-08 22:25:30 -07001004 log.info("VM {} is vanished", host.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001005 ruleInstaller.removeBasicConnectionRules(host);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001006
Hyunsun Moon4161e6f2016-01-07 01:32:31 -08001007 CordService service = getCordService(vNet);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -08001008 if (service != null) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -08001009 // TODO check if the service needs an update on its group buckets after done CORD-433
Hyunsun Moon4161e6f2016-01-07 01:32:31 -08001010 ruleInstaller.updateServiceGroup(service);
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -08001011
1012 if (getHostsWithOpenstackNetwork(vNet).isEmpty()) {
1013 arpProxy.removeServiceIp(service.serviceIp());
1014 }
Hyunsun Moon4161e6f2016-01-07 01:32:31 -08001015 }
1016
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001017 hostNetMap.remove(host.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001018 }
1019 }
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -08001020
1021 private class InternalPacketProcessor implements PacketProcessor {
1022
1023 @Override
1024 public void process(PacketContext context) {
1025 if (context.isHandled()) {
1026 return;
1027 }
1028
1029 Ethernet ethPacket = context.inPacket().parsed();
1030 if (ethPacket == null) {
1031 return;
1032 }
1033
1034 if (ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
1035 return;
1036 }
1037
1038 arpProxy.processArpPacket(context, ethPacket);
1039 }
1040 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001041}