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 @@
"managementIp" : "10.203.198.125",
"dataIp" : "10.134.33.208",
"integrationBridge" : "of:00000000000000a3",
"routerBridge" : "of:00000000000000b1"
"routerBridge" : "of:00000000000000b3",
"uplinkPort" : "veth1",
"routerController" : "172.17.0.2"
},
{
"hostname" : "gateway-02",
......@@ -31,7 +33,9 @@
"managementIp" : "10.203.198.131",
"dataIp" : "10.134.33.209",
"integrationBridge" : "of:00000000000000a4",
"routerBridge" : "of:00000000000000b2"
"routerBridge" : "of:00000000000000b4",
"uplinkPort" : "veth1",
"routerController" : "172.17.0.2"
}
]
}
......
......@@ -28,4 +28,8 @@ public final class Constants {
public static final String DEFAULT_TUNNEL = "vxlan";
public static final String PATCH_INTG_BRIDGE = "patch-intg";
public static final String PATCH_ROUT_BRIDGE = "patch-rout";
public static final int DEFAULT_OVSDB_PORT = 6640;
public static final int DEFAULT_OFPORT = 6653;
public static final String DEFAULT_OF_PROTO = "tcp";
}
\ No newline at end of file
......
......@@ -41,6 +41,9 @@ public final class OpenstackNode {
private final IpAddress dataIp;
private final DeviceId integrationBridge;
private final Optional<DeviceId> routerBridge;
private final Optional<String> uplink;
// TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
private final Optional<IpAddress> routerController;
private final NodeState state;
public static final Comparator<OpenstackNode> OPENSTACK_NODE_COMPARATOR =
......@@ -52,6 +55,8 @@ public final class OpenstackNode {
IpAddress dataIp,
DeviceId integrationBridge,
Optional<DeviceId> routerBridge,
Optional<String> uplink,
Optional<IpAddress> routerController,
NodeState state) {
this.hostname = hostname;
this.type = type;
......@@ -59,6 +64,8 @@ public final class OpenstackNode {
this.dataIp = dataIp;
this.integrationBridge = integrationBridge;
this.routerBridge = routerBridge;
this.uplink = uplink;
this.routerController = routerController;
this.state = state;
}
......@@ -76,6 +83,8 @@ public final class OpenstackNode {
node.dataIp,
node.integrationBridge,
node.routerBridge,
node.uplink,
node.routerController,
state);
}
......@@ -135,6 +144,27 @@ public final class OpenstackNode {
}
/**
* Returns the router bridge controller.
* It returns valid value only if the node type is GATEWAY.
*
* @return device id; or empty value
*/
// TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
public Optional<IpAddress> routerController() {
return routerController;
}
/**
* Returns the uplink interface name.
* It returns valid value only if the node type is GATEWAY.
*
* @return uplink interface name; or empty value
*/
public Optional<String> uplink() {
return uplink;
}
/**
* Returns the init state of the node.
*
* @return init state
......@@ -165,7 +195,9 @@ public final class OpenstackNode {
Objects.equals(managementIp, that.managementIp) &&
Objects.equals(dataIp, that.dataIp) &&
Objects.equals(integrationBridge, that.integrationBridge) &&
Objects.equals(routerBridge, that.routerBridge)) {
Objects.equals(routerBridge, that.routerBridge) &&
Objects.equals(uplink, that.uplink) &&
Objects.equals(routerController, that.routerController)) {
return true;
}
}
......@@ -179,7 +211,9 @@ public final class OpenstackNode {
managementIp,
dataIp,
integrationBridge,
routerBridge);
routerBridge,
uplink,
routerController);
}
@Override
......@@ -191,6 +225,8 @@ public final class OpenstackNode {
.add("dataIp", dataIp)
.add("integrationBridge", integrationBridge)
.add("routerBridge", routerBridge)
.add("uplink", uplink)
.add("routerController", routerController)
.add("state", state)
.toString();
}
......@@ -214,6 +250,9 @@ public final class OpenstackNode {
private IpAddress dataIp;
private DeviceId integrationBridge;
private Optional<DeviceId> routerBridge = Optional.empty();
private Optional<String> uplink = Optional.empty();
// TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
private Optional<IpAddress> routerController = Optional.empty();
private NodeState state = INIT;
private Builder() {
......@@ -226,12 +265,23 @@ public final class OpenstackNode {
checkNotNull(dataIp);
checkNotNull(integrationBridge);
checkNotNull(routerBridge);
checkNotNull(uplink);
checkNotNull(routerController);
if (type == NodeType.GATEWAY) {
checkArgument(routerBridge.isPresent());
checkArgument(uplink.isPresent());
checkArgument(routerController.isPresent());
}
return new OpenstackNode(hostname,
type,
managementIp,
dataIp,
integrationBridge,
routerBridge,
uplink,
routerController,
state);
}
......@@ -302,6 +352,29 @@ public final class OpenstackNode {
}
/**
* Returns node builder with the uplink interface name.
*
* @param uplink uplink interface name
* @return openstack node builder
*/
public Builder uplink(String uplink) {
this.uplink = Optional.ofNullable(uplink);
return this;
}
/**
* Returns node builder with the router controller.
*
* @param routerController router contoller
* @return openstack node builder
*/
// TODO remove this when we use single ONOS cluster for both openstackNode and vRouter
public Builder routerController(IpAddress routerController) {
this.routerController = Optional.ofNullable(routerController);
return this;
}
/**
* Returns node builder with the init state.
*
* @param state node init state
......
......@@ -40,7 +40,12 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
private static final String MANAGEMENT_IP = "managementIp";
private static final String DATA_IP = "dataIp";
private static final String INTEGRATION_BRIDGE = "integrationBridge";
// GATEWAY node specific fields
private static final String ROUTER_BRIDGE = "routerBridge";
private static final String UPLINK_PORT_NAME = "uplinkPort";
// TODO remove this when vRouter supports multiple switches
private static final String ROUTER_CONTROLLER = "routerController";
@Override
public boolean isValid() {
......@@ -59,7 +64,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
MANAGEMENT_IP,
DATA_IP,
INTEGRATION_BRIDGE,
ROUTER_BRIDGE
ROUTER_BRIDGE,
UPLINK_PORT_NAME,
ROUTER_CONTROLLER
);
result &= isString(osNode, HOST_NAME, MANDATORY);
......@@ -74,6 +81,8 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
if (osNode.get(TYPE).asText().equals(GATEWAY.name())) {
result &= isString(osNode, ROUTER_BRIDGE, MANDATORY);
DeviceId.deviceId(osNode.get(ROUTER_BRIDGE).asText());
result &= isString(osNode, UPLINK_PORT_NAME, MANDATORY);
result &= isIpAddress(osNode, ROUTER_CONTROLLER, MANDATORY);
}
}
return result;
......@@ -97,7 +106,9 @@ public final class OpenstackNodeConfig extends Config<ApplicationId> {
.hostname(get(node, HOST_NAME));
if (type.equals(GATEWAY)) {
nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)));
nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)))
.uplink(get(node, UPLINK_PORT_NAME))
.routerController(IpAddress.valueOf(get(node, ROUTER_CONTROLLER)));
}
nodes.add(nodeBuilder.build());
}
......
......@@ -22,10 +22,14 @@ import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.Device;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.openstacknode.OpenstackNode;
import org.onosproject.openstacknode.OpenstackNodeService;
import java.util.Optional;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknode.Constants.*;
import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
......@@ -60,7 +64,7 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
return;
}
print("%n[Integration Bridge Status]");
print("[Integration Bridge Status]");
Device device = deviceService.getDevice(node.intBridge());
if (device != null) {
print("%s %s=%s available=%s %s",
......@@ -79,23 +83,30 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
}
if (node.type().equals(GATEWAY)) {
print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
print("%n[Router Bridge Status]");
device = deviceService.getDevice(node.routerBridge().get());
if (device != null) {
print("%s %s=%s available=%s %s",
deviceService.isAvailable(device.id()) ? MSG_OK : MSG_NO,
ROUTER_BRIDGE,
device.id(),
deviceService.isAvailable(device.id()),
device.annotations());
print(getPortState(deviceService, node.routerBridge().get(), PATCH_ROUT_BRIDGE));
print(getPortState(deviceService, node.intBridge(), PATCH_INTG_BRIDGE));
device = deviceService.getDevice(node.ovsdbId());
if (device == null || !device.is(BridgeConfig.class)) {
print("%s %s=%s is not available(unable to connect OVSDB)",
MSG_NO,
ROUTER_BRIDGE,
node.intBridge());
} else {
print("%s %s=%s is not available",
MSG_NO,
ROUTER_BRIDGE,
node.intBridge());
BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
boolean available = bridgeConfig.getBridges().stream()
.filter(bridge -> bridge.name().equals(ROUTER_BRIDGE))
.findAny()
.isPresent();
print("%s %s=%s available=%s",
available ? MSG_OK : MSG_NO,
ROUTER_BRIDGE,
node.routerBridge().get(),
available);
print(getPortStateOvsdb(deviceService, node.ovsdbId(), PATCH_ROUT_BRIDGE));
print(getPortStateOvsdb(deviceService, node.ovsdbId(), node.uplink().get()));
}
}
}
......@@ -117,4 +128,28 @@ public class OpenstackNodeCheckCommand extends AbstractShellCommand {
return String.format("%s %s does not exist", MSG_NO, portName);
}
}
private String getPortStateOvsdb(DeviceService deviceService, DeviceId deviceId, String portName) {
Device device = deviceService.getDevice(deviceId);
if (device == null || !device.is(BridgeConfig.class)) {
return String.format("%s %s does not exist(unable to connect OVSDB)",
MSG_NO, portName);
}
BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
Optional<PortDescription> port = bridgeConfig.getPorts().stream()
.filter(p -> p.annotations().value(PORT_NAME).contains(portName))
.findAny();
if (port.isPresent()) {
return String.format("%s %s portNum=%s enabled=%s %s",
port.get().isEnabled() ? MSG_OK : MSG_NO,
portName,
port.get().portNumber(),
port.get().isEnabled() ? Boolean.TRUE : Boolean.FALSE,
port.get().annotations());
} else {
return String.format("%s %s does not exist", MSG_NO, portName);
}
}
}
......