blob: d119a5a103b9111158ed8b1356cbc86c3d00652e [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 Moonc71231d2015-12-16 20:53:23 -0800106 private static final String GWPORT_PREFIX = "qr-";
Hyunsun Moon523d9762015-10-19 12:38:21 -0700107 private static final String DEFAULT_TUNNEL = "vxlan";
108 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
Hyunsun Moon1f145552015-10-08 22:25:30 -0700109 {
110 put("key", "flow");
Hyunsun Moon1f145552015-10-08 22:25:30 -0700111 put("remote_ip", "flow");
112 }
113 };
114 private static final int DPID_BEGIN = 3;
115 private static final int OFPORT = 6653;
Hyunsun Moon2b530322015-09-23 13:24:35 -0700116
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected CoreService coreService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected StorageService storageService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700124 protected DeviceService deviceService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected HostService hostService;
128
Hyunsun Moon1f145552015-10-08 22:25:30 -0700129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond772f342015-10-28 20:28:16 -0700130 protected DriverService driverService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon8539b042015-11-07 22:08:43 -0800133 protected DeviceAdminService adminService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800136 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon1f145552015-10-08 22:25:30 -0700139 protected OvsdbController controller;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected ClusterService clusterService;
143
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800145 protected MastershipService mastershipService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 protected GroupService groupService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800151 protected OpenstackSwitchingService openstackService;
152
Hyunsun Moon2b530322015-09-23 13:24:35 -0700153 private final ExecutorService eventExecutor = Executors
154 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700155
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700156 private final DeviceListener deviceListener = new InternalDeviceListener();
157 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700158
159 private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700160 private final BridgeHandler bridgeHandler = new BridgeHandler();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700161 private final VmHandler vmHandler = new VmHandler();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700162
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800163 private ApplicationId appId;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800164 private ConsistentMap<CordVtnNode, NodeState> nodeStore;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800165 private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800166 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800167
168 private enum NodeState {
169
170 INIT {
171 @Override
172 public void process(CordVtn cordVtn, CordVtnNode node) {
173 cordVtn.connect(node);
174 }
175 },
176 OVSDB_CONNECTED {
177 @Override
178 public void process(CordVtn cordVtn, CordVtnNode node) {
179 if (!cordVtn.getOvsdbConnectionState(node)) {
180 cordVtn.connect(node);
181 } else {
182 cordVtn.createIntegrationBridge(node);
183 }
184 }
185 },
186 BRIDGE_CREATED {
187 @Override
188 public void process(CordVtn cordVtn, CordVtnNode node) {
189 if (!cordVtn.getOvsdbConnectionState(node)) {
190 cordVtn.connect(node);
191 } else {
192 cordVtn.createTunnelInterface(node);
193 }
194 }
195 },
196 COMPLETE {
197 @Override
198 public void process(CordVtn cordVtn, CordVtnNode node) {
199 cordVtn.postInit(node);
200 }
201 },
202 INCOMPLETE {
203 @Override
204 public void process(CordVtn cordVtn, CordVtnNode node) {
205 }
206 };
207
208 public abstract void process(CordVtn cordVtn, CordVtnNode node);
209 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700210
211 @Activate
212 protected void activate() {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800213 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moon8539b042015-11-07 22:08:43 -0800214 nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
Hyunsun Moon1f145552015-10-08 22:25:30 -0700215 .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700216 .withName("cordvtn-nodestore")
Hyunsun Moon1f145552015-10-08 22:25:30 -0700217 .withApplicationId(appId)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700218 .build();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700219
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800220 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
221 deviceService,
222 driverService,
223 groupService,
224 mastershipService,
225 DEFAULT_TUNNEL);
226
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700227 deviceService.addListener(deviceListener);
228 hostService.addListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700229
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700230 log.info("Started");
231 }
232
233 @Deactivate
234 protected void deactivate() {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700235 deviceService.removeListener(deviceListener);
236 hostService.removeListener(hostListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700237
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700238 eventExecutor.shutdown();
Hyunsun Moon1f145552015-10-08 22:25:30 -0700239 nodeStore.clear();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700240
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700241 log.info("Stopped");
242 }
243
244 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800245 public void addNode(CordVtnNode node) {
246 checkNotNull(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700247
Hyunsun Moon8539b042015-11-07 22:08:43 -0800248 nodeStore.putIfAbsent(node, checkNodeState(node));
249 initNode(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700250 }
251
252 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800253 public void deleteNode(CordVtnNode node) {
254 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700255
Hyunsun Moon8539b042015-11-07 22:08:43 -0800256 if (getOvsdbConnectionState(node)) {
257 disconnect(node);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700258 }
Hyunsun Moon523d9762015-10-19 12:38:21 -0700259
Hyunsun Moon8539b042015-11-07 22:08:43 -0800260 nodeStore.remove(node);
Hyunsun Moon523d9762015-10-19 12:38:21 -0700261 }
262
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700263 @Override
264 public int getNodeCount() {
265 return nodeStore.size();
266 }
267
268 @Override
Hyunsun Moon8539b042015-11-07 22:08:43 -0800269 public List<CordVtnNode> getNodes() {
270 List<CordVtnNode> nodes = new ArrayList<>();
271 nodes.addAll(nodeStore.keySet());
272 return nodes;
273 }
274
275 @Override
276 public void initNode(CordVtnNode node) {
277 checkNotNull(node);
278
279 if (!nodeStore.containsKey(node)) {
280 log.warn("Node {} does not exist, add node first", node.hostname());
281 return;
282 }
283
Hyunsun Moonbaf70542015-12-16 14:29:36 -0800284 NodeState state = checkNodeState(node);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800285 state.process(this, node);
286 }
287
288 @Override
289 public boolean getNodeInitState(CordVtnNode node) {
290 checkNotNull(node);
291
292 NodeState state = getNodeState(node);
293 return state != null && state.equals(NodeState.COMPLETE);
294 }
295
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800296 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800297 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
298 CordService tService = getCordService(tServiceId);
299 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800300
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800301 if (tService == null || pService == null) {
302 log.error("Failed to create CordService for {}", tServiceId.id());
303 return;
304 }
305
306 ruleInstaller.populateServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800307 }
308
309 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800310 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
311 CordService tService = getCordService(tServiceId);
312 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800313
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800314 if (tService == null || pService == null) {
315 log.error("Failed to create CordService for {}", tServiceId.id());
316 return;
317 }
318
319 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800320 }
321
Hyunsun Moon8539b042015-11-07 22:08:43 -0800322 /**
323 * Returns state of a given cordvtn node.
324 *
325 * @param node cordvtn node
326 * @return node state, or null if no such node exists
327 */
328 private NodeState getNodeState(CordVtnNode node) {
329 checkNotNull(node);
330
331 try {
332 return nodeStore.get(node).value();
333 } catch (NullPointerException e) {
334 log.error("Failed to get state of {}", node.hostname());
Hyunsun Moon1f145552015-10-08 22:25:30 -0700335 return null;
336 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700337 }
338
Hyunsun Moon8539b042015-11-07 22:08:43 -0800339 /**
340 * Sets a new state for a given cordvtn node.
341 *
342 * @param node cordvtn node
343 * @param newState new node state
344 */
345 private void setNodeState(CordVtnNode node, NodeState newState) {
346 checkNotNull(node);
347
348 log.info("Changed {} state: {}", node.hostname(), newState.toString());
349
350 nodeStore.put(node, newState);
351 newState.process(this, node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700352 }
353
Hyunsun Moon8539b042015-11-07 22:08:43 -0800354 /**
355 * Checks current state of a given cordvtn node and returns it.
356 *
357 * @param node cordvtn node
358 * @return node state
359 */
360 private NodeState checkNodeState(CordVtnNode node) {
361 checkNotNull(node);
Hyunsun Moon1f145552015-10-08 22:25:30 -0700362
Hyunsun Moon8539b042015-11-07 22:08:43 -0800363 if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
364 return NodeState.COMPLETE;
365 } else if (checkIntegrationBridge(node)) {
366 return NodeState.BRIDGE_CREATED;
367 } else if (getOvsdbConnectionState(node)) {
368 return NodeState.OVSDB_CONNECTED;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700369 } else {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800370 return NodeState.INIT;
Hyunsun Moon1f145552015-10-08 22:25:30 -0700371 }
372 }
373
Hyunsun Moon8539b042015-11-07 22:08:43 -0800374 /**
375 * Performs tasks after node initialization.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800376 * First disconnect unnecessary OVSDB connection and then installs flow rules
377 * for existing VMs if there are any.
Hyunsun Moon8539b042015-11-07 22:08:43 -0800378 *
379 * @param node cordvtn node
380 */
381 private void postInit(CordVtnNode node) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800382 log.info("Initializing {}", node.hostname());
Hyunsun Moon8539b042015-11-07 22:08:43 -0800383 disconnect(node);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800384
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800385 ruleInstaller.init(node.intBrId(), getTunnelPort(node.intBrId()));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800386 hostService.getConnectedHosts(node.intBrId())
387 .stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800388 .forEach(vmHandler::connected);
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
649 return openstackService.ports(vNet.id()).stream()
650 .filter(port -> port.deviceOwner().contains("compute"))
651 .map(port -> hostService.getHostsByMac(port.macAddress())
652 .stream()
653 .findFirst()
654 .orElse(null))
655 .collect(Collectors.toSet());
656 }
657
658 /**
659 * Returns host IP assigned by OpenStack.
660 *
661 * @param host host
662 * @return IPv4 prefix, or null if it fails to get IP from OpenStack
663 */
664 private IpAddress getHostIpFromOpenstack(Host host) {
665 OpenstackPort vPort = getOpenstackPortByHost(host);
666
667 if (vPort == null || vPort.fixedIps().isEmpty()) {
668 log.error("Failed to get VM IP for {}", host.id());
669 return null;
670 }
671 // Assumes there's only one fixed IP is assigned to a port
672 return (Ip4Address) vPort.fixedIps().values()
673 .stream()
674 .findFirst()
675 .orElse(null);
676 }
677
678 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800679 * Returns port name with OpenStack port information.
680 *
681 * @param vPort OpenStack port
682 * @return port name
683 */
684 private String getPortName(OpenstackPort vPort) {
685 checkNotNull(vPort);
686 return VPORT_PREFIX + vPort.id().substring(0, 10);
687 }
688
689 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800690 * Returns if the host is gateway interface.
691 * This codes should be removed after adding proxy arp for the gateway.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800692 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800693 * @param host host
694 * @return true if the host is gateway
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800695 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800696 private boolean isGateway(Host host) {
697 Port port = deviceService.getPort(host.location().deviceId(),
698 host.location().port());
699 return port.annotations().value("portName").contains(GWPORT_PREFIX);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800700 }
701
702 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800703 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800704 *
705 * @param serviceId service id
706 * @return cord service, or null if it fails to get network from OpenStack
707 */
708 private CordService getCordService(CordServiceId serviceId) {
709 OpenstackNetwork vNet = openstackService.network(serviceId.id());
710 if (vNet == null) {
711 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
712 return null;
713 }
714
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800715 OpenstackSubnet subnet = vNet.subnets().stream()
716 .findFirst()
717 .orElse(null);
718 if (subnet == null) {
719 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
720 return null;
721 }
722
723 Set<CordServiceId> tServices = Sets.newHashSet();
724 // TODO get tenant services from XOS
725
726 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
727 .stream()
728 .collect(Collectors.toMap(host -> host,
729 host -> getRemoteIp(host.location().deviceId())));
730
731 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800732 }
733
734 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800735 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800736 *
737 * @param vNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800738 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800739 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800740 private CordService getCordService(OpenstackNetwork vNet) {
741 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800742
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800743 CordServiceId serviceId = CordServiceId.of(vNet.id());
744 OpenstackSubnet subnet = vNet.subnets().stream()
745 .findFirst()
746 .orElse(null);
747 if (subnet == null) {
748 log.warn("Couldn't find OpenStack subnet for service {}", serviceId);
749 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800750 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800751
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800752 Set<CordServiceId> tServices = Sets.newHashSet();
753 // TODO get tenant services from XOS
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800754
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800755 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
756 .stream()
757 .collect(Collectors.toMap(host -> host,
758 host -> getRemoteIp(host.location().deviceId())));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800759
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800760 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800761 }
762
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700763 private class InternalDeviceListener implements DeviceListener {
764
765 @Override
766 public void event(DeviceEvent event) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800767
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700768 Device device = event.subject();
Hyunsun Moon8539b042015-11-07 22:08:43 -0800769 ConnectionHandler<Device> handler =
770 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700771
772 switch (event.type()) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800773 case PORT_ADDED:
774 eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
Hyunsun Moon2b530322015-09-23 13:24:35 -0700775 break;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800776 case PORT_UPDATED:
777 if (!event.port().isEnabled()) {
778 eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
779 }
780 break;
781 case DEVICE_ADDED:
Hyunsun Moon2b530322015-09-23 13:24:35 -0700782 case DEVICE_AVAILABILITY_CHANGED:
Hyunsun Moon523d9762015-10-19 12:38:21 -0700783 if (deviceService.isAvailable(device.id())) {
784 eventExecutor.submit(() -> handler.connected(device));
785 } else {
786 eventExecutor.submit(() -> handler.disconnected(device));
787 }
Hyunsun Moon2b530322015-09-23 13:24:35 -0700788 break;
789 default:
790 break;
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700791 }
792 }
793 }
794
795 private class InternalHostListener implements HostListener {
796
797 @Override
798 public void event(HostEvent event) {
799 Host vm = event.subject();
800
801 switch (event.type()) {
802 case HOST_ADDED:
803 eventExecutor.submit(() -> vmHandler.connected(vm));
804 break;
805 case HOST_REMOVED:
806 eventExecutor.submit(() -> vmHandler.disconnected(vm));
807 break;
808 default:
809 break;
810 }
811 }
812 }
813
Hyunsun Moon2b530322015-09-23 13:24:35 -0700814 private class OvsdbHandler implements ConnectionHandler<Device> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700815
816 @Override
817 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800818 CordVtnNode node = getNodeByOvsdbId(device.id());
819 if (node != null) {
820 setNodeState(node, checkNodeState(node));
Hyunsun Moon523d9762015-10-19 12:38:21 -0700821 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700822 }
823
824 @Override
825 public void disconnected(Device device) {
Hyunsun Moonba225722015-12-10 13:14:05 -0800826 if (!deviceService.isAvailable(device.id())) {
827 adminService.removeDevice(device.id());
828 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700829 }
830 }
831
832 private class BridgeHandler implements ConnectionHandler<Device> {
833
834 @Override
835 public void connected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800836 CordVtnNode node = getNodeByBridgeId(device.id());
837 if (node != null) {
838 setNodeState(node, checkNodeState(node));
Hyunsun Moon1f145552015-10-08 22:25:30 -0700839 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700840 }
841
842 @Override
843 public void disconnected(Device device) {
Hyunsun Moon8539b042015-11-07 22:08:43 -0800844 CordVtnNode node = getNodeByBridgeId(device.id());
845 if (node != null) {
846 log.info("Integration Bridge is disconnected from {}", node.hostname());
847 setNodeState(node, NodeState.INCOMPLETE);
848 }
849 }
850
851 /**
852 * Handles port added situation.
853 * If the added port is tunnel port, proceed remaining node initialization.
854 * Otherwise, do nothing.
855 *
856 * @param port port
857 */
858 public void portAdded(Port port) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800859 // TODO add host by updating network config
Hyunsun Moon8539b042015-11-07 22:08:43 -0800860 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
861 return;
862 }
863
864 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
865 if (node != null) {
866 setNodeState(node, checkNodeState(node));
867 }
868 }
869
870 /**
871 * Handles port removed situation.
872 * If the removed port is tunnel port, proceed remaining node initialization.
873 * Others, do nothing.
874 *
875 * @param port port
876 */
877 public void portRemoved(Port port) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800878 // TODO remove host by updating network config
Hyunsun Moon8539b042015-11-07 22:08:43 -0800879 if (!port.annotations().value("portName").contains(DEFAULT_TUNNEL)) {
880 return;
881 }
882
883 CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
884 if (node != null) {
885 log.info("Tunnel interface is removed from {}", node.hostname());
886 setNodeState(node, NodeState.INCOMPLETE);
887 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700888 }
889 }
890
Hyunsun Moon2b530322015-09-23 13:24:35 -0700891 private class VmHandler implements ConnectionHandler<Host> {
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700892
893 @Override
894 public void connected(Host host) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800895 // TODO remove check gateway here after applying network config host provider
896 if (isGateway(host)) {
897 return;
898 }
899
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800900 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800901 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800902 // do nothing for the host on unregistered or unprepared device
903 return;
904 }
905
906 OpenstackNetwork vNet = getOpenstackNetworkByHost(host);
907 if (vNet == null) {
908 return;
909 }
910
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800911 // TODO host ip should be set in host information after applying network config host provider
912 IpAddress hostIp = getHostIpFromOpenstack(host);
913 if (hostIp == null) {
914 log.error("Failed to get host IP of {}", host.id());
915 return;
916 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800917
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800918 log.info("VM {} is detected", host.id());
919 hostNetMap.put(host.id(), vNet);
920
921 ruleInstaller.populateBasicConnectionRules(
922 host,
923 hostIp,
924 checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
925 vNet);
926
927 // TODO add new VM to related service group if exists
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700928 }
929
930 @Override
931 public void disconnected(Host host) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800932 CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800933 if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800934 // do nothing for the host on unregistered or unprepared device
935 return;
936 }
937
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800938 OpenstackNetwork vNet = hostNetMap.get(host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800939 if (vNet == null) {
940 return;
941 }
942
Hyunsun Moon1f145552015-10-08 22:25:30 -0700943 log.info("VM {} is vanished", host.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800944 ruleInstaller.removeBasicConnectionRules(host);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800945
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800946 // TODO remove the VM from related service group if exists
947 hostNetMap.remove(host.id());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700948 }
949 }
950}