[ONOS-6150] OpenstackNode application support creation of vlan interface on open vswitch
Change-Id: I4342a8bd5f8a0a802e05f6b89a7962e5d3c9c9af
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
index 2cafcd6..3f5adee 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
@@ -427,7 +427,7 @@
// don't need to add gateway here and there
GatewayNode gnode = GatewayNode.builder()
.gatewayDeviceId(osNode.intBridge())
- .dataIpAddress(osNode.dataIp().getIp4Address())
+ .dataIpAddress(osNode.dataIp().get().getIp4Address())
.uplinkIntf(osNode.externalPortName().get())
.build();
gatewayService.addGatewayNode(gnode);
diff --git a/apps/openstacknode/network-cfg.json b/apps/openstacknode/network-cfg.json
index daecd85..6cca7ed 100644
--- a/apps/openstacknode/network-cfg.json
+++ b/apps/openstacknode/network-cfg.json
@@ -2,41 +2,35 @@
"apps" : {
"org.onosproject.openstacknode" : {
"openstacknode" : {
- "nodes" : [
- {
- "hostname" : "compute-01",
- "type" : "COMPUTE",
- "managementIp" : "10.203.25.244",
- "dataIp" : "10.134.34.222",
- "integrationBridge" : "of:00000000000000a1"
- },
- {
- "hostname" : "compute-02",
- "type" : "COMPUTE",
- "managementIp" : "10.203.229.42",
- "dataIp" : "10.134.34.223",
- "integrationBridge" : "of:00000000000000a2"
- },
- {
- "hostname" : "gateway-01",
- "type" : "GATEWAY",
- "managementIp" : "10.203.198.125",
- "dataIp" : "10.134.33.208",
- "integrationBridge" : "of:00000000000000a3",
- "routerBridge" : "of:00000000000000b3",
- "uplinkPort" : "veth1",
- "routerController" : "172.17.0.2"
- },
- {
- "hostname" : "gateway-02",
- "type" : "GATEWAY",
- "managementIp" : "10.203.198.131",
- "dataIp" : "10.134.33.209",
- "integrationBridge" : "of:00000000000000a4",
- "routerBridge" : "of:00000000000000b4",
- "uplinkPort" : "veth1",
- "routerController" : "172.17.0.2"
- }
+ "nodes" : [
+ {
+ "hostname" : "compute-01",
+ "type" : "COMPUTE",
+ "managementIp" : "172.16.130.4",
+ "dataIp" : "172.16.130.4",
+ "vlanPort" : "eth2",
+ "integrationBridge" : "of:00000000000000a1"
+ },
+ {
+ "hostname" : "compute-02",
+ "type" : "COMPUTE",
+ "managementIp" : "172.16.130.6",
+ "dataIp" : "172.16.130.6",
+ "vlanPort" : "eth2",
+ "integrationBridge" : "of:00000000000000a2"
+ },
+ {
+ "hostname" : "gateway-01",
+ "type" : "GATEWAY",
+ "managementIp" : "172.16.130.8",
+ "dataIp" : "172.16.130.7",
+ "vlanPort" : "eth2",
+ "integrationBridge" : "of:00000000000000a3",
+ "routerBridge" : "of:00000000000000b1",
+ "uplinkPort" : "quagga-router",
+ "routerController" : "172.17.0.2"
+
+ }
]
}
}
@@ -51,16 +45,6 @@
"basic" : {
"driver" : "sona"
}
- },
- "of:00000000000000b1" : {
- "basic" : {
- "driver" : "softrouter"
- }
- },
- "of:00000000000000b2" : {
- "basic" : {
- "driver" : "softrouter"
- }
}
}
}
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
index 2d73a85..0ff91a9 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNode.java
@@ -39,12 +39,13 @@
private final String hostname;
private final NodeType type;
private final IpAddress managementIp;
- private final IpAddress dataIp;
+ private final Optional<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 Optional<String> vlanPort;
private final NodeState state;
public static final Comparator<OpenstackNode> OPENSTACK_NODE_COMPARATOR =
@@ -53,11 +54,12 @@
private OpenstackNode(String hostname,
NodeType type,
IpAddress managementIp,
- IpAddress dataIp,
+ Optional<IpAddress> dataIp,
DeviceId integrationBridge,
Optional<DeviceId> routerBridge,
Optional<String> uplink,
Optional<IpAddress> routerController,
+ Optional<String> vlanPort,
NodeState state) {
this.hostname = hostname;
this.type = type;
@@ -67,6 +69,7 @@
this.routerBridge = routerBridge;
this.uplink = uplink;
this.routerController = routerController;
+ this.vlanPort = vlanPort;
this.state = state;
}
@@ -86,6 +89,7 @@
node.routerBridge,
node.uplink,
node.routerController,
+ node.vlanPort,
state);
}
@@ -119,9 +123,9 @@
/**
* Returns the data network IP address of the node.
*
- * @return data network ip address
+ * @return data network ip address; or empty value
*/
- public IpAddress dataIp() {
+ public Optional<IpAddress> dataIp() {
return dataIp;
}
@@ -166,6 +170,15 @@
}
/**
+ * Returns the vlan interface name.
+ *
+ * @return vlan interface name; or empty value
+ */
+ public Optional<String> vlanPort() {
+ return vlanPort;
+ }
+
+ /**
* Returns the init state of the node.
*
* @return init state
@@ -212,7 +225,8 @@
Objects.equals(integrationBridge, that.integrationBridge) &&
Objects.equals(routerBridge, that.routerBridge) &&
Objects.equals(uplink, that.uplink) &&
- Objects.equals(routerController, that.routerController)) {
+ Objects.equals(routerController, that.routerController) &&
+ Objects.equals(vlanPort, that.vlanPort)) {
return true;
}
}
@@ -228,7 +242,8 @@
integrationBridge,
routerBridge,
uplink,
- routerController);
+ routerController,
+ vlanPort);
}
@Override
@@ -242,6 +257,7 @@
.add("routerBridge", routerBridge)
.add("uplink", uplink)
.add("routerController", routerController)
+ .add("vlanport", vlanPort)
.add("state", state)
.toString();
}
@@ -262,10 +278,11 @@
private String hostname;
private NodeType type;
private IpAddress managementIp;
- private IpAddress dataIp;
+ private Optional<IpAddress> dataIp = Optional.empty();
private DeviceId integrationBridge;
private Optional<DeviceId> routerBridge = Optional.empty();
private Optional<String> uplink = Optional.empty();
+ private Optional<String> vlanPort = 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;
@@ -282,6 +299,7 @@
checkNotNull(routerBridge);
checkNotNull(uplink);
checkNotNull(routerController);
+ checkNotNull(vlanPort);
if (type == NodeType.GATEWAY) {
checkArgument(routerBridge.isPresent());
@@ -297,6 +315,7 @@
routerBridge,
uplink,
routerController,
+ vlanPort,
state);
}
@@ -340,7 +359,7 @@
* @return openstack node builder
*/
public Builder dataIp(IpAddress dataIp) {
- this.dataIp = dataIp;
+ this.dataIp = Optional.ofNullable(dataIp);
return this;
}
@@ -390,6 +409,17 @@
}
/**
+ * Returns node builder with the vlan interface name.
+ *
+ * @param vlanPort vlan interface name
+ * @return openstack node builder
+ */
+ public Builder vlanPort(String vlanPort) {
+ this.vlanPort = Optional.ofNullable(vlanPort);
+ return this;
+ }
+
+ /**
* Returns node builder with the init state.
*
* @param state node init state
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
index c20e678..0f264e9 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeConfig.java
@@ -27,6 +27,7 @@
import org.onosproject.net.config.Config;
import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
+import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
/**
@@ -46,6 +47,7 @@
private static final String UPLINK_PORT_NAME = "uplinkPort";
// TODO remove this when vRouter supports multiple switches
private static final String ROUTER_CONTROLLER = "routerController";
+ private static final String VLAN_PORT_NAME = "vlanPort";
@Override
public boolean isValid() {
@@ -57,6 +59,10 @@
}
for (JsonNode node : object.get(NODES)) {
+ if (get(node, DATA_IP) == null && get(node, VLAN_PORT_NAME) == null) {
+ final String msg = "There is neither tunnel interface nor vlan port";
+ throw new IllegalArgumentException(msg);
+ }
ObjectNode osNode = (ObjectNode) node;
result &= hasOnlyFields(osNode,
HOST_NAME,
@@ -66,14 +72,16 @@
INTEGRATION_BRIDGE,
ROUTER_BRIDGE,
UPLINK_PORT_NAME,
- ROUTER_CONTROLLER
+ ROUTER_CONTROLLER,
+ VLAN_PORT_NAME
);
result &= isString(osNode, HOST_NAME, MANDATORY);
result &= isString(osNode, TYPE, MANDATORY);
result &= isIpAddress(osNode, MANAGEMENT_IP, MANDATORY);
- result &= result && isIpAddress(osNode, DATA_IP, MANDATORY);
result &= isString(osNode, INTEGRATION_BRIDGE, MANDATORY);
+ result &= isString(osNode, VLAN_PORT_NAME, OPTIONAL);
+ result &= isIpAddress(osNode, DATA_IP, OPTIONAL);
DeviceId.deviceId(osNode.get(INTEGRATION_BRIDGE).asText());
NodeType.valueOf(osNode.get(TYPE).asText());
@@ -95,16 +103,22 @@
*/
public Set<OpenstackNode> openstackNodes() {
Set<OpenstackNode> nodes = Sets.newHashSet();
-
for (JsonNode node : object.get(NODES)) {
NodeType type = NodeType.valueOf(get(node, TYPE));
OpenstackNode.Builder nodeBuilder = OpenstackNode.builder()
.integrationBridge(DeviceId.deviceId(get(node, INTEGRATION_BRIDGE)))
- .dataIp(IpAddress.valueOf(get(node, DATA_IP)))
.managementIp(IpAddress.valueOf(get(node, MANAGEMENT_IP)))
.type(type)
.hostname(get(node, HOST_NAME));
+ if (get(node, DATA_IP) != null) {
+ nodeBuilder.dataIp(IpAddress.valueOf(get(node, DATA_IP)));
+ }
+
+ if (get(node, VLAN_PORT_NAME) != null) {
+ nodeBuilder.vlanPort(get(node, VLAN_PORT_NAME));
+ }
+
if (type.equals(GATEWAY)) {
nodeBuilder.routerBridge(DeviceId.deviceId(get(node, ROUTER_BRIDGE)))
.uplink(get(node, UPLINK_PORT_NAME))
@@ -116,6 +130,10 @@
}
private String get(JsonNode jsonNode, String path) {
- return jsonNode.get(path).asText();
+ JsonNode jNode = jsonNode.get(path);
+ if (jNode == null || jNode.isMissingNode()) {
+ return null;
+ }
+ return jNode.asText();
}
}
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
index 09b4f52..5276c58 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
@@ -253,9 +253,17 @@
connectOvsdb(node);
return;
}
+
process(new OpenstackNodeEvent(DEVICE_CREATED, node));
- createTunnelInterface(node);
+ if (node.dataIp().isPresent()) {
+ createTunnelInterface(node);
+ }
+
+ if (node.vlanPort().isPresent()) {
+ addVlanPort(node);
+ }
+
if (node.type().equals(NodeType.GATEWAY)) {
createPatchInterface(node);
addUplink(node);
@@ -294,7 +302,7 @@
log.warn("Failed to get node for {}", deviceId);
return Optional.empty();
}
- return Optional.of(node.dataIp());
+ return node.dataIp();
}
@Override
@@ -348,7 +356,11 @@
return INIT;
}
- if (!isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
+ if (node.dataIp().isPresent() && !isIfaceCreated(node.ovsdbId(), DEFAULT_TUNNEL)) {
+ return DEVICE_CREATED;
+ }
+
+ if (node.vlanPort().isPresent() && !isIfaceCreated(node.ovsdbId(), node.vlanPort().get())) {
return DEVICE_CREATED;
}
@@ -491,6 +503,22 @@
node.uplink().get());
}
+ private void addVlanPort(OpenstackNode node) {
+ if (isIfaceCreated(node.ovsdbId(), node.vlanPort().get())) {
+ return;
+ }
+
+ Device device = deviceService.getDevice(node.ovsdbId());
+ if (device == null || !device.is(BridgeConfig.class)) {
+ log.error("Failed to add port {} on {}", node.vlanPort().get(), node.ovsdbId());
+ return;
+ }
+
+ BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
+ bridgeConfig.addPort(BridgeName.bridgeName(INTEGRATION_BRIDGE),
+ node.vlanPort().get());
+ }
+
private boolean isOvsdbConnected(OpenstackNode node) {
OvsdbNodeId ovsdb = new OvsdbNodeId(node.managementIp(), ovsdbPort);
OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb);
@@ -504,7 +532,9 @@
}
private Set<String> systemIfaces(OpenstackNode node) {
- Set<String> ifaces = Sets.newHashSet(DEFAULT_TUNNEL);
+ Set<String> ifaces = Sets.newHashSet();
+ node.dataIp().ifPresent(ip -> ifaces.add(DEFAULT_TUNNEL));
+ node.vlanPort().ifPresent(p -> ifaces.add(p));
if (node.type().equals(NodeType.GATEWAY)) {
ifaces.add(PATCH_INTG_BRIDGE);
ifaces.add(PATCH_ROUT_BRIDGE);
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
index 84803c1..4d54abd 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
@@ -74,7 +74,8 @@
deviceService.isAvailable(device.id()),
device.annotations());
- print(getPortState(deviceService, node.intBridge(), DEFAULT_TUNNEL));
+ node.dataIp().ifPresent(ip -> print(getPortState(deviceService, node.intBridge(), DEFAULT_TUNNEL)));
+ node.vlanPort().ifPresent(p -> print(getPortState(deviceService, node.intBridge(), p)));
} else {
print("%s %s=%s is not available",
MSG_NO,
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
index 2649b05..a20d278 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
@@ -44,11 +44,13 @@
print("%s", json(nodes));
} else {
for (OpenstackNode node : nodes) {
- print("hostname=%s, type=%s, managementIp=%s, dataIp=%s, intBridge=%s, routerBridge=%s init=%s",
+ print("hostname=%s, type=%s, managementIp=%s, dataIp=%s, vlanPort=%s," +
+ "intBridge=%s, routerBridge=%s init=%s",
node.hostname(),
node.type(),
node.managementIp(),
node.dataIp(),
+ node.vlanPort(),
node.intBridge(),
node.routerBridge(),
node.state());
@@ -66,6 +68,7 @@
.put("type", node.type().name())
.put("managementIp", node.managementIp().toString())
.put("dataIp", node.dataIp().toString())
+ .put("vlanPort", node.vlanPort().toString())
.put("intBridge", node.intBridge().toString())
.put("routerBridge", node.routerBridge().toString())
.put("state", node.state().name()));