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 }
......
...@@ -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 }
......