Hyunsun Moon
Committed by Gerrit Code Review

CORD-380 Added host provider for cordvtn service

- Renamed CordVtnConfigManager to CordVtnNodeManager
- Moved all node bootstrap logic to CordVtnNodeManager
- CordVtnService now provides VM add/remove and service dependency create/remove
- Made CordVtn implement HostProvider so that it can inject/eject VM to the system

Change-Id: I0011ac692ecea240d2d7fe48b3e7a1db4973b76e
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.cordvtn; 16 package org.onosproject.cordvtn;
17 17
18 -import com.google.common.collect.Maps;
19 import com.google.common.collect.Sets; 18 import com.google.common.collect.Sets;
20 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
...@@ -24,59 +23,43 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -24,59 +23,43 @@ import org.apache.felix.scr.annotations.Reference;
24 import org.apache.felix.scr.annotations.ReferenceCardinality; 23 import org.apache.felix.scr.annotations.ReferenceCardinality;
25 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
26 import org.onlab.packet.Ethernet; 25 import org.onlab.packet.Ethernet;
27 -import org.onlab.packet.Ip4Address;
28 -import org.onlab.util.ItemNotFoundException;
29 import org.onlab.packet.IpAddress; 26 import org.onlab.packet.IpAddress;
30 -import org.onlab.util.KryoNamespace; 27 +import org.onlab.packet.MacAddress;
31 -import org.onosproject.cluster.ClusterService; 28 +import org.onlab.packet.VlanId;
32 import org.onosproject.core.ApplicationId; 29 import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.CoreService; 30 import org.onosproject.core.CoreService;
34 import org.onosproject.mastership.MastershipService; 31 import org.onosproject.mastership.MastershipService;
32 +import org.onosproject.net.ConnectPoint;
35 import org.onosproject.net.DefaultAnnotations; 33 import org.onosproject.net.DefaultAnnotations;
36 -import org.onosproject.net.Device;
37 -import org.onosproject.net.DeviceId;
38 import org.onosproject.net.Host; 34 import org.onosproject.net.Host;
39 import org.onosproject.net.HostId; 35 import org.onosproject.net.HostId;
36 +import org.onosproject.net.HostLocation;
40 import org.onosproject.net.Port; 37 import org.onosproject.net.Port;
41 -import org.onosproject.net.behaviour.BridgeConfig; 38 +import org.onosproject.net.SparseAnnotations;
42 -import org.onosproject.net.behaviour.BridgeName;
43 -import org.onosproject.net.behaviour.ControllerInfo;
44 -import org.onosproject.net.behaviour.DefaultTunnelDescription;
45 -import org.onosproject.net.behaviour.TunnelConfig;
46 -import org.onosproject.net.behaviour.TunnelDescription;
47 -import org.onosproject.net.behaviour.TunnelName;
48 -import org.onosproject.net.device.DeviceAdminService;
49 -import org.onosproject.net.device.DeviceEvent;
50 -import org.onosproject.net.device.DeviceListener;
51 import org.onosproject.net.device.DeviceService; 39 import org.onosproject.net.device.DeviceService;
52 -import org.onosproject.net.driver.DriverHandler;
53 import org.onosproject.net.driver.DriverService; 40 import org.onosproject.net.driver.DriverService;
54 import org.onosproject.net.flow.FlowRuleService; 41 import org.onosproject.net.flow.FlowRuleService;
55 import org.onosproject.net.group.GroupService; 42 import org.onosproject.net.group.GroupService;
43 +import org.onosproject.net.host.DefaultHostDescription;
44 +import org.onosproject.net.host.HostDescription;
56 import org.onosproject.net.host.HostEvent; 45 import org.onosproject.net.host.HostEvent;
57 import org.onosproject.net.host.HostListener; 46 import org.onosproject.net.host.HostListener;
47 +import org.onosproject.net.host.HostProvider;
48 +import org.onosproject.net.host.HostProviderRegistry;
49 +import org.onosproject.net.host.HostProviderService;
58 import org.onosproject.net.host.HostService; 50 import org.onosproject.net.host.HostService;
59 import org.onosproject.net.packet.PacketContext; 51 import org.onosproject.net.packet.PacketContext;
60 import org.onosproject.net.packet.PacketProcessor; 52 import org.onosproject.net.packet.PacketProcessor;
61 import org.onosproject.net.packet.PacketService; 53 import org.onosproject.net.packet.PacketService;
54 +import org.onosproject.net.provider.AbstractProvider;
55 +import org.onosproject.net.provider.ProviderId;
62 import org.onosproject.openstackswitching.OpenstackNetwork; 56 import org.onosproject.openstackswitching.OpenstackNetwork;
63 import org.onosproject.openstackswitching.OpenstackPort; 57 import org.onosproject.openstackswitching.OpenstackPort;
64 import org.onosproject.openstackswitching.OpenstackSubnet; 58 import org.onosproject.openstackswitching.OpenstackSubnet;
65 import org.onosproject.openstackswitching.OpenstackSwitchingService; 59 import org.onosproject.openstackswitching.OpenstackSwitchingService;
66 -import org.onosproject.ovsdb.controller.OvsdbClientService;
67 -import org.onosproject.ovsdb.controller.OvsdbController;
68 -import org.onosproject.ovsdb.controller.OvsdbNodeId;
69 -import org.onosproject.store.serializers.KryoNamespaces;
70 -import org.onosproject.store.service.ConsistentMap;
71 -import org.onosproject.store.service.Serializer;
72 -import org.onosproject.store.service.StorageService;
73 import org.slf4j.Logger; 60 import org.slf4j.Logger;
74 61
75 -import java.util.ArrayList;
76 -import java.util.HashMap;
77 -import java.util.List;
78 import java.util.Map; 62 import java.util.Map;
79 -import java.util.Objects;
80 import java.util.Set; 63 import java.util.Set;
81 import java.util.concurrent.ExecutorService; 64 import java.util.concurrent.ExecutorService;
82 import java.util.concurrent.Executors; 65 import java.util.concurrent.Executors;
...@@ -84,8 +67,6 @@ import java.util.stream.Collectors; ...@@ -84,8 +67,6 @@ import java.util.stream.Collectors;
84 67
85 import static com.google.common.base.Preconditions.checkNotNull; 68 import static com.google.common.base.Preconditions.checkNotNull;
86 import static org.onlab.util.Tools.groupedThreads; 69 import static org.onlab.util.Tools.groupedThreads;
87 -import static org.onosproject.net.Device.Type.SWITCH;
88 -import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
89 import static org.slf4j.LoggerFactory.getLogger; 70 import static org.slf4j.LoggerFactory.getLogger;
90 71
91 /** 72 /**
...@@ -94,36 +75,15 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -94,36 +75,15 @@ import static org.slf4j.LoggerFactory.getLogger;
94 */ 75 */
95 @Component(immediate = true) 76 @Component(immediate = true)
96 @Service 77 @Service
97 -public class CordVtn implements CordVtnService { 78 +public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
98 79
99 protected final Logger log = getLogger(getClass()); 80 protected final Logger log = getLogger(getClass());
100 81
101 - private static final int NUM_THREADS = 1;
102 - private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
103 - .register(KryoNamespaces.API)
104 - .register(CordVtnNode.class)
105 - .register(NodeState.class);
106 -
107 - private static final String DEFAULT_BRIDGE = "br-int";
108 - private static final String VPORT_PREFIX = "tap";
109 - private static final String DEFAULT_TUNNEL = "vxlan";
110 - private static final String OK = "OK";
111 - private static final String NO = "NO";
112 -
113 - private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
114 - {
115 - put("key", "flow");
116 - put("remote_ip", "flow");
117 - }
118 - };
119 - private static final int DPID_BEGIN = 3;
120 - private static final int OFPORT = 6653;
121 -
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected CoreService coreService; 83 protected CoreService coreService;
124 84
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 - protected StorageService storageService; 86 + protected HostProviderRegistry hostProviderRegistry;
127 87
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 protected DeviceService deviceService; 89 protected DeviceService deviceService;
...@@ -135,21 +95,12 @@ public class CordVtn implements CordVtnService { ...@@ -135,21 +95,12 @@ public class CordVtn implements CordVtnService {
135 protected DriverService driverService; 95 protected DriverService driverService;
136 96
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 - protected DeviceAdminService adminService;
139 -
140 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected FlowRuleService flowRuleService; 98 protected FlowRuleService flowRuleService;
142 99
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 protected PacketService packetService; 101 protected PacketService packetService;
145 102
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 - protected OvsdbController controller;
148 -
149 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 - protected ClusterService clusterService;
151 -
152 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected MastershipService mastershipService; 104 protected MastershipService mastershipService;
154 105
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -158,76 +109,32 @@ public class CordVtn implements CordVtnService { ...@@ -158,76 +109,32 @@ public class CordVtn implements CordVtnService {
158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
159 protected OpenstackSwitchingService openstackService; 110 protected OpenstackSwitchingService openstackService;
160 111
112 + private static final int NUM_THREADS = 1;
113 + private static final String DEFAULT_TUNNEL = "vxlan";
114 + private static final String SERVICE_ID = "serviceId";
115 + private static final String LOCATION_IP = "locationIp";
116 + private static final String OPENSTACK_VM_ID = "openstackVmId";
117 +
161 private final ExecutorService eventExecutor = Executors 118 private final ExecutorService eventExecutor = Executors
162 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler")); 119 .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
163 120
164 - private final DeviceListener deviceListener = new InternalDeviceListener();
165 - private final HostListener hostListener = new InternalHostListener();
166 private final PacketProcessor packetProcessor = new InternalPacketProcessor(); 121 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
122 + private final HostListener hostListener = new InternalHostListener();
167 123
168 - private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); 124 + private HostProviderService hostProvider;
169 - private final BridgeHandler bridgeHandler = new BridgeHandler();
170 - private final VmHandler vmHandler = new VmHandler();
171 -
172 - private ApplicationId appId;
173 - private ConsistentMap<CordVtnNode, NodeState> nodeStore;
174 - private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap();
175 private CordVtnRuleInstaller ruleInstaller; 125 private CordVtnRuleInstaller ruleInstaller;
176 private CordVtnArpProxy arpProxy; 126 private CordVtnArpProxy arpProxy;
177 127
178 - private enum NodeState { 128 + /**
179 - 129 + * Creates an cordvtn host location provider.
180 - INIT { 130 + */
181 - @Override 131 + public CordVtn() {
182 - public void process(CordVtn cordVtn, CordVtnNode node) { 132 + super(new ProviderId("host", CORDVTN_APP_ID));
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 -
218 - // TODO Add physical port add state
219 -
220 - public abstract void process(CordVtn cordVtn, CordVtnNode node);
221 } 133 }
222 134
223 @Activate 135 @Activate
224 protected void activate() { 136 protected void activate() {
225 - appId = coreService.registerApplication("org.onosproject.cordvtn"); 137 + ApplicationId appId = coreService.registerApplication("org.onosproject.cordvtn");
226 - nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
227 - .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
228 - .withName("cordvtn-nodestore")
229 - .withApplicationId(appId)
230 - .build();
231 138
232 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService, 139 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
233 deviceService, 140 deviceService,
...@@ -240,95 +147,29 @@ public class CordVtn implements CordVtnService { ...@@ -240,95 +147,29 @@ public class CordVtn implements CordVtnService {
240 packetService.addProcessor(packetProcessor, PacketProcessor.director(0)); 147 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
241 arpProxy.requestPacket(); 148 arpProxy.requestPacket();
242 149
243 - deviceService.addListener(deviceListener);
244 hostService.addListener(hostListener); 150 hostService.addListener(hostListener);
151 + hostProvider = hostProviderRegistry.register(this);
245 152
246 log.info("Started"); 153 log.info("Started");
247 } 154 }
248 155
249 @Deactivate 156 @Deactivate
250 protected void deactivate() { 157 protected void deactivate() {
251 - deviceService.removeListener(deviceListener);
252 hostService.removeListener(hostListener); 158 hostService.removeListener(hostListener);
253 packetService.removeProcessor(packetProcessor); 159 packetService.removeProcessor(packetProcessor);
254 160
255 eventExecutor.shutdown(); 161 eventExecutor.shutdown();
256 - nodeStore.clear(); 162 + hostProviderRegistry.unregister(this);
257 163
258 log.info("Stopped"); 164 log.info("Stopped");
259 } 165 }
260 166
261 @Override 167 @Override
262 - public void addNode(CordVtnNode node) { 168 + public void triggerProbe(Host host) {
263 - checkNotNull(node); 169 + /*
264 - 170 + * Note: In CORD deployment, we assume that all hosts are configured.
265 - nodeStore.putIfAbsent(node, checkNodeState(node)); 171 + * Therefore no probe is required.
266 - initNode(node); 172 + */
267 - }
268 -
269 - @Override
270 - public void deleteNode(CordVtnNode node) {
271 - checkNotNull(node);
272 -
273 - if (getOvsdbConnectionState(node)) {
274 - disconnect(node);
275 - }
276 -
277 - nodeStore.remove(node);
278 - }
279 -
280 - @Override
281 - public int getNodeCount() {
282 - return nodeStore.size();
283 - }
284 -
285 - @Override
286 - 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 -
301 - NodeState state = checkNodeState(node);
302 - 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 -
313 - @Override
314 - 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 } 173 }
333 174
334 @Override 175 @Override
...@@ -341,6 +182,7 @@ public class CordVtn implements CordVtnService { ...@@ -341,6 +182,7 @@ public class CordVtn implements CordVtnService {
341 return; 182 return;
342 } 183 }
343 184
185 + log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
344 ruleInstaller.populateServiceDependencyRules(tService, pService); 186 ruleInstaller.populateServiceDependencyRules(tService, pService);
345 } 187 }
346 188
...@@ -354,390 +196,61 @@ public class CordVtn implements CordVtnService { ...@@ -354,390 +196,61 @@ public class CordVtn implements CordVtnService {
354 return; 196 return;
355 } 197 }
356 198
199 + log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
357 ruleInstaller.removeServiceDependencyRules(tService, pService); 200 ruleInstaller.removeServiceDependencyRules(tService, pService);
358 } 201 }
359 202
360 - /** 203 + @Override
361 - * Returns state of a given cordvtn node. 204 + public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
362 - * 205 + Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
363 - * @param node cordvtn node 206 + OpenstackPort vPort = openstackService.port(port);
364 - * @return node state, or null if no such node exists 207 + if (vPort == null) {
365 - */ 208 + log.warn("Failed to get OpenstackPort for {}", getPortName(port));
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());
373 - return null;
374 - }
375 - }
376 -
377 - /**
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);
390 - }
391 -
392 - /**
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);
400 -
401 - if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
402 - // TODO add physical port add state
403 - if (checkPhyInterface(node)) {
404 - return NodeState.COMPLETE;
405 - } else {
406 - return NodeState.INCOMPLETE;
407 - }
408 - } else if (checkIntegrationBridge(node)) {
409 - return NodeState.BRIDGE_CREATED;
410 - } else if (getOvsdbConnectionState(node)) {
411 - return NodeState.OVSDB_CONNECTED;
412 - } else {
413 - return NodeState.INIT;
414 - }
415 - }
416 -
417 - /**
418 - * Performs tasks after node initialization.
419 - * First disconnect unnecessary OVSDB connection and then installs flow rules
420 - * for existing VMs if there are any.
421 - *
422 - * @param node cordvtn node
423 - */
424 - private void postInit(CordVtnNode node) {
425 - disconnect(node);
426 -
427 - ruleInstaller.init(node.intBrId(), node.phyPortName(), node.localIp());
428 - hostService.getConnectedHosts(node.intBrId())
429 - .stream()
430 - .forEach(vmHandler::connected);
431 -
432 - log.info("Finished initializing {}", node.hostname());
433 - }
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)) {
463 - 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 - }
484 - }
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) {
493 - return getNodes().stream()
494 - .filter(node -> node.ovsdbId().equals(ovsdbId))
495 - .findFirst().orElse(null);
496 - }
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) {
505 - return getNodes().stream()
506 - .filter(node -> node.intBrId().equals(bridgeId))
507 - .findFirst().orElse(null);
508 - }
509 -
510 - /**
511 - * 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 - /**
521 - * 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);
528 -
529 - OvsdbClientService ovsdbClient = controller.getOvsdbClient(
530 - new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
531 - if (ovsdbClient == null) {
532 - log.debug("Couldn't find OVSDB client for {}", node.hostname());
533 - }
534 - return ovsdbClient;
535 - }
536 -
537 - /**
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; 209 return;
545 } 210 }
546 211
547 - List<ControllerInfo> controllers = new ArrayList<>(); 212 + MacAddress mac = vPort.macAddress();
548 - Sets.newHashSet(clusterService.getNodes()).stream() 213 + HostId hostId = HostId.hostId(mac);
549 - .forEach(controller -> {
550 - ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
551 - controllers.add(ctrlInfo);
552 - });
553 -
554 - String dpid = node.intBrId().toString().substring(DPID_BEGIN);
555 -
556 - try {
557 - DriverHandler handler = driverService.createHandler(node.ovsdbId());
558 - BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
559 - bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
560 - } catch (ItemNotFoundException e) {
561 - log.warn("Failed to create integration bridge on {}", node.ovsdbId());
562 - }
563 - }
564 214
565 - /** 215 + Host host = hostService.getHost(hostId);
566 - * Creates tunnel interface to the integration bridge for a given node. 216 + if (host != null) {
567 - * 217 + // Host is already known to the system, no HOST_ADDED event is triggered in this case.
568 - * @param node cordvtn node 218 + // It happens when the application is restarted.
569 - */ 219 + // TODO check host description if it has all the information
570 - private void createTunnelInterface(CordVtnNode node) { 220 + serviceVmAdded(host);
571 - if (checkTunnelInterface(node)) {
572 return; 221 return;
573 } 222 }
574 223
575 - DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder(); 224 + Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values());
576 - for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) { 225 + SparseAnnotations annotations = DefaultAnnotations.builder()
577 - optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key)); 226 + .set(OPENSTACK_VM_ID, vPort.deviceId())
578 - } 227 + .set(SERVICE_ID, vPort.networkId())
579 - 228 + .set(LOCATION_IP, node.localIp().toString())
580 - TunnelDescription description = new DefaultTunnelDescription( 229 + .build();
581 - null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
582 - optionBuilder.build());
583 -
584 - try {
585 - DriverHandler handler = driverService.createHandler(node.ovsdbId());
586 - TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
587 - tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
588 - } catch (ItemNotFoundException e) {
589 - log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
590 - }
591 - }
592 -
593 - /**
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) {
611 - return deviceService.getPorts(node.intBrId())
612 - .stream()
613 - .filter(p -> getPortName(p).contains(DEFAULT_TUNNEL)
614 - && p.isEnabled())
615 - .findAny().isPresent();
616 - }
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) {
625 - return deviceService.getPorts(node.intBrId())
626 - .stream()
627 - .filter(p -> getPortName(p).contains(node.phyPortName())
628 - && p.isEnabled())
629 - .findAny().isPresent();
630 - }
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 - */
638 - private Ip4Address getRemoteIp(DeviceId bridgeId) {
639 - CordVtnNode node = getNodeByBridgeId(bridgeId);
640 - if (node != null) {
641 - return node.localIp().getIp4Address();
642 - } else {
643 - log.debug("Couldn't find node information for {}", bridgeId);
644 - return null;
645 - }
646 - }
647 -
648 - /**
649 - * 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());
657 - if (port == null) {
658 - log.debug("Failed to get port for {}", host.id());
659 - return null;
660 - }
661 - 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 - /**
680 - * 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 230
688 - Set<Host> hosts = openstackService.ports(vNet.id()).stream() 231 + HostDescription hostDesc = new DefaultHostDescription(
689 - .filter(port -> port.deviceOwner().contains("compute")) 232 + mac,
690 - .map(port -> hostService.getHostsByMac(port.macAddress()) 233 + VlanId.NONE,
691 - .stream() 234 + new HostLocation(connectPoint, System.currentTimeMillis()),
692 - .findFirst() 235 + ip,
693 - .orElse(null)) 236 + annotations);
694 - .collect(Collectors.toSet());
695 237
696 - hosts.remove(null); 238 + hostProvider.hostDetected(hostId, hostDesc, false);
697 - return hosts;
698 } 239 }
699 240
700 - /** 241 + @Override
701 - * Returns host IP assigned by OpenStack. 242 + public void removeServiceVm(ConnectPoint connectPoint) {
702 - * 243 + Host host = hostService.getConnectedHosts(connectPoint)
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() 244 .stream()
716 .findFirst() 245 .findFirst()
717 .orElse(null); 246 .orElse(null);
718 - }
719 247
720 - /** 248 + if (host == null) {
721 - * Returns port name with OpenStack port information. 249 + log.debug("No host is connected on {}", connectPoint.toString());
722 - * 250 + return;
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 } 251 }
730 252
731 - /** 253 + hostProvider.hostVanished(host.id());
732 - * Returns if the host is VM or not.
733 - *
734 - * @param host host
735 - * @return true if the host is a VM.
736 - */
737 - private boolean isVm(Host host) {
738 - Port port = deviceService.getPort(host.location().deviceId(),
739 - host.location().port());
740 - return getPortName(port).contains(VPORT_PREFIX);
741 } 254 }
742 255
743 /** 256 /**
...@@ -766,8 +279,7 @@ public class CordVtn implements CordVtnService { ...@@ -766,8 +279,7 @@ public class CordVtn implements CordVtnService {
766 279
767 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) 280 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
768 .stream() 281 .stream()
769 - .collect(Collectors.toMap(host -> host, 282 + .collect(Collectors.toMap(host -> host, this::getTunnelIp));
770 - host -> getRemoteIp(host.location().deviceId())));
771 283
772 return new CordService(vNet, subnet, hosts, tServices); 284 return new CordService(vNet, subnet, hosts, tServices);
773 } 285 }
...@@ -795,184 +307,72 @@ public class CordVtn implements CordVtnService { ...@@ -795,184 +307,72 @@ public class CordVtn implements CordVtnService {
795 307
796 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) 308 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
797 .stream() 309 .stream()
798 - .collect(Collectors.toMap(host -> host, 310 + .collect(Collectors.toMap(host -> host, this::getTunnelIp));
799 - host -> getRemoteIp(host.location().deviceId())));
800 311
801 return new CordService(vNet, subnet, hosts, tServices); 312 return new CordService(vNet, subnet, hosts, tServices);
802 } 313 }
803 314
804 - private class InternalDeviceListener implements DeviceListener {
805 -
806 - @Override
807 - public void event(DeviceEvent event) {
808 -
809 - Device device = event.subject();
810 - ConnectionHandler<Device> handler =
811 - (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
812 -
813 - switch (event.type()) {
814 - case PORT_ADDED:
815 - eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
816 - break;
817 - case PORT_UPDATED:
818 - if (!event.port().isEnabled()) {
819 - eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
820 - }
821 - break;
822 - case DEVICE_ADDED:
823 - case DEVICE_AVAILABILITY_CHANGED:
824 - if (deviceService.isAvailable(device.id())) {
825 - eventExecutor.submit(() -> handler.connected(device));
826 - } else {
827 - eventExecutor.submit(() -> handler.disconnected(device));
828 - }
829 - break;
830 - default:
831 - break;
832 - }
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 -
855 - private class OvsdbHandler implements ConnectionHandler<Device> {
856 -
857 - @Override
858 - public void connected(Device device) {
859 - CordVtnNode node = getNodeByOvsdbId(device.id());
860 - if (node != null) {
861 - setNodeState(node, checkNodeState(node));
862 - } else {
863 - log.debug("Unregistered device {} connected, ignore it.", device.id());
864 - }
865 - }
866 -
867 - @Override
868 - public void disconnected(Device device) {
869 - if (!deviceService.isAvailable(device.id())) {
870 - adminService.removeDevice(device.id());
871 - }
872 - }
873 - }
874 -
875 - private class BridgeHandler implements ConnectionHandler<Device> {
876 -
877 - @Override
878 - public void connected(Device device) {
879 - CordVtnNode node = getNodeByBridgeId(device.id());
880 - if (node != null) {
881 - setNodeState(node, checkNodeState(node));
882 - } else {
883 - log.debug("Unregistered device {} connected, ignore it.", device.id());
884 - }
885 - }
886 -
887 - @Override
888 - public void disconnected(Device device) {
889 - 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 /** 315 /**
897 - * Handles port added situation. 316 + * Returns IP address for tunneling for a given host.
898 - * If the added port is tunnel or physical port, proceed remaining node
899 - * initialization. Otherwise, do nothing.
900 * 317 *
901 - * @param port port 318 + * @param host host
319 + * @return ip address
902 */ 320 */
903 - public void portAdded(Port port) { 321 + private IpAddress getTunnelIp(Host host) {
904 - CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); 322 + return IpAddress.valueOf(host.annotations().value(LOCATION_IP));
905 - if (node == null) {
906 - return;
907 - } else {
908 - log.debug("Port {} added to unregistered device, ignore it.", getPortName(port));
909 - }
910 -
911 - // TODO add host by updating network config
912 - String portName = getPortName(port);
913 - if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) {
914 - return;
915 - }
916 -
917 - log.info("Port {} is added to {}", portName, node.hostname());
918 - setNodeState(node, checkNodeState(node));
919 } 323 }
920 324
921 /** 325 /**
922 - * Handles port removed situation. 326 + * Returns port name.
923 - * If the removed port is tunnel or physical port, proceed remaining node
924 - * initialization.Others, do nothing.
925 * 327 *
926 * @param port port 328 * @param port port
329 + * @return port name
927 */ 330 */
928 - public void portRemoved(Port port) { 331 + private String getPortName(Port port) {
929 - CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); 332 + return port.annotations().value("portName");
930 - if (node == null) {
931 - return;
932 - }
933 -
934 - // TODO remove host by updating network config
935 - String portName = getPortName(port);
936 - if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) {
937 - return;
938 - }
939 -
940 - log.info("Port {} is removed from {}", portName, node.hostname());
941 - setNodeState(node, NodeState.INCOMPLETE);
942 - }
943 } 333 }
944 334
945 - private class VmHandler implements ConnectionHandler<Host> { 335 + /**
336 + * Returns hosts associated with a given OpenStack network.
337 + *
338 + * @param vNet openstack network
339 + * @return set of hosts
340 + */
341 + private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
342 + checkNotNull(vNet);
946 343
947 - @Override 344 + Set<Host> hosts = openstackService.ports(vNet.id()).stream()
948 - public void connected(Host host) { 345 + .filter(port -> port.deviceOwner().contains("compute"))
949 - // TODO remove check VM here after applying network config host provider 346 + .map(port -> hostService.getHostsByMac(port.macAddress())
950 - if (!isVm(host)) { 347 + .stream()
951 - log.debug("Host {} is not a VM, ignore it.", host.id()); 348 + .findFirst()
952 - return; 349 + .orElse(null))
953 - } 350 + .collect(Collectors.toSet());
954 351
955 - CordVtnNode node = getNodeByBridgeId(host.location().deviceId()); 352 + hosts.remove(null);
956 - if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) { 353 + return hosts;
957 - log.debug("VM {} is detected unknown or incomplete device, ignore it.", host.id());
958 - return;
959 } 354 }
960 355
961 - OpenstackNetwork vNet = getOpenstackNetworkByHost(host); 356 + /**
357 + * Handles VM detected situation.
358 + *
359 + * @param host host
360 + */
361 + private void serviceVmAdded(Host host) {
362 + String vNetId = host.annotations().value(SERVICE_ID);
363 + OpenstackNetwork vNet = openstackService.network(vNetId);
962 if (vNet == null) { 364 if (vNet == null) {
963 - log.debug("Failed to get OpenStack network for VM {}, ignore it.", host.id()); 365 + log.warn("Failed to get OpenStack network {} for VM {}({}).",
366 + vNetId,
367 + host.id(),
368 + host.annotations().value(OPENSTACK_VM_ID));
964 return; 369 return;
965 } 370 }
966 371
967 - // TODO host ip should be set in host information after applying network config host provider 372 + log.info("VM {} is detected, MAC: {} IP: {}",
968 - IpAddress hostIp = getHostIpFromOpenstack(host); 373 + host.annotations().value(OPENSTACK_VM_ID),
969 - if (hostIp == null) { 374 + host.mac(),
970 - log.debug("Failed to get host IP of {}, ignore it.", host.id()); 375 + host.ipAddresses().stream().findFirst().get());
971 - return;
972 - }
973 -
974 - log.info("VM {} is detected", host.id());
975 - hostNetMap.put(host.id(), vNet);
976 376
977 CordService service = getCordService(vNet); 377 CordService service = getCordService(vNet);
978 if (service != null) { 378 if (service != null) {
...@@ -981,27 +381,30 @@ public class CordVtn implements CordVtnService { ...@@ -981,27 +381,30 @@ public class CordVtn implements CordVtnService {
981 arpProxy.addServiceIp(service.serviceIp()); 381 arpProxy.addServiceIp(service.serviceIp());
982 } 382 }
983 383
984 - ruleInstaller.populateBasicConnectionRules( 384 + ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet);
985 - host,
986 - hostIp,
987 - checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
988 - vNet);
989 } 385 }
990 386
991 - @Override 387 + /**
992 - public void disconnected(Host host) { 388 + * Handles VM removed situation.
993 - CordVtnNode node = getNodeByBridgeId(host.location().deviceId()); 389 + *
994 - if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) { 390 + * @param host host
995 - // do nothing for the host on unregistered or unprepared device 391 + */
996 - return; 392 + private void serviceVmRemoved(Host host) {
997 - } 393 + String vNetId = host.annotations().value(SERVICE_ID);
998 - 394 + OpenstackNetwork vNet = openstackService.network(host.annotations().value(SERVICE_ID));
999 - OpenstackNetwork vNet = hostNetMap.get(host.id());
1000 if (vNet == null) { 395 if (vNet == null) {
396 + log.warn("Failed to get OpenStack network {} for VM {}({}).",
397 + vNetId,
398 + host.id(),
399 + host.annotations().value(OPENSTACK_VM_ID));
1001 return; 400 return;
1002 } 401 }
1003 402
1004 - log.info("VM {} is vanished", host.id()); 403 + log.info("VM {} is vanished, MAC: {} IP: {}",
404 + host.annotations().value(OPENSTACK_VM_ID),
405 + host.mac(),
406 + host.ipAddresses().stream().findFirst().get());
407 +
1005 ruleInstaller.removeBasicConnectionRules(host); 408 ruleInstaller.removeBasicConnectionRules(host);
1006 409
1007 CordService service = getCordService(vNet); 410 CordService service = getCordService(vNet);
...@@ -1013,8 +416,24 @@ public class CordVtn implements CordVtnService { ...@@ -1013,8 +416,24 @@ public class CordVtn implements CordVtnService {
1013 arpProxy.removeServiceIp(service.serviceIp()); 416 arpProxy.removeServiceIp(service.serviceIp());
1014 } 417 }
1015 } 418 }
419 + }
420 +
421 + private class InternalHostListener implements HostListener {
1016 422
1017 - hostNetMap.remove(host.id()); 423 + @Override
424 + public void event(HostEvent event) {
425 + Host host = event.subject();
426 +
427 + switch (event.type()) {
428 + case HOST_ADDED:
429 + eventExecutor.submit(() -> serviceVmAdded(host));
430 + break;
431 + case HOST_REMOVED:
432 + eventExecutor.submit(() -> serviceVmRemoved(host));
433 + break;
434 + default:
435 + break;
436 + }
1018 } 437 }
1019 } 438 }
1020 439
......
1 -/*
2 - * Copyright 2014-2015 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn;
17 -
18 -import org.apache.felix.scr.annotations.Activate;
19 -import org.apache.felix.scr.annotations.Component;
20 -import org.apache.felix.scr.annotations.Deactivate;
21 -import org.apache.felix.scr.annotations.Reference;
22 -import org.apache.felix.scr.annotations.ReferenceCardinality;
23 -import org.onosproject.core.ApplicationId;
24 -import org.onosproject.core.CoreService;
25 -import org.onosproject.net.config.ConfigFactory;
26 -import org.onosproject.net.config.NetworkConfigEvent;
27 -import org.onosproject.net.config.NetworkConfigListener;
28 -import org.onosproject.net.config.NetworkConfigRegistry;
29 -import org.onosproject.net.config.NetworkConfigService;
30 -import org.onosproject.net.config.basics.SubjectFactories;
31 -import org.slf4j.Logger;
32 -
33 -import java.util.concurrent.ExecutorService;
34 -
35 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
36 -import static org.onlab.util.Tools.groupedThreads;
37 -import static org.slf4j.LoggerFactory.getLogger;
38 -
39 -/**
40 - * Reads node information from the network config file and handles the config
41 - * update events.
42 - * Only a leader controller performs the node addition or deletion.
43 - */
44 -@Component(immediate = true)
45 -public class CordVtnConfigManager {
46 -
47 - protected final Logger log = getLogger(getClass());
48 -
49 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 - protected CoreService coreService;
51 -
52 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 - protected NetworkConfigRegistry configRegistry;
54 -
55 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 - protected NetworkConfigService configService;
57 -
58 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 - protected CordVtnService cordVtnService;
60 -
61 - private final ConfigFactory configFactory =
62 - new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
63 - @Override
64 - public CordVtnConfig createConfig() {
65 - return new CordVtnConfig();
66 - }
67 - };
68 -
69 - private final NetworkConfigListener configListener = new InternalConfigListener();
70 - private ApplicationId appId;
71 - protected ExecutorService eventExecutor;
72 -
73 -
74 - @Activate
75 - protected void active() {
76 - appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID);
77 -
78 - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtncfg", "event-handler"));
79 - configService.addListener(configListener);
80 - configRegistry.registerConfigFactory(configFactory);
81 - }
82 -
83 - @Deactivate
84 - protected void deactivate() {
85 - configRegistry.unregisterConfigFactory(configFactory);
86 - configService.removeListener(configListener);
87 - eventExecutor.shutdown();
88 - }
89 -
90 - private void readConfiguration() {
91 - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
92 -
93 - if (config == null) {
94 - log.warn("No configuration found");
95 - return;
96 - }
97 -
98 - config.cordVtnNodes().forEach(node -> {
99 - CordVtnNode cordVtnNode = new CordVtnNode(
100 - node.hostname(),
101 - node.ovsdbIp(),
102 - node.ovsdbPort(),
103 - node.bridgeId(),
104 - node.phyPortName(),
105 - node.localIp());
106 -
107 - cordVtnService.addNode(cordVtnNode);
108 - });
109 - }
110 -
111 - private class InternalConfigListener implements NetworkConfigListener {
112 -
113 - @Override
114 - public void event(NetworkConfigEvent event) {
115 - if (!event.configClass().equals(CordVtnConfig.class)) {
116 - return;
117 - }
118 -
119 - switch (event.type()) {
120 - case CONFIG_ADDED:
121 - log.info("Network configuration added");
122 - eventExecutor.execute(CordVtnConfigManager.this::readConfiguration);
123 - break;
124 - case CONFIG_UPDATED:
125 - log.info("Network configuration updated");
126 - eventExecutor.execute(CordVtnConfigManager.this::readConfiguration);
127 - break;
128 - default:
129 - break;
130 - }
131 - }
132 - }
133 -}
1 +/*
2 + * Copyright 2014-2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.cordvtn;
17 +
18 +import com.google.common.collect.Sets;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.apache.felix.scr.annotations.Service;
25 +import org.onlab.util.ItemNotFoundException;
26 +import org.onlab.util.KryoNamespace;
27 +import org.onosproject.cluster.ClusterService;
28 +import org.onosproject.core.ApplicationId;
29 +import org.onosproject.core.CoreService;
30 +import org.onosproject.mastership.MastershipService;
31 +import org.onosproject.net.ConnectPoint;
32 +import org.onosproject.net.DefaultAnnotations;
33 +import org.onosproject.net.Device;
34 +import org.onosproject.net.DeviceId;
35 +import org.onosproject.net.Host;
36 +import org.onosproject.net.Port;
37 +import org.onosproject.net.behaviour.BridgeConfig;
38 +import org.onosproject.net.behaviour.BridgeName;
39 +import org.onosproject.net.behaviour.ControllerInfo;
40 +import org.onosproject.net.behaviour.DefaultTunnelDescription;
41 +import org.onosproject.net.behaviour.TunnelConfig;
42 +import org.onosproject.net.behaviour.TunnelDescription;
43 +import org.onosproject.net.behaviour.TunnelName;
44 +import org.onosproject.net.config.ConfigFactory;
45 +import org.onosproject.net.config.NetworkConfigEvent;
46 +import org.onosproject.net.config.NetworkConfigListener;
47 +import org.onosproject.net.config.NetworkConfigRegistry;
48 +import org.onosproject.net.config.NetworkConfigService;
49 +import org.onosproject.net.config.basics.SubjectFactories;
50 +import org.onosproject.net.device.DeviceAdminService;
51 +import org.onosproject.net.device.DeviceEvent;
52 +import org.onosproject.net.device.DeviceListener;
53 +import org.onosproject.net.device.DeviceService;
54 +import org.onosproject.net.driver.DriverHandler;
55 +import org.onosproject.net.driver.DriverService;
56 +import org.onosproject.net.flow.FlowRuleService;
57 +import org.onosproject.net.group.GroupService;
58 +import org.onosproject.net.host.HostService;
59 +import org.onosproject.ovsdb.controller.OvsdbClientService;
60 +import org.onosproject.ovsdb.controller.OvsdbController;
61 +import org.onosproject.ovsdb.controller.OvsdbNodeId;
62 +import org.onosproject.store.serializers.KryoNamespaces;
63 +import org.onosproject.store.service.ConsistentMap;
64 +import org.onosproject.store.service.Serializer;
65 +import org.onosproject.store.service.StorageService;
66 +import org.slf4j.Logger;
67 +
68 +import java.util.ArrayList;
69 +import java.util.HashMap;
70 +import java.util.List;
71 +import java.util.Map;
72 +import java.util.concurrent.ExecutorService;
73 +
74 +import static com.google.common.base.Preconditions.checkNotNull;
75 +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
76 +import static org.onlab.util.Tools.groupedThreads;
77 +import static org.onosproject.net.Device.Type.SWITCH;
78 +import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
79 +import static org.slf4j.LoggerFactory.getLogger;
80 +
81 +/**
82 + * Reads node information from the network config file and handles the config
83 + * update events.
84 + * Only a leader controller performs the node addition or deletion.
85 + */
86 +@Component(immediate = true)
87 +@Service(value = CordVtnNodeManager.class)
88 +public class CordVtnNodeManager {
89 +
90 + protected final Logger log = getLogger(getClass());
91 +
92 + private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
93 + .register(KryoNamespaces.API)
94 + .register(CordVtnNode.class)
95 + .register(NodeState.class);
96 +
97 + private static final String DEFAULT_BRIDGE = "br-int";
98 + private static final String DEFAULT_TUNNEL = "vxlan";
99 + private static final String VPORT_PREFIX = "tap";
100 + private static final String OK = "OK";
101 + private static final String NO = "NO";
102 +
103 + private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
104 + {
105 + put("key", "flow");
106 + put("remote_ip", "flow");
107 + }
108 + };
109 + private static final int DPID_BEGIN = 3;
110 + private static final int OFPORT = 6653;
111 +
112 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 + protected CoreService coreService;
114 +
115 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 + protected NetworkConfigRegistry configRegistry;
117 +
118 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 + protected NetworkConfigService configService;
120 +
121 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 + protected StorageService storageService;
123 +
124 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 + protected DeviceAdminService adminService;
126 +
127 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 + protected OvsdbController controller;
129 +
130 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 + protected ClusterService clusterService;
132 +
133 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 + protected DriverService driverService;
135 +
136 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 + protected DeviceService deviceService;
138 +
139 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 + protected HostService hostService;
141 +
142 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 + protected FlowRuleService flowRuleService;
144 +
145 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 + protected MastershipService mastershipService;
147 +
148 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
149 + protected GroupService groupService;
150 +
151 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
152 + protected CordVtnService cordVtnService;
153 +
154 + private final ConfigFactory configFactory =
155 + new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
156 + @Override
157 + public CordVtnConfig createConfig() {
158 + return new CordVtnConfig();
159 + }
160 + };
161 +
162 + private final ExecutorService eventExecutor =
163 + newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtncfg", "event-handler"));
164 +
165 + private final NetworkConfigListener configListener = new InternalConfigListener();
166 + private final DeviceListener deviceListener = new InternalDeviceListener();
167 +
168 + private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
169 + private final BridgeHandler bridgeHandler = new BridgeHandler();
170 +
171 + private ConsistentMap<CordVtnNode, NodeState> nodeStore;
172 + private CordVtnRuleInstaller ruleInstaller;
173 + private ApplicationId appId;
174 +
175 + private enum NodeState {
176 +
177 + INIT {
178 + @Override
179 + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
180 + nodeManager.connectOvsdb(node);
181 + }
182 + },
183 + OVSDB_CONNECTED {
184 + @Override
185 + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
186 + if (!nodeManager.getOvsdbConnectionState(node)) {
187 + nodeManager.connectOvsdb(node);
188 + } else {
189 + nodeManager.createIntegrationBridge(node);
190 + }
191 + }
192 + },
193 + BRIDGE_CREATED {
194 + @Override
195 + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
196 + if (!nodeManager.getOvsdbConnectionState(node)) {
197 + nodeManager.connectOvsdb(node);
198 + } else {
199 + nodeManager.createTunnelInterface(node);
200 + }
201 + }
202 + },
203 + COMPLETE {
204 + @Override
205 + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
206 + nodeManager.postInit(node);
207 + }
208 + },
209 + INCOMPLETE {
210 + @Override
211 + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
212 + }
213 + };
214 +
215 + // TODO Add physical port add state
216 +
217 + public abstract void process(CordVtnNodeManager nodeManager, CordVtnNode node);
218 + }
219 +
220 + @Activate
221 + protected void active() {
222 + appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID);
223 +
224 + nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder()
225 + .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
226 + .withName("cordvtn-nodestore")
227 + .withApplicationId(appId)
228 + .build();
229 +
230 + ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
231 + deviceService,
232 + driverService,
233 + groupService,
234 + mastershipService,
235 + DEFAULT_TUNNEL);
236 +
237 + deviceService.addListener(deviceListener);
238 + configService.addListener(configListener);
239 + configRegistry.registerConfigFactory(configFactory);
240 + }
241 +
242 + @Deactivate
243 + protected void deactivate() {
244 + configRegistry.unregisterConfigFactory(configFactory);
245 + configService.removeListener(configListener);
246 + deviceService.removeListener(deviceListener);
247 +
248 + eventExecutor.shutdown();
249 + nodeStore.clear();
250 + }
251 +
252 + /**
253 + * Adds a new node to the service.
254 + *
255 + * @param node cordvtn node
256 + */
257 + public void addNode(CordVtnNode node) {
258 + checkNotNull(node);
259 +
260 + nodeStore.putIfAbsent(node, checkNodeState(node));
261 + initNode(node);
262 + }
263 +
264 + /**
265 + * Deletes a node from the service.
266 + *
267 + * @param node cordvtn node
268 + */
269 + public void deleteNode(CordVtnNode node) {
270 + checkNotNull(node);
271 +
272 + if (getOvsdbConnectionState(node)) {
273 + disconnectOvsdb(node);
274 + }
275 +
276 + nodeStore.remove(node);
277 + }
278 +
279 + /**
280 + * Initiates node to serve virtual tenant network.
281 + *
282 + * @param node cordvtn node
283 + */
284 + public void initNode(CordVtnNode node) {
285 + checkNotNull(node);
286 +
287 + if (!nodeStore.containsKey(node)) {
288 + log.warn("Node {} does not exist, add node first", node.hostname());
289 + return;
290 + }
291 +
292 + NodeState state = checkNodeState(node);
293 + state.process(this, node);
294 + }
295 +
296 + /**
297 + * Returns node initialization state.
298 + *
299 + * @param node cordvtn node
300 + * @return true if initial node setup is completed, otherwise false
301 + */
302 + public boolean getNodeInitState(CordVtnNode node) {
303 + checkNotNull(node);
304 +
305 + NodeState state = getNodeState(node);
306 + return state != null && state.equals(NodeState.COMPLETE);
307 + }
308 +
309 + /**
310 + * Returns detailed node initialization state.
311 + * Return string includes the following information.
312 + *
313 + * Integration bridge created/connected: OK or NO
314 + * VXLAN interface created: OK or NO
315 + * Physical interface added: OK or NO
316 + *
317 + * @param node cordvtn node
318 + * @return string including detailed node init state
319 + */
320 + public String checkNodeInitState(CordVtnNode node) {
321 + checkNotNull(node);
322 +
323 + NodeState state = getNodeState(node);
324 + if (state == null) {
325 + log.warn("Failed to get init state of {}", node.hostname());
326 + return null;
327 + }
328 +
329 + String result = String.format(
330 + "Integration bridge created/connected : %s (%s)%n" +
331 + "VXLAN interface created : %s%n" +
332 + "Physical interface added : %s (%s)",
333 + checkIntegrationBridge(node) ? OK : NO, DEFAULT_BRIDGE,
334 + checkTunnelInterface(node) ? OK : NO,
335 + checkPhyInterface(node) ? OK : NO, node.phyPortName());
336 +
337 + return result;
338 + }
339 +
340 + /**
341 + * Returns the number of the nodes known to the service.
342 + *
343 + * @return number of nodes
344 + */
345 + public int getNodeCount() {
346 + return nodeStore.size();
347 + }
348 +
349 + /**
350 + * Returns all nodes known to the service.
351 + *
352 + * @return list of nodes
353 + */
354 + public List<CordVtnNode> getNodes() {
355 + List<CordVtnNode> nodes = new ArrayList<>();
356 + nodes.addAll(nodeStore.keySet());
357 + return nodes;
358 + }
359 +
360 + /**
361 + * Returns cordvtn node associated with a given OVSDB device.
362 + *
363 + * @param ovsdbId OVSDB device id
364 + * @return cordvtn node, null if it fails to find the node
365 + */
366 + private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) {
367 + return getNodes().stream()
368 + .filter(node -> node.ovsdbId().equals(ovsdbId))
369 + .findFirst().orElse(null);
370 + }
371 +
372 + /**
373 + * Returns cordvtn node associated with a given integration bridge.
374 + *
375 + * @param bridgeId device id of integration bridge
376 + * @return cordvtn node, null if it fails to find the node
377 + */
378 + private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) {
379 + return getNodes().stream()
380 + .filter(node -> node.intBrId().equals(bridgeId))
381 + .findFirst().orElse(null);
382 + }
383 +
384 + /**
385 + * Returns state of a given cordvtn node.
386 + *
387 + * @param node cordvtn node
388 + * @return node state, or null if no such node exists
389 + */
390 + private NodeState getNodeState(CordVtnNode node) {
391 + checkNotNull(node);
392 +
393 + try {
394 + return nodeStore.get(node).value();
395 + } catch (NullPointerException e) {
396 + log.error("Failed to get state of {}", node.hostname());
397 + return null;
398 + }
399 + }
400 +
401 + /**
402 + * Sets a new state for a given cordvtn node.
403 + *
404 + * @param node cordvtn node
405 + * @param newState new node state
406 + */
407 + private void setNodeState(CordVtnNode node, NodeState newState) {
408 + checkNotNull(node);
409 +
410 + log.debug("Changed {} state: {}", node.hostname(), newState.toString());
411 +
412 + nodeStore.put(node, newState);
413 + newState.process(this, node);
414 + }
415 +
416 + /**
417 + * Checks current state of a given cordvtn node and returns it.
418 + *
419 + * @param node cordvtn node
420 + * @return node state
421 + */
422 + private NodeState checkNodeState(CordVtnNode node) {
423 + checkNotNull(node);
424 +
425 + if (checkIntegrationBridge(node) && checkTunnelInterface(node)) {
426 + // TODO add physical port add state
427 + if (checkPhyInterface(node)) {
428 + return NodeState.COMPLETE;
429 + } else {
430 + return NodeState.INCOMPLETE;
431 + }
432 + } else if (checkIntegrationBridge(node)) {
433 + return NodeState.BRIDGE_CREATED;
434 + } else if (getOvsdbConnectionState(node)) {
435 + return NodeState.OVSDB_CONNECTED;
436 + } else {
437 + return NodeState.INIT;
438 + }
439 + }
440 +
441 + /**
442 + * Performs tasks after node initialization.
443 + * It disconnects unnecessary OVSDB connection and installs initial flow
444 + * rules on the device.
445 + *
446 + * @param node cordvtn node
447 + */
448 + private void postInit(CordVtnNode node) {
449 + disconnectOvsdb(node);
450 +
451 + ruleInstaller.init(node.intBrId(), node.phyPortName(), node.localIp());
452 +
453 + // add existing hosts to the service
454 + deviceService.getPorts(node.intBrId()).stream()
455 + .filter(port -> getPortName(port).startsWith(VPORT_PREFIX) &&
456 + port.isEnabled())
457 + .forEach(port -> cordVtnService.addServiceVm(node, getConnectPoint(port)));
458 +
459 + // remove stale hosts from the service
460 + hostService.getHosts().forEach(host -> {
461 + Port port = deviceService.getPort(host.location().deviceId(), host.location().port());
462 + if (port == null) {
463 + cordVtnService.removeServiceVm(getConnectPoint(host));
464 + }
465 + });
466 +
467 + log.info("Finished init {}", node.hostname());
468 + }
469 +
470 + /**
471 + * Returns port name.
472 + *
473 + * @param port port
474 + * @return port name
475 + */
476 + private String getPortName(Port port) {
477 + return port.annotations().value("portName");
478 + }
479 +
480 + /**
481 + * Returns connection state of OVSDB server for a given node.
482 + *
483 + * @param node cordvtn node
484 + * @return true if it is connected, false otherwise
485 + */
486 + private boolean getOvsdbConnectionState(CordVtnNode node) {
487 + checkNotNull(node);
488 +
489 + OvsdbClientService ovsdbClient = getOvsdbClient(node);
490 + return deviceService.isAvailable(node.ovsdbId()) &&
491 + ovsdbClient != null && ovsdbClient.isConnected();
492 + }
493 +
494 + /**
495 + * Connects to OVSDB server for a given node.
496 + *
497 + * @param node cordvtn node
498 + */
499 + private void connectOvsdb(CordVtnNode node) {
500 + checkNotNull(node);
501 +
502 + if (!nodeStore.containsKey(node)) {
503 + log.warn("Node {} does not exist", node.hostname());
504 + return;
505 + }
506 +
507 + if (!getOvsdbConnectionState(node)) {
508 + controller.connect(node.ovsdbIp(), node.ovsdbPort());
509 + }
510 + }
511 +
512 + /**
513 + * Disconnects OVSDB server for a given node.
514 + *
515 + * @param node cordvtn node
516 + */
517 + private void disconnectOvsdb(CordVtnNode node) {
518 + checkNotNull(node);
519 +
520 + if (!nodeStore.containsKey(node)) {
521 + log.warn("Node {} does not exist", node.hostname());
522 + return;
523 + }
524 +
525 + if (getOvsdbConnectionState(node)) {
526 + OvsdbClientService ovsdbClient = getOvsdbClient(node);
527 + ovsdbClient.disconnect();
528 + }
529 + }
530 +
531 + /**
532 + * Returns OVSDB client for a given node.
533 + *
534 + * @param node cordvtn node
535 + * @return OVSDB client, or null if it fails to get OVSDB client
536 + */
537 + private OvsdbClientService getOvsdbClient(CordVtnNode node) {
538 + checkNotNull(node);
539 +
540 + OvsdbClientService ovsdbClient = controller.getOvsdbClient(
541 + new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt()));
542 + if (ovsdbClient == null) {
543 + log.trace("Couldn't find OVSDB client for {}", node.hostname());
544 + }
545 + return ovsdbClient;
546 + }
547 +
548 + /**
549 + * Creates an integration bridge for a given node.
550 + *
551 + * @param node cordvtn node
552 + */
553 + private void createIntegrationBridge(CordVtnNode node) {
554 + if (checkIntegrationBridge(node)) {
555 + return;
556 + }
557 +
558 + List<ControllerInfo> controllers = new ArrayList<>();
559 + Sets.newHashSet(clusterService.getNodes()).stream()
560 + .forEach(controller -> {
561 + ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
562 + controllers.add(ctrlInfo);
563 + });
564 +
565 + String dpid = node.intBrId().toString().substring(DPID_BEGIN);
566 +
567 + try {
568 + DriverHandler handler = driverService.createHandler(node.ovsdbId());
569 + BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
570 + bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
571 + } catch (ItemNotFoundException e) {
572 + log.warn("Failed to create integration bridge on {}", node.ovsdbId());
573 + }
574 + }
575 +
576 + /**
577 + * Creates tunnel interface to the integration bridge for a given node.
578 + *
579 + * @param node cordvtn node
580 + */
581 + private void createTunnelInterface(CordVtnNode node) {
582 + if (checkTunnelInterface(node)) {
583 + return;
584 + }
585 +
586 + DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
587 + for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
588 + optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
589 + }
590 +
591 + TunnelDescription description = new DefaultTunnelDescription(
592 + null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
593 + optionBuilder.build());
594 +
595 + try {
596 + DriverHandler handler = driverService.createHandler(node.ovsdbId());
597 + TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
598 + tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
599 + } catch (ItemNotFoundException e) {
600 + log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
601 + }
602 + }
603 +
604 + /**
605 + * Checks if integration bridge exists and available.
606 + *
607 + * @param node cordvtn node
608 + * @return true if the bridge is available, false otherwise
609 + */
610 + private boolean checkIntegrationBridge(CordVtnNode node) {
611 + return (deviceService.getDevice(node.intBrId()) != null
612 + && deviceService.isAvailable(node.intBrId()));
613 + }
614 +
615 + /**
616 + * Checks if tunnel interface exists.
617 + *
618 + * @param node cordvtn node
619 + * @return true if the interface exists, false otherwise
620 + */
621 + private boolean checkTunnelInterface(CordVtnNode node) {
622 + return deviceService.getPorts(node.intBrId())
623 + .stream()
624 + .filter(p -> getPortName(p).contains(DEFAULT_TUNNEL) &&
625 + p.isEnabled())
626 + .findAny().isPresent();
627 + }
628 +
629 + /**
630 + * Checks if physical interface exists.
631 + *
632 + * @param node cordvtn node
633 + * @return true if the interface exists, false otherwise
634 + */
635 + private boolean checkPhyInterface(CordVtnNode node) {
636 + return deviceService.getPorts(node.intBrId())
637 + .stream()
638 + .filter(p -> getPortName(p).contains(node.phyPortName()) &&
639 + p.isEnabled())
640 + .findAny().isPresent();
641 + }
642 +
643 + /**
644 + * Returns connect point of a given port.
645 + *
646 + * @param port port
647 + * @return connect point
648 + */
649 + private ConnectPoint getConnectPoint(Port port) {
650 + return new ConnectPoint(port.element().id(), port.number());
651 + }
652 +
653 + /**
654 + * Returns connect point of a given host.
655 + *
656 + * @param host host
657 + * @return connect point
658 + */
659 + private ConnectPoint getConnectPoint(Host host) {
660 + return new ConnectPoint(host.location().deviceId(), host.location().port());
661 + }
662 +
663 + private class OvsdbHandler implements ConnectionHandler<Device> {
664 +
665 + @Override
666 + public void connected(Device device) {
667 + CordVtnNode node = getNodeByOvsdbId(device.id());
668 + if (node != null) {
669 + setNodeState(node, checkNodeState(node));
670 + } else {
671 + log.debug("{} is detected on unregistered node, ignore it.", device.id());
672 + }
673 + }
674 +
675 + @Override
676 + public void disconnected(Device device) {
677 + if (!deviceService.isAvailable(device.id())) {
678 + adminService.removeDevice(device.id());
679 + }
680 + }
681 + }
682 +
683 + private class BridgeHandler implements ConnectionHandler<Device> {
684 +
685 + @Override
686 + public void connected(Device device) {
687 + CordVtnNode node = getNodeByBridgeId(device.id());
688 + if (node != null) {
689 + setNodeState(node, checkNodeState(node));
690 + } else {
691 + log.debug("{} is detected on unregistered node, ignore it.", device.id());
692 + }
693 + }
694 +
695 + @Override
696 + public void disconnected(Device device) {
697 + CordVtnNode node = getNodeByBridgeId(device.id());
698 + if (node != null) {
699 + log.debug("Integration Bridge is disconnected from {}", node.hostname());
700 + setNodeState(node, NodeState.INCOMPLETE);
701 + }
702 + }
703 +
704 + /**
705 + * Handles port added situation.
706 + * If the added port is tunnel or physical port, proceed remaining node
707 + * initialization. Otherwise, do nothing.
708 + *
709 + * @param port port
710 + */
711 + public void portAdded(Port port) {
712 + CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
713 + String portName = getPortName(port);
714 +
715 + if (node == null) {
716 + log.debug("{} is added to unregistered node, ignore it.", portName);
717 + return;
718 + }
719 +
720 + log.debug("Port {} is added to {}", portName, node.hostname());
721 +
722 + if (portName.startsWith(VPORT_PREFIX)) {
723 + if (getNodeInitState(node)) {
724 + cordVtnService.addServiceVm(node, getConnectPoint(port));
725 + } else {
726 + log.debug("VM is detected on incomplete node, ignore it.", portName);
727 + }
728 + } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.phyPortName())) {
729 + setNodeState(node, checkNodeState(node));
730 + }
731 + }
732 +
733 + /**
734 + * Handles port removed situation.
735 + * If the removed port is tunnel or physical port, proceed remaining node
736 + * initialization.Others, do nothing.
737 + *
738 + * @param port port
739 + */
740 + public void portRemoved(Port port) {
741 + CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id());
742 + String portName = getPortName(port);
743 +
744 + if (node == null) {
745 + return;
746 + }
747 +
748 + log.debug("Port {} is removed from {}", portName, node.hostname());
749 +
750 + if (portName.startsWith(VPORT_PREFIX)) {
751 + if (getNodeInitState(node)) {
752 + cordVtnService.removeServiceVm(getConnectPoint(port));
753 + } else {
754 + log.debug("VM is vanished from incomplete node, ignore it.", portName);
755 + }
756 + } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.phyPortName())) {
757 + setNodeState(node, NodeState.INCOMPLETE);
758 + }
759 + }
760 + }
761 +
762 + private class InternalDeviceListener implements DeviceListener {
763 +
764 + @Override
765 + public void event(DeviceEvent event) {
766 +
767 + Device device = event.subject();
768 + ConnectionHandler<Device> handler =
769 + (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
770 +
771 + switch (event.type()) {
772 + case PORT_ADDED:
773 + eventExecutor.submit(() -> bridgeHandler.portAdded(event.port()));
774 + break;
775 + case PORT_UPDATED:
776 + if (!event.port().isEnabled()) {
777 + eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port()));
778 + }
779 + break;
780 + case DEVICE_ADDED:
781 + case DEVICE_AVAILABILITY_CHANGED:
782 + if (deviceService.isAvailable(device.id())) {
783 + eventExecutor.submit(() -> handler.connected(device));
784 + } else {
785 + eventExecutor.submit(() -> handler.disconnected(device));
786 + }
787 + break;
788 + default:
789 + break;
790 + }
791 + }
792 + }
793 +
794 + /**
795 + * Reads node configuration from config file.
796 + */
797 + private void readConfiguration() {
798 + CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
799 +
800 + if (config == null) {
801 + log.warn("No configuration found");
802 + return;
803 + }
804 +
805 + config.cordVtnNodes().forEach(node -> {
806 + CordVtnNode cordVtnNode = new CordVtnNode(
807 + node.hostname(),
808 + node.ovsdbIp(),
809 + node.ovsdbPort(),
810 + node.bridgeId(),
811 + node.phyPortName(),
812 + node.localIp());
813 +
814 + addNode(cordVtnNode);
815 + });
816 + }
817 +
818 + private class InternalConfigListener implements NetworkConfigListener {
819 +
820 + @Override
821 + public void event(NetworkConfigEvent event) {
822 + if (!event.configClass().equals(CordVtnConfig.class)) {
823 + return;
824 + }
825 +
826 + switch (event.type()) {
827 + case CONFIG_ADDED:
828 + log.info("Network configuration added");
829 + eventExecutor.execute(CordVtnNodeManager.this::readConfiguration);
830 + break;
831 + case CONFIG_UPDATED:
832 + log.info("Network configuration updated");
833 + eventExecutor.execute(CordVtnNodeManager.this::readConfiguration);
834 + break;
835 + default:
836 + break;
837 + }
838 + }
839 + }
840 +}
...@@ -165,13 +165,10 @@ public class CordVtnRuleInstaller { ...@@ -165,13 +165,10 @@ public class CordVtnRuleInstaller {
165 * Populates basic rules that connect a VM to the other VMs in the system. 165 * Populates basic rules that connect a VM to the other VMs in the system.
166 * 166 *
167 * @param host host 167 * @param host host
168 - * @param hostIp host ip
169 * @param tunnelIp tunnel ip 168 * @param tunnelIp tunnel ip
170 * @param vNet openstack network 169 * @param vNet openstack network
171 */ 170 */
172 - public void populateBasicConnectionRules(Host host, IpAddress hostIp, IpAddress tunnelIp, 171 + public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
173 - OpenstackNetwork vNet) {
174 - // TODO we can get host ip from host.ip() after applying NetworkConfig host provider
175 checkNotNull(host); 172 checkNotNull(host);
176 checkNotNull(vNet); 173 checkNotNull(vNet);
177 174
...@@ -182,6 +179,7 @@ public class CordVtnRuleInstaller { ...@@ -182,6 +179,7 @@ public class CordVtnRuleInstaller {
182 179
183 PortNumber inPort = host.location().port(); 180 PortNumber inPort = host.location().port();
184 MacAddress dstMac = host.mac(); 181 MacAddress dstMac = host.mac();
182 + IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
185 long tunnelId = Long.parseLong(vNet.segmentId()); 183 long tunnelId = Long.parseLong(vNet.segmentId());
186 184
187 OpenstackSubnet subnet = vNet.subnets().stream() 185 OpenstackSubnet subnet = vNet.subnets().stream()
...@@ -352,7 +350,7 @@ public class CordVtnRuleInstaller { ...@@ -352,7 +350,7 @@ public class CordVtnRuleInstaller {
352 350
353 Group group = groupService.getGroup(deviceId, groupKey); 351 Group group = groupService.getGroup(deviceId, groupKey);
354 if (group == null) { 352 if (group == null) {
355 - log.debug("No group exists for service {} in {}", service.id(), deviceId); 353 + log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
356 continue; 354 continue;
357 } 355 }
358 356
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onosproject.cordvtn; 16 package org.onosproject.cordvtn;
17 17
18 -import java.util.List; 18 +import org.onosproject.net.ConnectPoint;
19 19
20 /** 20 /**
21 * Service for provisioning overlay virtual networks on compute nodes. 21 * Service for provisioning overlay virtual networks on compute nodes.
...@@ -23,61 +23,21 @@ import java.util.List; ...@@ -23,61 +23,21 @@ import java.util.List;
23 public interface CordVtnService { 23 public interface CordVtnService {
24 24
25 String CORDVTN_APP_ID = "org.onosproject.cordvtn"; 25 String CORDVTN_APP_ID = "org.onosproject.cordvtn";
26 - /**
27 - * Adds a new node to the service.
28 - *
29 - * @param node cordvtn node
30 - */
31 - void addNode(CordVtnNode node);
32 -
33 - /**
34 - * Deletes a node from the service.
35 - *
36 - * @param node cordvtn node
37 - */
38 - void deleteNode(CordVtnNode node);
39 -
40 - /**
41 - * Initiates node to serve virtual tenant network.
42 - *
43 - * @param node cordvtn node
44 - */
45 - void initNode(CordVtnNode node);
46 -
47 - /**
48 - * Returns the number of the nodes known to the service.
49 - *
50 - * @return number of nodes
51 - */
52 - int getNodeCount();
53 26
54 /** 27 /**
55 - * Returns node initialization state. 28 + * Adds a new VM on a given node and connect point.
56 - *
57 - * @param node cordvtn node
58 - * @return true if initial node setup is completed, otherwise false
59 - */
60 - boolean getNodeInitState(CordVtnNode node);
61 -
62 - /**
63 - * Returns detailed node initialization state.
64 - * Return string includes the following information.
65 - *
66 - * Integration bridge created/connected: OK or NO
67 - * VXLAN interface created: OK or NO
68 - * Physical interface added: OK or NO
69 * 29 *
70 * @param node cordvtn node 30 * @param node cordvtn node
71 - * @return string including detailed node init state 31 + * @param connectPoint connect point
72 */ 32 */
73 - String checkNodeInitState(CordVtnNode node); 33 + void addServiceVm(CordVtnNode node, ConnectPoint connectPoint);
74 34
75 /** 35 /**
76 - * Returns all nodes known to the service. 36 + * Removes a VM from a given node and connect point.
77 * 37 *
78 - * @return list of nodes 38 + * @param connectPoint connect point
79 */ 39 */
80 - List<CordVtnNode> getNodes(); 40 + void removeServiceVm(ConnectPoint connectPoint);
81 41
82 /** 42 /**
83 * Creates dependencies for a given tenant service. 43 * Creates dependencies for a given tenant service.
......
...@@ -21,7 +21,7 @@ import org.apache.karaf.shell.commands.Command; ...@@ -21,7 +21,7 @@ import org.apache.karaf.shell.commands.Command;
21 import org.onlab.packet.IpAddress; 21 import org.onlab.packet.IpAddress;
22 import org.onlab.packet.TpPort; 22 import org.onlab.packet.TpPort;
23 import org.onosproject.cli.AbstractShellCommand; 23 import org.onosproject.cli.AbstractShellCommand;
24 -import org.onosproject.cordvtn.CordVtnService; 24 +import org.onosproject.cordvtn.CordVtnNodeManager;
25 import org.onosproject.cordvtn.CordVtnNode; 25 import org.onosproject.cordvtn.CordVtnNode;
26 import org.onosproject.net.DeviceId; 26 import org.onosproject.net.DeviceId;
27 27
...@@ -63,7 +63,7 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { ...@@ -63,7 +63,7 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand {
63 checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format"); 63 checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format");
64 checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format"); 64 checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format");
65 65
66 - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); 66 + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
67 String[] ipPort = ovsdb.split(":"); 67 String[] ipPort = ovsdb.split(":");
68 CordVtnNode node = new CordVtnNode(hostname, 68 CordVtnNode node = new CordVtnNode(hostname,
69 IpAddress.valueOf(ipPort[0]), 69 IpAddress.valueOf(ipPort[0]),
...@@ -71,6 +71,6 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { ...@@ -71,6 +71,6 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand {
71 DeviceId.deviceId(bridgeId), 71 DeviceId.deviceId(bridgeId),
72 phyPortName, 72 phyPortName,
73 IpAddress.valueOf(localIp)); 73 IpAddress.valueOf(localIp));
74 - service.addNode(node); 74 + nodeManager.addNode(node);
75 } 75 }
76 } 76 }
......
...@@ -20,7 +20,7 @@ import org.apache.karaf.shell.commands.Argument; ...@@ -20,7 +20,7 @@ import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command; 20 import org.apache.karaf.shell.commands.Command;
21 import org.onosproject.cli.AbstractShellCommand; 21 import org.onosproject.cli.AbstractShellCommand;
22 import org.onosproject.cordvtn.CordVtnNode; 22 import org.onosproject.cordvtn.CordVtnNode;
23 -import org.onosproject.cordvtn.CordVtnService; 23 +import org.onosproject.cordvtn.CordVtnNodeManager;
24 24
25 /** 25 /**
26 * Checks detailed node init state. 26 * Checks detailed node init state.
...@@ -35,8 +35,8 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { ...@@ -35,8 +35,8 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand {
35 35
36 @Override 36 @Override
37 protected void execute() { 37 protected void execute() {
38 - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); 38 + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
39 - CordVtnNode node = service.getNodes() 39 + CordVtnNode node = nodeManager.getNodes()
40 .stream() 40 .stream()
41 .filter(n -> n.hostname().equals(hostname)) 41 .filter(n -> n.hostname().equals(hostname))
42 .findFirst() 42 .findFirst()
...@@ -47,6 +47,6 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { ...@@ -47,6 +47,6 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand {
47 return; 47 return;
48 } 48 }
49 49
50 - print(service.checkNodeInitState(node)); 50 + print(nodeManager.checkNodeInitState(node));
51 } 51 }
52 } 52 }
......
...@@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; ...@@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli;
19 import org.apache.karaf.shell.commands.Argument; 19 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command; 20 import org.apache.karaf.shell.commands.Command;
21 import org.onosproject.cli.AbstractShellCommand; 21 import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordvtn.CordVtnService; 22 +import org.onosproject.cordvtn.CordVtnNodeManager;
23 import org.onosproject.cordvtn.CordVtnNode; 23 import org.onosproject.cordvtn.CordVtnNode;
24 24
25 import java.util.NoSuchElementException; 25 import java.util.NoSuchElementException;
...@@ -37,12 +37,12 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { ...@@ -37,12 +37,12 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
37 37
38 @Override 38 @Override
39 protected void execute() { 39 protected void execute() {
40 - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); 40 + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
41 41
42 for (String hostname : hostnames) { 42 for (String hostname : hostnames) {
43 CordVtnNode node; 43 CordVtnNode node;
44 try { 44 try {
45 - node = service.getNodes() 45 + node = nodeManager.getNodes()
46 .stream() 46 .stream()
47 .filter(n -> n.hostname().equals(hostname)) 47 .filter(n -> n.hostname().equals(hostname))
48 .findFirst().get(); 48 .findFirst().get();
...@@ -51,7 +51,7 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { ...@@ -51,7 +51,7 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
51 continue; 51 continue;
52 } 52 }
53 53
54 - service.deleteNode(node); 54 + nodeManager.deleteNode(node);
55 } 55 }
56 } 56 }
57 } 57 }
......
...@@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; ...@@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli;
19 import org.apache.karaf.shell.commands.Argument; 19 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command; 20 import org.apache.karaf.shell.commands.Command;
21 import org.onosproject.cli.AbstractShellCommand; 21 import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordvtn.CordVtnService; 22 +import org.onosproject.cordvtn.CordVtnNodeManager;
23 import org.onosproject.cordvtn.CordVtnNode; 23 import org.onosproject.cordvtn.CordVtnNode;
24 24
25 import java.util.NoSuchElementException; 25 import java.util.NoSuchElementException;
...@@ -37,12 +37,12 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { ...@@ -37,12 +37,12 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand {
37 37
38 @Override 38 @Override
39 protected void execute() { 39 protected void execute() {
40 - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); 40 + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
41 41
42 for (String hostname : hostnames) { 42 for (String hostname : hostnames) {
43 CordVtnNode node; 43 CordVtnNode node;
44 try { 44 try {
45 - node = service.getNodes() 45 + node = nodeManager.getNodes()
46 .stream() 46 .stream()
47 .filter(n -> n.hostname().equals(hostname)) 47 .filter(n -> n.hostname().equals(hostname))
48 .findFirst().get(); 48 .findFirst().get();
...@@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { ...@@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand {
51 continue; 51 continue;
52 } 52 }
53 53
54 - service.initNode(node); 54 + nodeManager.initNode(node);
55 } 55 }
56 } 56 }
57 } 57 }
......
...@@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
21 import com.fasterxml.jackson.databind.node.ArrayNode; 21 import com.fasterxml.jackson.databind.node.ArrayNode;
22 import org.apache.karaf.shell.commands.Command; 22 import org.apache.karaf.shell.commands.Command;
23 import org.onosproject.cli.AbstractShellCommand; 23 import org.onosproject.cli.AbstractShellCommand;
24 -import org.onosproject.cordvtn.CordVtnService; 24 +import org.onosproject.cordvtn.CordVtnNodeManager;
25 import org.onosproject.cordvtn.CordVtnNode; 25 import org.onosproject.cordvtn.CordVtnNode;
26 26
27 import java.util.Collections; 27 import java.util.Collections;
...@@ -36,12 +36,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { ...@@ -36,12 +36,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand {
36 36
37 @Override 37 @Override
38 protected void execute() { 38 protected void execute() {
39 - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); 39 + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
40 - List<CordVtnNode> nodes = service.getNodes(); 40 + List<CordVtnNode> nodes = nodeManager.getNodes();
41 Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR); 41 Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR);
42 42
43 if (outputJson()) { 43 if (outputJson()) {
44 - print("%s", json(service, nodes)); 44 + print("%s", json(nodeManager, nodes));
45 } else { 45 } else {
46 for (CordVtnNode node : nodes) { 46 for (CordVtnNode node : nodes) {
47 print("hostname=%s, ovsdb=%s, br-int=%s, phyPort=%s, localIp=%s, init=%s", 47 print("hostname=%s, ovsdb=%s, br-int=%s, phyPort=%s, localIp=%s, init=%s",
...@@ -50,13 +50,13 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { ...@@ -50,13 +50,13 @@ public class CordVtnNodeListCommand extends AbstractShellCommand {
50 node.intBrId().toString(), 50 node.intBrId().toString(),
51 node.phyPortName(), 51 node.phyPortName(),
52 node.localIp().toString(), 52 node.localIp().toString(),
53 - getState(service, node)); 53 + getState(nodeManager, node));
54 } 54 }
55 - print("Total %s nodes", service.getNodeCount()); 55 + print("Total %s nodes", nodeManager.getNodeCount());
56 } 56 }
57 } 57 }
58 58
59 - private JsonNode json(CordVtnService service, List<CordVtnNode> nodes) { 59 + private JsonNode json(CordVtnNodeManager nodeManager, List<CordVtnNode> nodes) {
60 ObjectMapper mapper = new ObjectMapper(); 60 ObjectMapper mapper = new ObjectMapper();
61 ArrayNode result = mapper.createArrayNode(); 61 ArrayNode result = mapper.createArrayNode();
62 for (CordVtnNode node : nodes) { 62 for (CordVtnNode node : nodes) {
...@@ -67,12 +67,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { ...@@ -67,12 +67,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand {
67 .put("brInt", node.intBrId().toString()) 67 .put("brInt", node.intBrId().toString())
68 .put("phyPort", node.phyPortName()) 68 .put("phyPort", node.phyPortName())
69 .put("localIp", node.localIp().toString()) 69 .put("localIp", node.localIp().toString())
70 - .put("init", getState(service, node))); 70 + .put("init", getState(nodeManager, node)));
71 } 71 }
72 return result; 72 return result;
73 } 73 }
74 74
75 - private String getState(CordVtnService service, CordVtnNode node) { 75 + private String getState(CordVtnNodeManager nodeManager, CordVtnNode node) {
76 - return service.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE"; 76 + return nodeManager.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE";
77 } 77 }
78 } 78 }
......