blob: 127c7c99ad31886ea11cd399f3c5dee80515ad15 [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 Moonc71231d2015-12-16 20:53:23 -080026import org.onlab.packet.Ip4Address;
Hyunsun Moond772f342015-10-28 20:28:16 -070027import org.onlab.util.ItemNotFoundException;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080028import org.onlab.packet.IpAddress;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070029import org.onlab.util.KryoNamespace;
Hyunsun Moon1f145552015-10-08 22:25:30 -070030import org.onosproject.cluster.ClusterService;
31import org.onosproject.core.ApplicationId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070032import org.onosproject.core.CoreService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080033import org.onosproject.mastership.MastershipService;
Hyunsun Moond772f342015-10-28 20:28:16 -070034import org.onosproject.net.DefaultAnnotations;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070035import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Host;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080038import org.onosproject.net.HostId;
Hyunsun Moon8539b042015-11-07 22:08:43 -080039import org.onosproject.net.Port;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080040import org.onosproject.net.PortNumber;
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 Moon9f0814b2015-11-04 17:34:35 -080059import org.onosproject.openstackswitching.OpenstackNetwork;
60import org.onosproject.openstackswitching.OpenstackPort;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080061import org.onosproject.openstackswitching.OpenstackSubnet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080062import org.onosproject.openstackswitching.OpenstackSwitchingService;
Hyunsun Moon1f145552015-10-08 22:25:30 -070063import org.onosproject.ovsdb.controller.OvsdbClientService;
64import org.onosproject.ovsdb.controller.OvsdbController;
65import org.onosproject.ovsdb.controller.OvsdbNodeId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070066import org.onosproject.store.serializers.KryoNamespaces;
Hyunsun Moon1f145552015-10-08 22:25:30 -070067import org.onosproject.store.service.ConsistentMap;
68import org.onosproject.store.service.Serializer;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070069import org.onosproject.store.service.StorageService;
70import org.slf4j.Logger;
71
Hyunsun Moon1f145552015-10-08 22:25:30 -070072import java.util.ArrayList;
73import java.util.HashMap;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070074import java.util.List;
Hyunsun Moon1f145552015-10-08 22:25:30 -070075import java.util.Map;
Hyunsun Moon523d9762015-10-19 12:38:21 -070076import java.util.NoSuchElementException;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080077import java.util.Objects;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080078import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070079import java.util.concurrent.ExecutorService;
80import java.util.concurrent.Executors;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080081import java.util.stream.Collectors;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070082
Hyunsun Moon1f145552015-10-08 22:25:30 -070083import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070084import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon2b530322015-09-23 13:24:35 -070085import static org.onosproject.net.Device.Type.SWITCH;
Hyunsun Moond772f342015-10-28 20:28:16 -070086import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070087import static org.slf4j.LoggerFactory.getLogger;
88
89/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080090 * Provisions virtual tenant networks with service chaining capability
91 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070092 */
93@Component(immediate = true)
94@Service
95public class CordVtn implements CordVtnService {
96
97 protected final Logger log = getLogger(getClass());
98
Hyunsun Moon2b530322015-09-23 13:24:35 -070099 private static final int NUM_THREADS = 1;
100 private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
101 .register(KryoNamespaces.API)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800102 .register(CordVtnNode.class)
103 .register(NodeState.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800104 private static final String DEFAULT_BRIDGE = "br-int";
105 private static final String VPORT_PREFIX = "tap";
Hyunsun Moon523d9762015-10-19 12:38:21 -0700106 private static final String DEFAULT_TUNNEL = "vxlan";
107 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
Hyunsun Moon1f145552015-10-08 22:25:30 -0700108 {
109 put("key", "flow");
Hyunsun Moon1f145552015-10-08 22:25:30 -0700110 put("remote_ip", "flow");
111 }
112 };
113 private static final int DPID_BEGIN = 3;
114 private static final int OFPORT = 6653;
Hyunsun Moon2b530322015-09-23 13:24:35 -0700115
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected CoreService coreService;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected StorageService storageService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700123 protected DeviceService deviceService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected HostService hostService;
127
Hyunsun Moon1f145552015-10-08 22:25:30 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond772f342015-10-28 20:28:16 -0700129 protected DriverService driverService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800132 protected DeviceAdminService adminService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800135 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1f145552015-10-08 22:25:30 -0700138 protected OvsdbController controller;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected ClusterService clusterService;
142
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800144 protected MastershipService mastershipService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected GroupService groupService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800150 protected OpenstackSwitchingService openstackService;
151
Hyunsun Moon2b530322015-09-23 13:24:35 -0700152 private final ExecutorService eventExecutor = Executors
153 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700154
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700155 private final DeviceListener deviceListener = new InternalDeviceListener();
156 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700157
158 private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700159 private final BridgeHandler bridgeHandler = new BridgeHandler();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700160 private final VmHandler vmHandler = new VmHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700161
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800162 private ApplicationId appId;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800163 private ConsistentMap<CordVtnNode, NodeState> nodeStore;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800164 private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800165 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800166
167 private enum NodeState {
168
169 INIT {
170 @Override
171 public void process(CordVtn cordVtn, CordVtnNode node) {
172 cordVtn.connect(node);
173 }
174 },
175 OVSDB_CONNECTED {
176 @Override
177 public void process(CordVtn cordVtn, CordVtnNode node) {
178 if (!cordVtn.getOvsdbConnectionState(node)) {
179 cordVtn.connect(node);
180 } else {
181 cordVtn.createIntegrationBridge(node);
182 }
183 }
184 },
185 BRIDGE_CREATED {
186 @Override
187 public void process(CordVtn cordVtn, CordVtnNode node) {
188 if (!cordVtn.getOvsdbConnectionState(node)) {
189 cordVtn.connect(node);
190 } else {
191 cordVtn.createTunnelInterface(node);
192 }
193 }
194 },
195 COMPLETE {
196 @Override
197 public void process(CordVtn cordVtn, CordVtnNode node) {
198 cordVtn.postInit(node);
199 }
200 },
201 INCOMPLETE {
202 @Override
203 public void process(CordVtn cordVtn, CordVtnNode node) {
204 }
205 };
206
207 public abstract void process(CordVtn cordVtn, CordVtnNode node);
208 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700209
210 @Activate
211 protected void activate() {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800212 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moon8539b042015-11-07 22:08:43 -0800213 nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
Hyunsun Moon1f145552015-10-08 22:25:30 -0700214 .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700215 .withName("cordvtn-nodestore")
Hyunsun Moon1f145552015-10-08 22:25:30 -0700216 .withApplicationId(appId)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700217 .build();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700218
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800219 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
220 deviceService,
221 driverService,
222 groupService,
223 mastershipService,
224 DEFAULT_TUNNEL);
225
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700226 deviceService.addListener(deviceListener);
227 hostService.addListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700228
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700229 log.info("Started");
230 }
231
232 @Deactivate
233 protected void deactivate() {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700234 deviceService.removeListener(deviceListener);
235 hostService.removeListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700236
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700237 eventExecutor.shutdown();
Hyunsun Moon1f145552015-10-08 22:25:30 -0700238 nodeStore.clear();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700239
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700240 log.info("Stopped");
241 }
242
243 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800244 public void addNode(CordVtnNode node) {
245 checkNotNull(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700246
Hyunsun Moon8539b042015-11-07 22:08:43 -0800247 nodeStore.putIfAbsent(node, checkNodeState(node));
248 initNode(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700249 }
250
251 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800252 public void deleteNode(CordVtnNode node) {
253 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700254
Hyunsun Moon8539b042015-11-07 22:08:43 -0800255 if (getOvsdbConnectionState(node)) {
256 disconnect(node);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700257 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700258
Hyunsun Moon8539b042015-11-07 22:08:43 -0800259 nodeStore.remove(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700260 }
261
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700262 @Override
263 public int getNodeCount() {
264 return nodeStore.size();
265 }
266
267 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800268 public List<CordVtnNode> getNodes() {
269 List<CordVtnNode> nodes = new ArrayList<>();
270 nodes.addAll(nodeStore.keySet());
271 return nodes;
272 }
273
274 @Override
275 public void initNode(CordVtnNode node) {
276 checkNotNull(node);
277
278 if (!nodeStore.containsKey(node)) {
279 log.warn("Node {} does not exist, add node first", node.hostname());
280 return;
281 }
282
Hyunsun Moonbaf70542015-12-16 14:29:36 -0800283 NodeState state = checkNodeState(node);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800284 state.process(this, node);
285 }
286
287 @Override
288 public boolean getNodeInitState(CordVtnNode node) {
289 checkNotNull(node);
290
291 NodeState state = getNodeState(node);
292 return state != null && state.equals(NodeState.COMPLETE);
293 }
294
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800295 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800296 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
297 CordService tService = getCordService(tServiceId);
298 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800299
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800300 if (tService == null || pService == null) {
301 log.error("Failed to create CordService for {}", tServiceId.id());
302 return;
303 }
304
305 ruleInstaller.populateServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800306 }
307
308 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800309 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
310 CordService tService = getCordService(tServiceId);
311 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800312
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800313 if (tService == null || pService == null) {
314 log.error("Failed to create CordService for {}", tServiceId.id());
315 return;
316 }
317
318 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800319 }
320
Hyunsun Moon8539b042015-11-07 22:08:43 -0800321 /**
322 * Returns state of a given cordvtn node.
323 *
324 * @param node cordvtn node
325 * @return node state, or null if no such node exists
326 */
327 private NodeState getNodeState(CordVtnNode node) {
328 checkNotNull(node);
329
330 try {
331 return nodeStore.get(node).value();
332 } catch (NullPointerException e) {
333 log.error("Failed to get state of {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700334 return null;
335 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700336 }
337
Hyunsun Moon8539b042015-11-07 22:08:43 -0800338 /**
339 * Sets a new state for a given cordvtn node.
340 *
341 * @param node cordvtn node
342 * @param newState new node state
343 */
344 private void setNodeState(CordVtnNode node, NodeState newState) {
345 checkNotNull(node);
346
347 log.info("Changed {} state: {}", node.hostname(), newState.toString());
348
349 nodeStore.put(node, newState);
350 newState.process(this, node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700351 }
352
Hyunsun Moon8539b042015-11-07 22:08:43 -0800353 /**
354 * Checks current state of a given cordvtn node and returns it.
355 *
356 * @param node cordvtn node
357 * @return node state
358 */
359 private NodeState checkNodeState(CordVtnNode node) {
360 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700361
Hyunsun Moon8539b042015-11-07 22:08:43 -0800362 if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
363 return NodeState.COMPLETE;
364 } else if (checkIntegrationBridge(node)) {
365 return NodeState.BRIDGE_CREATED;
366 } else if (getOvsdbConnectionState(node)) {
367 return NodeState.OVSDB_CONNECTED;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700368 } else {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800369 return NodeState.INIT;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700370 }
371 }
372
Hyunsun Moon8539b042015-11-07 22:08:43 -0800373 /**
374 * Performs tasks after node initialization.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800375 * First disconnect unnecessary OVSDB connection and then installs flow rules
376 * for existing VMs if there are any.
Hyunsun Moon8539b042015-11-07 22:08:43 -0800377 *
378 * @param node cordvtn node
379 */
380 private void postInit(CordVtnNode node) {
381 disconnect(node);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800382
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800383 ruleInstaller.init(node.intBrId(), getTunnelPort(node.intBrId()));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800384 hostService.getConnectedHosts(node.intBrId())
385 .stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800386 .forEach(vmHandler::connected);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800387
388 log.info("Finished initializing {}", node.hostname());
Hyunsun Moon8539b042015-11-07 22:08:43 -0800389 }
390
391 /**
392 * Returns connection state of OVSDB server for a given node.
393 *
394 * @param node cordvtn node
395 * @return true if it is connected, false otherwise
396 */
397 private boolean getOvsdbConnectionState(CordVtnNode node) {
398 checkNotNull(node);
399
400 OvsdbClientService ovsdbClient = getOvsdbClient(node);
401 return deviceService.isAvailable(node.ovsdbId()) &&
402 ovsdbClient != null && ovsdbClient.isConnected();
403 }
404
405 /**
406 * Connects to OVSDB server for a given node.
407 *
408 * @param node cordvtn node
409 */
410 private void connect(CordVtnNode node) {
411 checkNotNull(node);
412
413 if (!nodeStore.containsKey(node)) {
414 log.warn("Node {} does not exist", node.hostname());
415 return;
416 }
417
418 if (!getOvsdbConnectionState(node)) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800419 controller.connect(node.ovsdbIp(), node.ovsdbPort());
420 }
421 }
422
423 /**
424 * Disconnects OVSDB server for a given node.
425 *
426 * @param node cordvtn node
427 */
428 private void disconnect(CordVtnNode node) {
429 checkNotNull(node);
430
431 if (!nodeStore.containsKey(node)) {
432 log.warn("Node {} does not exist", node.hostname());
433 return;
434 }
435
436 if (getOvsdbConnectionState(node)) {
437 OvsdbClientService ovsdbClient = getOvsdbClient(node);
438 ovsdbClient.disconnect();
439 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800440 }
441
442 /**
443 * Returns cordvtn node associated with a given OVSDB device.
444 *
445 * @param ovsdbId OVSDB device id
446 * @return cordvtn node, null if it fails to find the node
447 */
448 private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) {
449 try {
450 return getNodes().stream()
451 .filter(node -> node.ovsdbId().equals(ovsdbId))
452 .findFirst().get();
453 } catch (NoSuchElementException e) {
454 log.debug("Couldn't find node information for {}", ovsdbId);
455 return null;
456 }
457 }
458
459 /**
460 * Returns cordvtn node associated with a given integration bridge.
461 *
462 * @param bridgeId device id of integration bridge
463 * @return cordvtn node, null if it fails to find the node
464 */
465 private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) {
466 try {
467 return getNodes().stream()
468 .filter(node -> node.intBrId().equals(bridgeId))
469 .findFirst().get();
470 } catch (NoSuchElementException e) {
471 log.debug("Couldn't find node information for {}", bridgeId);
472 return null;
473 }
474 }
475
476 /**
477 * Returns OVSDB client for a given node.
478 *
479 * @param node cordvtn node
480 * @return OVSDB client, or null if it fails to get OVSDB client
481 */
482 private OvsdbClientService getOvsdbClient(CordVtnNode node) {
483 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700484
485 OvsdbClientService ovsdbClient = controller.getOvsdbClient(
Hyunsun Moon8539b042015-11-07 22:08:43 -0800486 new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700487 if (ovsdbClient == null) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800488 log.debug("Couldn't find OVSDB client for {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700489 }
490 return ovsdbClient;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700491 }
492
Hyunsun Moon8539b042015-11-07 22:08:43 -0800493 /**
494 * Creates an integration bridge for a given node.
495 *
496 * @param node cordvtn node
497 */
498 private void createIntegrationBridge(CordVtnNode node) {
499 if (checkIntegrationBridge(node)) {
500 return;
501 }
502
Hyunsun Moon523d9762015-10-19 12:38:21 -0700503 List<ControllerInfo> controllers = new ArrayList<>();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800504 Sets.newHashSet(clusterService.getNodes()).stream()
Hyunsun Moon523d9762015-10-19 12:38:21 -0700505 .forEach(controller -> {
506 ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
507 controllers.add(ctrlInfo);
508 });
Hyunsun Moon8539b042015-11-07 22:08:43 -0800509 String dpid = node.intBrId().toString().substring(DPID_BEGIN);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700510
Hyunsun Moon523d9762015-10-19 12:38:21 -0700511 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800512 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700513 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800514 bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
Hyunsun Moond772f342015-10-28 20:28:16 -0700515 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800516 log.warn("Failed to create integration bridge on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700517 }
518 }
519
Hyunsun Moon8539b042015-11-07 22:08:43 -0800520 /**
521 * Creates tunnel interface to the integration bridge for a given node.
522 *
523 * @param node cordvtn node
524 */
525 private void createTunnelInterface(CordVtnNode node) {
526 if (checkTunnelInterface(node)) {
527 return;
528 }
529
Hyunsun Moond772f342015-10-28 20:28:16 -0700530 DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
531 for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
532 optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
533 }
534 TunnelDescription description =
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800535 new DefaultTunnelDescription(null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
Hyunsun Moond772f342015-10-28 20:28:16 -0700536 optionBuilder.build());
537 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800538 DriverHandler handler = driverService.createHandler(node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700539 TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800540 tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
Hyunsun Moond772f342015-10-28 20:28:16 -0700541 } catch (ItemNotFoundException e) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800542 log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
Hyunsun Moond772f342015-10-28 20:28:16 -0700543 }
544 }
545
Hyunsun Moon8539b042015-11-07 22:08:43 -0800546 /**
547 * Checks if integration bridge exists and available.
548 *
549 * @param node cordvtn node
550 * @return true if the bridge is available, false otherwise
551 */
552 private boolean checkIntegrationBridge(CordVtnNode node) {
553 return (deviceService.getDevice(node.intBrId()) != null
554 && deviceService.isAvailable(node.intBrId()));
555 }
556
557 /**
558 * Checks if tunnel interface exists.
559 *
560 * @param node cordvtn node
561 * @return true if the interface exists, false otherwise
562 */
563 private boolean checkTunnelInterface(CordVtnNode node) {
Hyunsun Moond772f342015-10-28 20:28:16 -0700564 try {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800565 deviceService.getPorts(node.intBrId())
566 .stream()
567 .filter(p -> p.annotations().value("portName").contains(DEFAULT_TUNNEL)
568 && p.isEnabled())
Hyunsun Moond772f342015-10-28 20:28:16 -0700569 .findAny().get();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800570 return true;
571 } catch (NoSuchElementException e) {
Hyunsun Moon523d9762015-10-19 12:38:21 -0700572 return false;
573 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700574 }
575
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800576 /**
577 * Returns tunnel port of the device.
578 *
579 * @param bridgeId device id
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800580 * @return port number, null if no tunnel port exists on a given device
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800581 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800582 private PortNumber getTunnelPort(DeviceId bridgeId) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800583 try {
584 return deviceService.getPorts(bridgeId).stream()
585 .filter(p -> p.annotations().value("portName").contains(DEFAULT_TUNNEL)
586 && p.isEnabled())
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800587 .findFirst().get().number();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800588 } catch (NoSuchElementException e) {
589 return null;
590 }
591 }
592
593 /**
594 * Returns remote ip address for tunneling.
595 *
596 * @param bridgeId device id
597 * @return ip address, null if no such device exists
598 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800599 private Ip4Address getRemoteIp(DeviceId bridgeId) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800600 CordVtnNode node = getNodeByBridgeId(bridgeId);
601 if (node != null) {
602 // TODO get data plane IP for tunneling
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800603 return node.ovsdbIp().getIp4Address();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800604 } else {
605 return null;
606 }
607 }
608
609 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800610 * Returns OpenStack port associated with a given host.
611 *
612 * @param host host
613 * @return OpenStack port, or null if no port has been found
614 */
615 private OpenstackPort getOpenstackPortByHost(Host host) {
616 Port port = deviceService.getPort(host.location().deviceId(),
617 host.location().port());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800618 if (port == null) {
619 log.debug("Failed to get port for {}", host.id());
620 return null;
621 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800622 return openstackService.port(port);
623 }
624
625 /**
626 * Returns OpenStack network associated with a given host.
627 *
628 * @param host host
629 * @return OpenStack network, or null if no network has been found
630 */
631 private OpenstackNetwork getOpenstackNetworkByHost(Host host) {
632 OpenstackPort vPort = getOpenstackPortByHost(host);
633 if (vPort != null) {
634 return openstackService.network(vPort.networkId());
635 } else {
636 return null;
637 }
638 }
639
640 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800641 * Returns hosts associated with a given OpenStack network.
642 *
643 * @param vNet openstack network
644 * @return set of hosts
645 */
646 private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
647 checkNotNull(vNet);
648
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800649 Set<Host> hosts = openstackService.ports(vNet.id()).stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800650 .filter(port -> port.deviceOwner().contains("compute"))
651 .map(port -> hostService.getHostsByMac(port.macAddress())
652 .stream()
653 .findFirst()
654 .orElse(null))
655 .collect(Collectors.toSet());
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800656
657 hosts.remove(null);
658 return hosts;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800659 }
660
661 /**
662 * Returns host IP assigned by OpenStack.
663 *
664 * @param host host
665 * @return IPv4 prefix, or null if it fails to get IP from OpenStack
666 */
667 private IpAddress getHostIpFromOpenstack(Host host) {
668 OpenstackPort vPort = getOpenstackPortByHost(host);
669
670 if (vPort == null || vPort.fixedIps().isEmpty()) {
671 log.error("Failed to get VM IP for {}", host.id());
672 return null;
673 }
674 // Assumes there's only one fixed IP is assigned to a port
675 return (Ip4Address) vPort.fixedIps().values()
676 .stream()
677 .findFirst()
678 .orElse(null);
679 }
680
681 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800682 * Returns port name with OpenStack port information.
683 *
684 * @param vPort OpenStack port
685 * @return port name
686 */
687 private String getPortName(OpenstackPort vPort) {
688 checkNotNull(vPort);
689 return VPORT_PREFIX + vPort.id().substring(0, 10);
690 }
691
692 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800693 * Returns if the host is VM or not.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800694 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800695 * @param host host
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800696 * @return true if the host is a VM.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800697 */
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800698 private boolean isVm(Host host) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800699 Port port = deviceService.getPort(host.location().deviceId(),
700 host.location().port());
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800701 return port.annotations().value("portName").contains(VPORT_PREFIX);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800702 }
703
704 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800705 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800706 *
707 * @param serviceId service id
708 * @return cord service, or null if it fails to get network from OpenStack
709 */
710 private CordService getCordService(CordServiceId serviceId) {
711 OpenstackNetwork vNet = openstackService.network(serviceId.id());
712 if (vNet == null) {
713 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
714 return null;
715 }
716
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800717 OpenstackSubnet subnet = vNet.subnets().stream()
718 .findFirst()
719 .orElse(null);
720 if (subnet == null) {
721 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
722 return null;
723 }
724
725 Set<CordServiceId> tServices = Sets.newHashSet();
726 // TODO get tenant services from XOS
727
728 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
729 .stream()
730 .collect(Collectors.toMap(host -> host,
731 host -> getRemoteIp(host.location().deviceId())));
732
733 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800734 }
735
736 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800737 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800738 *
739 * @param vNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800740 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800741 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800742 private CordService getCordService(OpenstackNetwork vNet) {
743 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800744
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800745 CordServiceId serviceId = CordServiceId.of(vNet.id());
746 OpenstackSubnet subnet = vNet.subnets().stream()
747 .findFirst()
748 .orElse(null);
749 if (subnet == null) {
750 log.warn("Couldn't find OpenStack subnet for service {}", serviceId);
751 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800752 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800753
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800754 Set<CordServiceId> tServices = Sets.newHashSet();
755 // TODO get tenant services from XOS
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800756
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800757 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
758 .stream()
759 .collect(Collectors.toMap(host -> host,
760 host -> getRemoteIp(host.location().deviceId())));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800761
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800762 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800763 }
764
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700765 private class InternalDeviceListener implements DeviceListener {
766
767 @Override
768 public void event(DeviceEvent event) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800769
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700770 Device device = event.subject();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800771 ConnectionHandler<Device> handler =
772 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700773
774 switch (event.type()) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800775 case PORT_ADDED:
776 eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
Hyunsun Moon2b530322015-09-23 13:24:35 -0700777 break;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800778 case PORT_UPDATED:
779 if (!event.port().isEnabled()) {
780 eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
781 }
782 break;
783 case DEVICE_ADDED:
Hyunsun Moon2b530322015-09-23 13:24:35 -0700784 case DEVICE_AVAILABILITY_CHANGED:
Hyunsun Moon523d9762015-10-19 12:38:21 -0700785 if (deviceService.isAvailable(device.id())) {
786 eventExecutor.submit(() -> handler.connected(device));
787 } else {
788 eventExecutor.submit(() -> handler.disconnected(device));
789 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700790 break;
791 default:
792 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700793 }
794 }
795 }
796
797 private class InternalHostListener implements HostListener {
798
799 @Override
800 public void event(HostEvent event) {
801 Host vm = event.subject();
802
803 switch (event.type()) {
804 case HOST_ADDED:
805 eventExecutor.submit(() -> vmHandler.connected(vm));
806 break;
807 case HOST_REMOVED:
808 eventExecutor.submit(() -> vmHandler.disconnected(vm));
809 break;
810 default:
811 break;
812 }
813 }
814 }
815
Hyunsun Moon2b530322015-09-23 13:24:35 -0700816 private class OvsdbHandler implements ConnectionHandler<Device> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700817
818 @Override
819 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800820 CordVtnNode node = getNodeByOvsdbId(device.id());
821 if (node != null) {
822 setNodeState(node, checkNodeState(node));
Hyunsun Moon523d9762015-10-19 12:38:21 -0700823 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700824 }
825
826 @Override
827 public void disconnected(Device device) {
Hyunsun Moonba225722015-12-10 13:14:05 -0800828 if (!deviceService.isAvailable(device.id())) {
829 adminService.removeDevice(device.id());
830 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700831 }
832 }
833
834 private class BridgeHandler implements ConnectionHandler<Device> {
835
836 @Override
837 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800838 CordVtnNode node = getNodeByBridgeId(device.id());
839 if (node != null) {
840 setNodeState(node, checkNodeState(node));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700841 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700842 }
843
844 @Override
845 public void disconnected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800846 CordVtnNode node = getNodeByBridgeId(device.id());
847 if (node != null) {
848 log.info("Integration Bridge is disconnected from {}", node.hostname());
849 setNodeState(node, NodeState.INCOMPLETE);
850 }
851 }
852
853 /**
854 * Handles port added situation.
855 * If the added port is tunnel port, proceed remaining node initialization.
856 * Otherwise, do nothing.
857 *
858 * @param port port
859 */
860 public void portAdded(Port port) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800861 // TODO add host by updating network config
Hyunsun Moon8539b042015-11-07 22:08:43 -0800862 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
863 return;
864 }
865
866 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
867 if (node != null) {
868 setNodeState(node, checkNodeState(node));
869 }
870 }
871
872 /**
873 * Handles port removed situation.
874 * If the removed port is tunnel port, proceed remaining node initialization.
875 * Others, do nothing.
876 *
877 * @param port port
878 */
879 public void portRemoved(Port port) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800880 // TODO remove host by updating network config
Hyunsun Moon8539b042015-11-07 22:08:43 -0800881 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
882 return;
883 }
884
885 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
886 if (node != null) {
887 log.info("Tunnel interface is removed from {}", node.hostname());
888 setNodeState(node, NodeState.INCOMPLETE);
889 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700890 }
891 }
892
Hyunsun Moon2b530322015-09-23 13:24:35 -0700893 private class VmHandler implements ConnectionHandler<Host> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700894
895 @Override
896 public void connected(Host host) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800897 // TODO remove check VM here after applying network config host provider
898 if (!isVm(host)) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800899 return;
900 }
901
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800902 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800903 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800904 // do nothing for the host on unregistered or unprepared device
905 return;
906 }
907
908 OpenstackNetwork vNet = getOpenstackNetworkByHost(host);
909 if (vNet == null) {
910 return;
911 }
912
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800913 // TODO host ip should be set in host information after applying network config host provider
914 IpAddress hostIp = getHostIpFromOpenstack(host);
915 if (hostIp == null) {
916 log.error("Failed to get host IP of {}", host.id());
917 return;
918 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800919
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800920 log.info("VM {} is detected", host.id());
921 hostNetMap.put(host.id(), vNet);
922
923 ruleInstaller.populateBasicConnectionRules(
924 host,
925 hostIp,
926 checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
927 vNet);
928
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800929 CordService service = getCordService(vNet);
930 // TODO check if the service needs an update on its group buckets after done CORD-433
931 if (service != null) {
932 ruleInstaller.updateServiceGroup(service);
933 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700934 }
935
936 @Override
937 public void disconnected(Host host) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800938 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800939 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800940 // do nothing for the host on unregistered or unprepared device
941 return;
942 }
943
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800944 OpenstackNetwork vNet = hostNetMap.get(host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800945 if (vNet == null) {
946 return;
947 }
948
Hyunsun Moon1f145552015-10-08 22:25:30 -0700949 log.info("VM {} is vanished", host.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800950 ruleInstaller.removeBasicConnectionRules(host);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800951
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800952 CordService service = getCordService(vNet);
953 // TODO check if the service needs an update on its group buckets after done CORD-433
954 if (service != null) {
955 ruleInstaller.updateServiceGroup(service);
956 }
957
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800958 hostNetMap.remove(host.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700959 }
960 }
961}