Hyunsun Moon
Committed by Gerrit Code Review

ONOS-4660 Additional GATEWAY type node bootstrap

- Add uplink interface to the router bridge
- Set separate controller for the router bridge
- Use OVSDB provider to check the ports list and keep OVSDB session

Limitation:
OVSDB provider does not provide port or bridge updates, that is,
any changes on the router bridge may not be detected by ONOS

Change-Id: I1f17f4fb2c050afdbda1e5ffc06f6485903d3d90
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
23 "managementIp" : "10.203.198.125", 23 "managementIp" : "10.203.198.125",
24 "dataIp" : "10.134.33.208", 24 "dataIp" : "10.134.33.208",
25 "integrationBridge" : "of:00000000000000a3", 25 "integrationBridge" : "of:00000000000000a3",
26 - "routerBridge" : "of:00000000000000b1" 26 + "routerBridge" : "of:00000000000000b3",
27 + "uplinkPort" : "veth1",
28 + "routerController" : "172.17.0.2"
27 }, 29 },
28 { 30 {
29 "hostname" : "gateway-02", 31 "hostname" : "gateway-02",
...@@ -31,7 +33,9 @@ ...@@ -31,7 +33,9 @@
31 "managementIp" : "10.203.198.131", 33 "managementIp" : "10.203.198.131",
32 "dataIp" : "10.134.33.209", 34 "dataIp" : "10.134.33.209",
33 "integrationBridge" : "of:00000000000000a4", 35 "integrationBridge" : "of:00000000000000a4",
34 - "routerBridge" : "of:00000000000000b2" 36 + "routerBridge" : "of:00000000000000b4",
37 + "uplinkPort" : "veth1",
38 + "routerController" : "172.17.0.2"
35 } 39 }
36 ] 40 ]
37 } 41 }
......
...@@ -28,4 +28,8 @@ public final class Constants { ...@@ -28,4 +28,8 @@ public final class Constants {
28 public static final String DEFAULT_TUNNEL = "vxlan"; 28 public static final String DEFAULT_TUNNEL = "vxlan";
29 public static final String PATCH_INTG_BRIDGE = "patch-intg"; 29 public static final String PATCH_INTG_BRIDGE = "patch-intg";
30 public static final String PATCH_ROUT_BRIDGE = "patch-rout"; 30 public static final String PATCH_ROUT_BRIDGE = "patch-rout";
31 +
32 + public static final int DEFAULT_OVSDB_PORT = 6640;
33 + public static final int DEFAULT_OFPORT = 6653;
34 + public static final String DEFAULT_OF_PROTO = "tcp";
31 } 35 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -41,6 +41,9 @@ public final class OpenstackNode { ...@@ -41,6 +41,9 @@ public final class OpenstackNode {
41 private final IpAddress dataIp; 41 private final IpAddress dataIp;
42 private final DeviceId integrationBridge; 42 private final DeviceId integrationBridge;
43 private final Optional<DeviceId> routerBridge; 43 private final Optional<DeviceId> routerBridge;
44 + private final Optional<String> uplink;
45 + // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
46 + private final Optional<IpAddress> routerController;
44 private final NodeState state; 47 private final NodeState state;
45 48
46 public static final Comparator<OpenstackNode> OPENSTACK_NODE_COMPARATOR = 49 public static final Comparator<OpenstackNode> OPENSTACK_NODE_COMPARATOR =
...@@ -52,6 +55,8 @@ public final class OpenstackNode { ...@@ -52,6 +55,8 @@ public final class OpenstackNode {
52 IpAddress dataIp, 55 IpAddress dataIp,
53 DeviceId integrationBridge, 56 DeviceId integrationBridge,
54 Optional<DeviceId> routerBridge, 57 Optional<DeviceId> routerBridge,
58 + Optional<String> uplink,
59 + Optional<IpAddress> routerController,
55 NodeState state) { 60 NodeState state) {
56 this.hostname = hostname; 61 this.hostname = hostname;
57 this.type = type; 62 this.type = type;
...@@ -59,6 +64,8 @@ public final class OpenstackNode { ...@@ -59,6 +64,8 @@ public final class OpenstackNode {
59 this.dataIp = dataIp; 64 this.dataIp = dataIp;
60 this.integrationBridge = integrationBridge; 65 this.integrationBridge = integrationBridge;
61 this.routerBridge = routerBridge; 66 this.routerBridge = routerBridge;
67 + this.uplink = uplink;
68 + this.routerController = routerController;
62 this.state = state; 69 this.state = state;
63 } 70 }
64 71
...@@ -76,6 +83,8 @@ public final class OpenstackNode { ...@@ -76,6 +83,8 @@ public final class OpenstackNode {
76 node.dataIp, 83 node.dataIp,
77 node.integrationBridge, 84 node.integrationBridge,
78 node.routerBridge, 85 node.routerBridge,
86 + node.uplink,
87 + node.routerController,
79 state); 88 state);
80 } 89 }
81 90
...@@ -135,6 +144,27 @@ public final class OpenstackNode { ...@@ -135,6 +144,27 @@ public final class OpenstackNode {
135 } 144 }
136 145
137 /** 146 /**
147 + * Returns the router bridge controller.
148 + * It returns valid value only if the node type is GATEWAY.
149 + *
150 + * @return device id; or empty value
151 + */
152 + // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
153 + public Optional<IpAddress> routerController() {
154 + return routerController;
155 + }
156 +
157 + /**
158 + * Returns the uplink interface name.
159 + * It returns valid value only if the node type is GATEWAY.
160 + *
161 + * @return uplink interface name; or empty value
162 + */
163 + public Optional<String> uplink() {
164 + return uplink;
165 + }
166 +
167 + /**
138 * Returns the init state of the node. 168 * Returns the init state of the node.
139 * 169 *
140 * @return init state 170 * @return init state
...@@ -165,7 +195,9 @@ public final class OpenstackNode { ...@@ -165,7 +195,9 @@ public final class OpenstackNode {
165 Objects.equals(managementIp, that.managementIp) && 195 Objects.equals(managementIp, that.managementIp) &&
166 Objects.equals(dataIp, that.dataIp) && 196 Objects.equals(dataIp, that.dataIp) &&
167 Objects.equals(integrationBridge, that.integrationBridge) && 197 Objects.equals(integrationBridge, that.integrationBridge) &&
168 - Objects.equals(routerBridge, that.routerBridge)) { 198 + Objects.equals(routerBridge, that.routerBridge) &&
199 + Objects.equals(uplink, that.uplink) &&
200 + Objects.equals(routerController, that.routerController)) {
169 return true; 201 return true;
170 } 202 }
171 } 203 }
...@@ -179,7 +211,9 @@ public final class OpenstackNode { ...@@ -179,7 +211,9 @@ public final class OpenstackNode {
179 managementIp, 211 managementIp,
180 dataIp, 212 dataIp,
181 integrationBridge, 213 integrationBridge,
182 - routerBridge); 214 + routerBridge,
215 + uplink,
216 + routerController);
183 } 217 }
184 218
185 @Override 219 @Override
...@@ -191,6 +225,8 @@ public final class OpenstackNode { ...@@ -191,6 +225,8 @@ public final class OpenstackNode {
191 .add("dataIp", dataIp) 225 .add("dataIp", dataIp)
192 .add("integrationBridge", integrationBridge) 226 .add("integrationBridge", integrationBridge)
193 .add("routerBridge", routerBridge) 227 .add("routerBridge", routerBridge)
228 + .add("uplink", uplink)
229 + .add("routerController", routerController)
194 .add("state", state) 230 .add("state", state)
195 .toString(); 231 .toString();
196 } 232 }
...@@ -214,6 +250,9 @@ public final class OpenstackNode { ...@@ -214,6 +250,9 @@ public final class OpenstackNode {
214 private IpAddress dataIp; 250 private IpAddress dataIp;
215 private DeviceId integrationBridge; 251 private DeviceId integrationBridge;
216 private Optional<DeviceId> routerBridge = Optional.empty(); 252 private Optional<DeviceId> routerBridge = Optional.empty();
253 + private Optional<String> uplink = Optional.empty();
254 + // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
255 + private Optional<IpAddress> routerController = Optional.empty();
217 private NodeState state = INIT; 256 private NodeState state = INIT;
218 257
219 private Builder() { 258 private Builder() {
...@@ -226,12 +265,23 @@ public final class OpenstackNode { ...@@ -226,12 +265,23 @@ public final class OpenstackNode {
226 checkNotNull(dataIp); 265 checkNotNull(dataIp);
227 checkNotNull(integrationBridge); 266 checkNotNull(integrationBridge);
228 checkNotNull(routerBridge); 267 checkNotNull(routerBridge);
268 + checkNotNull(uplink);
269 + checkNotNull(routerController);
270 +
271 + if (type == NodeType.GATEWAY) {
272 + checkArgument(routerBridge.isPresent());
273 + checkArgument(uplink.isPresent());
274 + checkArgument(routerController.isPresent());
275 + }
276 +
229 return new OpenstackNode(hostname, 277 return new OpenstackNode(hostname,
230 type, 278 type,
231 managementIp, 279 managementIp,
232 dataIp, 280 dataIp,
233 integrationBridge, 281 integrationBridge,
234 routerBridge, 282 routerBridge,
283 + uplink,
284 + routerController,
235 state); 285 state);
236 } 286 }
237 287
...@@ -302,6 +352,29 @@ public final class OpenstackNode { ...@@ -302,6 +352,29 @@ public final class OpenstackNode {
302 } 352 }
303 353
304 /** 354 /**
355 + * Returns node builder with the uplink interface name.
356 + *
357 + * @param uplink uplink interface name
358 + * @return openstack node builder
359 + */
360 + public Builder uplink(String uplink) {
361 + this.uplink = Optional.ofNullable(uplink);
362 + return this;
363 + }
364 +
365 + /**
366 + * Returns node builder with the router controller.
367 + *
368 + * @param routerController router contoller
369 + * @return openstack node builder
370 + */
371 + // TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
372 + public Builder routerController(IpAddress routerController) {
373 + this.routerController = Optional.ofNullable(routerController);
374 + return this;
375 + }
376 +
377 + /**
305 * Returns node builder with the init state. 378 * Returns node builder with the init state.
306 * 379 *
307 * @param state node init state 380 * @param state node init state
......
...@@ -40,7 +40,12 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> { ...@@ -40,7 +40,12 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
40 private static final String MANAGEMENT_IP = "managementIp"; 40 private static final String MANAGEMENT_IP = "managementIp";
41 private static final String DATA_IP = "dataIp"; 41 private static final String DATA_IP = "dataIp";
42 private static final String INTEGRATION_BRIDGE = "integrationBridge"; 42 private static final String INTEGRATION_BRIDGE = "integrationBridge";
43 +
44 + // GATEWAY node specific fields
43 private static final String ROUTER_BRIDGE = "routerBridge"; 45 private static final String ROUTER_BRIDGE = "routerBridge";
46 + private static final String UPLINK_PORT_NAME = "uplinkPort";
47 + // TODO remove this when vRouter supports multiple switches
48 + private static final String ROUTER_CONTROLLER = "routerController";
44 49
45 @Override 50 @Override
46 public boolean isValid() { 51 public boolean isValid() {
...@@ -59,7 +64,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> { ...@@ -59,7 +64,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
59 MANAGEMENT_IP, 64 MANAGEMENT_IP,
60 DATA_IP, 65 DATA_IP,
61 INTEGRATION_BRIDGE, 66 INTEGRATION_BRIDGE,
62 - ROUTER_BRIDGE 67 + ROUTER_BRIDGE,
68 + UPLINK_PORT_NAME,
69 + ROUTER_CONTROLLER
63 ); 70 );
64 71
65 result &= isString(osNode, HOST_NAME, MANDATORY); 72 result &= isString(osNode, HOST_NAME, MANDATORY);
...@@ -74,6 +81,8 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> { ...@@ -74,6 +81,8 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
74 if (osNode.get(TYPE).asText().equals(GATEWAY.name())) { 81 if (osNode.get(TYPE).asText().equals(GATEWAY.name())) {
75 result &= isString(osNode, ROUTER_BRIDGE, MANDATORY); 82 result &= isString(osNode, ROUTER_BRIDGE, MANDATORY);
76 DeviceId.deviceId(osNode.get(ROUTER_BRIDGE).asText()); 83 DeviceId.deviceId(osNode.get(ROUTER_BRIDGE).asText());
84 + result &= isString(osNode, UPLINK_PORT_NAME, MANDATORY);
85 + result &= isIpAddress(osNode, ROUTER_CONTROLLER, MANDATORY);
77 } 86 }
78 } 87 }
79 return result; 88 return result;
...@@ -97,7 +106,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> { ...@@ -97,7 +106,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
97 .hostname(get(node, HOST_NAME)); 106 .hostname(get(node, HOST_NAME));
98 107
99 if (type.equals(GATEWAY)) { 108 if (type.equals(GATEWAY)) {
100 - nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE))); 109 + nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)))
110 + .uplink(get(node, UPLINK_PORT_NAME))
111 + .routerController(IpAddress.valueOf(get(node, ROUTER_CONTROLLER)));
101 } 112 }
102 nodes.add(nodeBuilder.build()); 113 nodes.add(nodeBuilder.build());
103 } 114 }
......
...@@ -30,6 +30,7 @@ import org.onlab.util.KryoNamespace; ...@@ -30,6 +30,7 @@ import org.onlab.util.KryoNamespace;
30 import org.onlab.util.Tools; 30 import org.onlab.util.Tools;
31 import org.onosproject.cfg.ComponentConfigService; 31 import org.onosproject.cfg.ComponentConfigService;
32 import org.onosproject.cluster.ClusterService; 32 import org.onosproject.cluster.ClusterService;
33 +import org.onosproject.cluster.ControllerNode;
33 import org.onosproject.cluster.LeadershipService; 34 import org.onosproject.cluster.LeadershipService;
34 import org.onosproject.cluster.NodeId; 35 import org.onosproject.cluster.NodeId;
35 import org.onosproject.core.ApplicationId; 36 import org.onosproject.core.ApplicationId;
...@@ -41,6 +42,7 @@ import org.onosproject.net.Port; ...@@ -41,6 +42,7 @@ import org.onosproject.net.Port;
41 import org.onosproject.net.PortNumber; 42 import org.onosproject.net.PortNumber;
42 import org.onosproject.net.behaviour.BridgeConfig; 43 import org.onosproject.net.behaviour.BridgeConfig;
43 import org.onosproject.net.behaviour.BridgeDescription; 44 import org.onosproject.net.behaviour.BridgeDescription;
45 +import org.onosproject.net.behaviour.BridgeName;
44 import org.onosproject.net.behaviour.ControllerInfo; 46 import org.onosproject.net.behaviour.ControllerInfo;
45 import org.onosproject.net.behaviour.DefaultBridgeDescription; 47 import org.onosproject.net.behaviour.DefaultBridgeDescription;
46 import org.onosproject.net.behaviour.DefaultPatchDescription; 48 import org.onosproject.net.behaviour.DefaultPatchDescription;
...@@ -72,6 +74,7 @@ import org.onosproject.store.service.Versioned; ...@@ -72,6 +74,7 @@ import org.onosproject.store.service.Versioned;
72 import org.osgi.service.component.ComponentContext; 74 import org.osgi.service.component.ComponentContext;
73 import org.slf4j.Logger; 75 import org.slf4j.Logger;
74 76
77 +import static com.google.common.base.Preconditions.checkArgument;
75 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; 78 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
76 import static org.onlab.util.Tools.groupedThreads; 79 import static org.onlab.util.Tools.groupedThreads;
77 import static org.onosproject.net.AnnotationKeys.PORT_NAME; 80 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
...@@ -89,7 +92,6 @@ import java.util.Set; ...@@ -89,7 +92,6 @@ import java.util.Set;
89 import java.util.concurrent.ExecutorService; 92 import java.util.concurrent.ExecutorService;
90 import java.util.stream.Collectors; 93 import java.util.stream.Collectors;
91 94
92 -
93 /** 95 /**
94 * Initializes devices in compute/gateway nodes according to there type. 96 * Initializes devices in compute/gateway nodes according to there type.
95 */ 97 */
...@@ -106,8 +108,6 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -106,8 +108,6 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
106 .register(NodeState.class); 108 .register(NodeState.class);
107 109
108 private static final String OVSDB_PORT = "ovsdbPort"; 110 private static final String OVSDB_PORT = "ovsdbPort";
109 - private static final int DEFAULT_OVSDB_PORT = 6640;
110 - private static final int DEFAULT_OFPORT = 6653;
111 private static final int DPID_BEGIN = 3; 111 private static final int DPID_BEGIN = 3;
112 112
113 private static final String APP_ID = "org.onosproject.openstacknode"; 113 private static final String APP_ID = "org.onosproject.openstacknode";
...@@ -120,7 +120,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -120,7 +120,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
120 protected DeviceService deviceService; 120 protected DeviceService deviceService;
121 121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 - protected OvsdbController controller; 123 + protected OvsdbController ovsdbController;
124 124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected ClusterService clusterService; 126 protected ClusterService clusterService;
...@@ -142,7 +142,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -142,7 +142,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
142 private int ovsdbPort = DEFAULT_OVSDB_PORT; 142 private int ovsdbPort = DEFAULT_OVSDB_PORT;
143 143
144 private final ExecutorService eventExecutor = 144 private final ExecutorService eventExecutor =
145 - newSingleThreadScheduledExecutor(groupedThreads("onos/openstack-node", "event-handler")); 145 + newSingleThreadScheduledExecutor(groupedThreads("onos/openstack-node", "event-handler", log));
146 146
147 private final ConfigFactory configFactory = 147 private final ConfigFactory configFactory =
148 new ConfigFactory<ApplicationId, OpenstackNodeConfig>( 148 new ConfigFactory<ApplicationId, OpenstackNodeConfig>(
...@@ -221,10 +221,6 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -221,10 +221,6 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
221 221
222 @Override 222 @Override
223 public void deleteNode(OpenstackNode node) { 223 public void deleteNode(OpenstackNode node) {
224 - if (isOvsdbConnected(node)) {
225 - OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
226 - controller.getOvsdbClient(ovsdb).disconnect();
227 - }
228 nodeStore.remove(node.hostname()); 224 nodeStore.remove(node.hostname());
229 process(new OpenstackNodeEvent(INCOMPLETE, node)); 225 process(new OpenstackNodeEvent(INCOMPLETE, node));
230 } 226 }
...@@ -236,15 +232,13 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -236,15 +232,13 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
236 connectOvsdb(node); 232 connectOvsdb(node);
237 return; 233 return;
238 } 234 }
239 -
240 process(new OpenstackNodeEvent(INIT, node)); 235 process(new OpenstackNodeEvent(INIT, node));
241 - createBridge(node, INTEGRATION_BRIDGE,
242 - node.intBridge().toString().substring(DPID_BEGIN));
243 236
244 - // creates additional router bridge if the node type is GATEWAY 237 + createBridge(node, INTEGRATION_BRIDGE, node.intBridge());
245 if (node.type().equals(NodeType.GATEWAY)) { 238 if (node.type().equals(NodeType.GATEWAY)) {
246 - createBridge(node, ROUTER_BRIDGE, 239 + createBridge(node, ROUTER_BRIDGE, node.routerBridge().get());
247 - node.routerBridge().get().toString().substring(DPID_BEGIN)); 240 + // TODO remove this when OVSDB provides port event
241 + setNodeState(node, nodeState(node));
248 } 242 }
249 } 243 }
250 244
...@@ -256,20 +250,18 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -256,20 +250,18 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
256 return; 250 return;
257 } 251 }
258 process(new OpenstackNodeEvent(DEVICE_CREATED, node)); 252 process(new OpenstackNodeEvent(DEVICE_CREATED, node));
253 +
259 createTunnelInterface(node); 254 createTunnelInterface(node);
260 - // creates additional patch ports connecting integration bridge and
261 - // router bridge if the node type is GATEWAY
262 if (node.type().equals(NodeType.GATEWAY)) { 255 if (node.type().equals(NodeType.GATEWAY)) {
263 createPatchInterface(node); 256 createPatchInterface(node);
257 + addUplink(node);
258 + // TODO remove this when OVSDB provides port event
259 + setNodeState(node, nodeState(node));
264 } 260 }
265 } 261 }
266 262
267 @Override 263 @Override
268 public void processCompleteState(OpenstackNode node) { 264 public void processCompleteState(OpenstackNode node) {
269 - if (isOvsdbConnected(node)) {
270 - OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
271 - controller.getOvsdbClient(ovsdb).disconnect();
272 - }
273 process(new OpenstackNodeEvent(COMPLETE, node)); 265 process(new OpenstackNodeEvent(COMPLETE, node));
274 log.info("Finished init {}", node.hostname()); 266 log.info("Finished init {}", node.hostname());
275 } 267 }
...@@ -334,50 +326,84 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -334,50 +326,84 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
334 } 326 }
335 327
336 private void setNodeState(OpenstackNode node, NodeState newState) { 328 private void setNodeState(OpenstackNode node, NodeState newState) {
337 - log.debug("Changed {} state: {}", node.hostname(), newState); 329 + if (node.state() != newState) {
338 - nodeStore.put(node.hostname(), OpenstackNode.getUpdatedNode(node, newState)); 330 + log.debug("Changed {} state: {}", node.hostname(), newState);
331 + nodeStore.put(node.hostname(), OpenstackNode.getUpdatedNode(node, newState));
332 + }
339 } 333 }
340 334
341 private NodeState nodeState(OpenstackNode node) { 335 private NodeState nodeState(OpenstackNode node) {
342 - if (!deviceService.isAvailable(node.intBridge())) { 336 + if (!isOvsdbConnected(node) || !deviceService.isAvailable(node.intBridge())) {
343 return INIT; 337 return INIT;
344 } 338 }
339 +
340 + // TODO use device service when we use single ONOS cluster for both openstackNode and vRouter
345 if (node.type().equals(NodeType.GATEWAY) && 341 if (node.type().equals(NodeType.GATEWAY) &&
346 - !deviceService.isAvailable(node.routerBridge().get())) { 342 + !isBridgeCreated(node.ovsdbId(), ROUTER_BRIDGE)) {
347 return INIT; 343 return INIT;
348 } 344 }
349 345
350 - if (!isIfaceCreated(node.intBridge(), DEFAULT_TUNNEL)) { 346 + if (!isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
351 return DEVICE_CREATED; 347 return DEVICE_CREATED;
352 } 348 }
349 +
353 if (node.type().equals(NodeType.GATEWAY) && ( 350 if (node.type().equals(NodeType.GATEWAY) && (
354 - !isIfaceCreated(node.routerBridge().get(), PATCH_ROUT_BRIDGE) || 351 + !isIfaceCreated(node.ovsdbId(), PATCH_ROUT_BRIDGE) ||
355 - !isIfaceCreated(node.intBridge(), PATCH_INTG_BRIDGE))) { 352 + !isIfaceCreated(node.ovsdbId(), PATCH_INTG_BRIDGE) ||
353 + !isIfaceCreated(node.ovsdbId(), node.uplink().get()))) {
356 return DEVICE_CREATED; 354 return DEVICE_CREATED;
357 } 355 }
358 -
359 return COMPLETE; 356 return COMPLETE;
360 } 357 }
361 358
362 private boolean isIfaceCreated(DeviceId deviceId, String ifaceName) { 359 private boolean isIfaceCreated(DeviceId deviceId, String ifaceName) {
363 - return deviceService.getPorts(deviceId).stream() 360 + Device device = deviceService.getDevice(deviceId);
364 - .filter(p -> p.annotations().value(PORT_NAME).contains(ifaceName) && 361 + if (device == null || !device.is(BridgeConfig.class)) {
365 - p.isEnabled()) 362 + return false;
363 + }
364 +
365 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
366 + return bridgeConfig.getPorts().stream()
367 + .filter(port -> port.annotations().value(PORT_NAME).equals(ifaceName))
368 + .findAny()
369 + .isPresent();
370 + }
371 +
372 + private boolean isBridgeCreated(DeviceId deviceId, String bridgeName) {
373 + Device device = deviceService.getDevice(deviceId);
374 + if (device == null || !device.is(BridgeConfig.class)) {
375 + return false;
376 + }
377 +
378 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
379 + return bridgeConfig.getBridges().stream()
380 + .filter(bridge -> bridge.name().equals(bridgeName))
366 .findAny() 381 .findAny()
367 .isPresent(); 382 .isPresent();
368 } 383 }
369 384
370 - private void createBridge(OpenstackNode node, String bridgeName, String dpid) { 385 + private void createBridge(OpenstackNode node, String bridgeName, DeviceId deviceId) {
371 Device device = deviceService.getDevice(node.ovsdbId()); 386 Device device = deviceService.getDevice(node.ovsdbId());
372 if (device == null || !device.is(BridgeConfig.class)) { 387 if (device == null || !device.is(BridgeConfig.class)) {
373 log.error("Failed to create integration bridge on {}", node.ovsdbId()); 388 log.error("Failed to create integration bridge on {}", node.ovsdbId());
374 return; 389 return;
375 } 390 }
376 391
377 - List<ControllerInfo> controllers = clusterService.getNodes().stream() 392 + // TODO fix this when we use single ONOS cluster for both openstackNode and vRouter
378 - .map(controller -> new ControllerInfo(controller.ip(), DEFAULT_OFPORT, "tcp")) 393 + Set<IpAddress> controllerIps;
379 - .collect(Collectors.toList()); 394 + if (bridgeName.equals(ROUTER_BRIDGE)) {
395 + controllerIps = Sets.newHashSet(node.routerController().get());
396 + } else {
397 + controllerIps = clusterService.getNodes().stream()
398 + .map(ControllerNode::ip)
399 + .collect(Collectors.toSet());
400 + }
401 +
402 + List<ControllerInfo> controllers = controllerIps.stream()
403 + .map(ip -> new ControllerInfo(ip, DEFAULT_OFPORT, DEFAULT_OF_PROTO))
404 + .collect(Collectors.toList());
380 405
406 + String dpid = deviceId.toString().substring(DPID_BEGIN);
381 BridgeDescription bridgeDesc = DefaultBridgeDescription.builder() 407 BridgeDescription bridgeDesc = DefaultBridgeDescription.builder()
382 .name(bridgeName) 408 .name(bridgeName)
383 .failMode(BridgeDescription.FailMode.SECURE) 409 .failMode(BridgeDescription.FailMode.SECURE)
...@@ -386,11 +412,15 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -386,11 +412,15 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
386 .controllers(controllers) 412 .controllers(controllers)
387 .build(); 413 .build();
388 414
389 - BridgeConfig bridgeConfig = device.as(BridgeConfig.class); 415 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
390 bridgeConfig.addBridge(bridgeDesc); 416 bridgeConfig.addBridge(bridgeDesc);
391 } 417 }
392 418
393 private void createTunnelInterface(OpenstackNode node) { 419 private void createTunnelInterface(OpenstackNode node) {
420 + if (isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
421 + return;
422 + }
423 +
394 Device device = deviceService.getDevice(node.ovsdbId()); 424 Device device = deviceService.getDevice(node.ovsdbId());
395 if (device == null || !device.is(InterfaceConfig.class)) { 425 if (device == null || !device.is(InterfaceConfig.class)) {
396 log.error("Failed to create tunnel interface on {}", node.ovsdbId()); 426 log.error("Failed to create tunnel interface on {}", node.ovsdbId());
...@@ -405,11 +435,17 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -405,11 +435,17 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
405 .key(TunnelKeys.flowTunnelKey()) 435 .key(TunnelKeys.flowTunnelKey())
406 .build(); 436 .build();
407 437
408 - InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class); 438 + InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
409 ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnelDesc); 439 ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnelDesc);
410 } 440 }
411 441
412 private void createPatchInterface(OpenstackNode node) { 442 private void createPatchInterface(OpenstackNode node) {
443 + checkArgument(node.type().equals(NodeType.GATEWAY));
444 + if (isIfaceCreated(node.ovsdbId(), PATCH_INTG_BRIDGE) &&
445 + isIfaceCreated(node.ovsdbId(), PATCH_ROUT_BRIDGE)) {
446 + return;
447 + }
448 +
413 Device device = deviceService.getDevice(node.ovsdbId()); 449 Device device = deviceService.getDevice(node.ovsdbId());
414 if (device == null || !device.is(InterfaceConfig.class)) { 450 if (device == null || !device.is(InterfaceConfig.class)) {
415 log.error("Failed to create patch interfaces on {}", node.hostname()); 451 log.error("Failed to create patch interfaces on {}", node.hostname());
...@@ -428,21 +464,38 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -428,21 +464,38 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
428 .peer(PATCH_INTG_BRIDGE) 464 .peer(PATCH_INTG_BRIDGE)
429 .build(); 465 .build();
430 466
431 - InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class); 467 + InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
432 ifaceConfig.addPatchMode(PATCH_INTG_BRIDGE, patchIntg); 468 ifaceConfig.addPatchMode(PATCH_INTG_BRIDGE, patchIntg);
433 ifaceConfig.addPatchMode(PATCH_ROUT_BRIDGE, patchRout); 469 ifaceConfig.addPatchMode(PATCH_ROUT_BRIDGE, patchRout);
434 } 470 }
435 471
472 + private void addUplink(OpenstackNode node) {
473 + checkArgument(node.type().equals(NodeType.GATEWAY));
474 + if (isIfaceCreated(node.ovsdbId(), node.uplink().get())) {
475 + return;
476 + }
477 +
478 + Device device = deviceService.getDevice(node.ovsdbId());
479 + if (device == null || !device.is(BridgeConfig.class)) {
480 + log.error("Failed to add port {} on {}", node.uplink().get(), node.ovsdbId());
481 + return;
482 + }
483 +
484 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
485 + bridgeConfig.addPort(BridgeName.bridgeName(ROUTER_BRIDGE),
486 + node.uplink().get());
487 + }
488 +
436 private boolean isOvsdbConnected(OpenstackNode node) { 489 private boolean isOvsdbConnected(OpenstackNode node) {
437 OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort); 490 OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
438 - OvsdbClientService client = controller.getOvsdbClient(ovsdb); 491 + OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb);
439 return deviceService.isAvailable(node.ovsdbId()) && 492 return deviceService.isAvailable(node.ovsdbId()) &&
440 client != null && 493 client != null &&
441 client.isConnected(); 494 client.isConnected();
442 } 495 }
443 496
444 private void connectOvsdb(OpenstackNode node) { 497 private void connectOvsdb(OpenstackNode node) {
445 - controller.connect(node.managementIp(), TpPort.tpPort(ovsdbPort)); 498 + ovsdbController.connect(node.managementIp(), TpPort.tpPort(ovsdbPort));
446 } 499 }
447 500
448 private Set<String> systemIfaces(OpenstackNode node) { 501 private Set<String> systemIfaces(OpenstackNode node) {
...@@ -450,6 +503,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -450,6 +503,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
450 if (node.type().equals(NodeType.GATEWAY)) { 503 if (node.type().equals(NodeType.GATEWAY)) {
451 ifaces.add(PATCH_INTG_BRIDGE); 504 ifaces.add(PATCH_INTG_BRIDGE);
452 ifaces.add(PATCH_ROUT_BRIDGE); 505 ifaces.add(PATCH_ROUT_BRIDGE);
506 + ifaces.add(node.uplink().get());
453 } 507 }
454 return ifaces; 508 return ifaces;
455 } 509 }
...@@ -482,7 +536,11 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -482,7 +536,11 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
482 536
483 @Override 537 @Override
484 public void disconnected(Device device) { 538 public void disconnected(Device device) {
485 - log.debug("Device {} is disconnected", device.id()); 539 + OpenstackNode node = nodeByDeviceId(device.id());
540 + if (node != null) {
541 + log.warn("Device {} is disconnected", device.id());
542 + setNodeState(node, NodeState.INCOMPLETE);
543 + }
486 } 544 }
487 } 545 }
488 546
...@@ -566,6 +624,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -566,6 +624,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
566 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler); 624 (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
567 625
568 switch (event.type()) { 626 switch (event.type()) {
627 + // TODO implement OVSDB port event so that we can handle updates on the OVSDB
569 case PORT_ADDED: 628 case PORT_ADDED:
570 eventExecutor.execute(() -> bridgeHandler.portAdded(event.port())); 629 eventExecutor.execute(() -> bridgeHandler.portAdded(event.port()));
571 break; 630 break;
...@@ -640,7 +699,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv ...@@ -640,7 +699,7 @@ public final class OpenstackNodeManager extends ListenerRegistry<OpenstackNodeEv
640 oldNode = event.oldValue().value(); 699 oldNode = event.oldValue().value();
641 newNode = event.newValue().value(); 700 newNode = event.newValue().value();
642 701
643 - log.debug("Reloaded {}", newNode.hostname()); 702 + log.info("Reloaded {}", newNode.hostname());
644 if (!newNode.equals(oldNode)) { 703 if (!newNode.equals(oldNode)) {
645 log.debug("New node: {}", newNode); 704 log.debug("New node: {}", newNode);
646 } 705 }
......
...@@ -22,10 +22,14 @@ import org.onosproject.cli.AbstractShellCommand; ...@@ -22,10 +22,14 @@ import org.onosproject.cli.AbstractShellCommand;
22 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
23 import org.onosproject.net.Port; 23 import org.onosproject.net.Port;
24 import org.onosproject.net.Device; 24 import org.onosproject.net.Device;
25 +import org.onosproject.net.behaviour.BridgeConfig;
25 import org.onosproject.net.device.DeviceService; 26 import org.onosproject.net.device.DeviceService;
27 +import org.onosproject.net.device.PortDescription;
26 import org.onosproject.openstacknode.OpenstackNode; 28 import org.onosproject.openstacknode.OpenstackNode;
27 import org.onosproject.openstacknode.OpenstackNodeService; 29 import org.onosproject.openstacknode.OpenstackNodeService;
28 30
31 +import java.util.Optional;
32 +
29 import static org.onosproject.net.AnnotationKeys.PORT_NAME; 33 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
30 import static org.onosproject.openstacknode.Constants.*; 34 import static org.onosproject.openstacknode.Constants.*;
31 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY; 35 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
...@@ -60,7 +64,7 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand { ...@@ -60,7 +64,7 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
60 return; 64 return;
61 } 65 }
62 66
63 - print("%n[Integration Bridge Status]"); 67 + print("[Integration Bridge Status]");
64 Device device = deviceService.getDevice(node.intBridge()); 68 Device device = deviceService.getDevice(node.intBridge());
65 if (device != null) { 69 if (device != null) {
66 print("%s %s=%s available=%s %s", 70 print("%s %s=%s available=%s %s",
...@@ -79,23 +83,30 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand { ...@@ -79,23 +83,30 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
79 } 83 }
80 84
81 if (node.type().equals(GATEWAY)) { 85 if (node.type().equals(GATEWAY)) {
86 + print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
87 +
82 print("%n[Router Bridge Status]"); 88 print("%n[Router Bridge Status]");
83 - device = deviceService.getDevice(node.routerBridge().get()); 89 + device = deviceService.getDevice(node.ovsdbId());
84 - if (device != null) { 90 + if (device == null || !device.is(BridgeConfig.class)) {
85 - print("%s %s=%s available=%s %s", 91 + print("%s %s=%s is not available(unable to connect OVSDB)",
86 - deviceService.isAvailable(device.id()) ? MSG_OK : MSG_NO, 92 + MSG_NO,
87 - ROUTER_BRIDGE, 93 + ROUTER_BRIDGE,
88 - device.id(), 94 + node.intBridge());
89 - deviceService.isAvailable(device.id()),
90 - device.annotations());
91 -
92 - print(getPortState(deviceService, node.routerBridge().get(), PATCH_ROUT_BRIDGE));
93 - print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
94 } else { 95 } else {
95 - print("%s %s=%s is not available", 96 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
96 - MSG_NO, 97 + boolean available = bridgeConfig.getBridges().stream()
97 - ROUTER_BRIDGE, 98 + .filter(bridge -> bridge.name().equals(ROUTER_BRIDGE))
98 - node.intBridge()); 99 + .findAny()
100 + .isPresent();
101 +
102 + print("%s %s=%s available=%s",
103 + available ? MSG_OK : MSG_NO,
104 + ROUTER_BRIDGE,
105 + node.routerBridge().get(),
106 + available);
107 +
108 + print(getPortStateOvsdb(deviceService, node.ovsdbId(), PATCH_ROUT_BRIDGE));
109 + print(getPortStateOvsdb(deviceService, node.ovsdbId(), node.uplink().get()));
99 } 110 }
100 } 111 }
101 } 112 }
...@@ -117,4 +128,28 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand { ...@@ -117,4 +128,28 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
117 return String.format("%s %s does not exist", MSG_NO, portName); 128 return String.format("%s %s does not exist", MSG_NO, portName);
118 } 129 }
119 } 130 }
131 +
132 + private String getPortStateOvsdb(DeviceService deviceService, DeviceId deviceId, String portName) {
133 + Device device = deviceService.getDevice(deviceId);
134 + if (device == null || !device.is(BridgeConfig.class)) {
135 + return String.format("%s %s does not exist(unable to connect OVSDB)",
136 + MSG_NO, portName);
137 + }
138 +
139 + BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
140 + Optional<PortDescription> port = bridgeConfig.getPorts().stream()
141 + .filter(p -> p.annotations().value(PORT_NAME).contains(portName))
142 + .findAny();
143 +
144 + if (port.isPresent()) {
145 + return String.format("%s %s portNum=%s enabled=%s %s",
146 + port.get().isEnabled() ? MSG_OK : MSG_NO,
147 + portName,
148 + port.get().portNumber(),
149 + port.get().isEnabled() ? Boolean.TRUE : Boolean.FALSE,
150 + port.get().annotations());
151 + } else {
152 + return String.format("%s %s does not exist", MSG_NO, portName);
153 + }
154 + }
120 } 155 }
......