Connects to all the physical bridges in Kubevirt Node app to deal with the case that the physical port is disabled.
Change-Id: I9706cd4b670fbbb7ffdaaa2924fb893c801b2253
diff --git a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/codec/KubevirtPhyInterfaceCodec.java b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/codec/KubevirtPhyInterfaceCodec.java
index 3ba0164..796a1b1 100644
--- a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/codec/KubevirtPhyInterfaceCodec.java
+++ b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/codec/KubevirtPhyInterfaceCodec.java
@@ -15,11 +15,13 @@
*/
package org.onosproject.kubevirtnode.codec;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.kubevirtnode.api.DefaultKubevirtPhyInterface;
import org.onosproject.kubevirtnode.api.KubevirtPhyInterface;
+import org.onosproject.net.DeviceId;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
@@ -31,6 +33,7 @@
private static final String NETWORK = "network";
private static final String INTERFACE = "intf";
+ private static final String PHYS_BRIDGE_ID = "physBridgeId";
private static final String MISSING_MESSAGE = " is required in KubevirtPhyInterface";
@@ -38,9 +41,15 @@
public ObjectNode encode(KubevirtPhyInterface phyIntf, CodecContext context) {
checkNotNull(phyIntf, "Kubevirt physical interface cannot be null");
- return context.mapper().createObjectNode()
+ ObjectNode result = context.mapper().createObjectNode()
.put(NETWORK, phyIntf.network())
.put(INTERFACE, phyIntf.intf());
+
+ if (phyIntf.physBridge() != null) {
+ result.put(PHYS_BRIDGE_ID, phyIntf.physBridge().toString());
+ }
+
+ return result;
}
@Override
@@ -54,9 +63,15 @@
String intf = nullIsIllegal(json.get(INTERFACE).asText(),
INTERFACE + MISSING_MESSAGE);
- return DefaultKubevirtPhyInterface.builder()
+ KubevirtPhyInterface.Builder builder = DefaultKubevirtPhyInterface.builder()
.network(network)
- .intf(intf)
- .build();
+ .intf(intf);
+
+ JsonNode physBridgeJson = json.get(PHYS_BRIDGE_ID);
+ if (physBridgeJson != null) {
+ builder.physBridge(DeviceId.deviceId(physBridgeJson.asText()));
+ }
+
+ return builder.build();
}
}
diff --git a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
index 00aa0bf..0850ba2 100644
--- a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
+++ b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
@@ -88,6 +88,7 @@
import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_TO_INTEGRATION;
import static org.onosproject.kubevirtnode.api.Constants.VXLAN;
import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
+import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
import static org.onosproject.kubevirtnode.api.KubevirtNodeService.APP_ID;
import static org.onosproject.kubevirtnode.api.KubevirtNodeState.COMPLETE;
import static org.onosproject.kubevirtnode.api.KubevirtNodeState.DEVICE_CREATED;
@@ -585,18 +586,42 @@
log.error("Exception caused during init state checking...");
}
- String bridgeName = BRIDGE_PREFIX + phyIntf.network();
String patchPortName = structurePortName(
INTEGRATION_TO_PHYSICAL_PREFIX + phyIntf.network());
- if (!(hasPhyBridge(node, bridgeName) &&
- hasPhyPatchPort(node, patchPortName) &&
- hasPhyIntf(node, phyIntf.intf()))) {
- log.warn("PhyBridge {}", hasPhyBridge(node, bridgeName));
- log.warn("hasPhyPatchPort {}", hasPhyPatchPort(node, patchPortName));
- log.warn("hasPhyIntf {}", hasPhyIntf(node, phyIntf.intf()));
- return false;
+ if (node.type() == WORKER) {
+ String bridgeName = BRIDGE_PREFIX + phyIntf.network();
+ if (!(hasPhyBridge(node, bridgeName) &&
+ hasPhyPatchPort(node, patchPortName) &&
+ hasPhyIntf(node, phyIntf.intf()))) {
+ log.warn("PhyBridge {}", hasPhyBridge(node, bridgeName));
+ log.warn("hasPhyPatchPort {}", hasPhyPatchPort(node, patchPortName));
+ log.warn("hasPhyIntf {}", hasPhyIntf(node, phyIntf.intf()));
+ return false;
+ }
+ } else {
+ //In case node type is GATEWAY, we create physical bridges connected to the contoller.
+ //By doing so, ONOS immediately recognizes the status of physical interface and performs RM procedures.
+ Port phyIntfPort = deviceService.getPorts(phyIntf.physBridge()).stream()
+ .filter(port -> port.annotations().value(PORT_NAME).equals(phyIntf.intf()))
+ .findAny().orElse(null);
+ if (phyIntfPort == null) {
+ log.warn("There's no connected physical port {} on physical device {}",
+ phyIntf.intf(), phyIntf.physBridge());
+ }
+
+ if (!(deviceService.isAvailable(phyIntf.physBridge()) &&
+ hasPhyPatchPort(node, patchPortName) &&
+ hasPhyIntf(node, phyIntf.intf()) &&
+ phyIntfPort.isEnabled())) {
+ log.warn("PhysBridge {}", deviceService.isAvailable(phyIntf.physBridge()));
+ log.warn("hasPhyPatchPort {}", hasPhyPatchPort(node, patchPortName));
+ log.warn("hasPhyIntf {}", hasPhyIntf(node, phyIntf.intf()));
+ log.warn("physical interface port {}", phyIntfPort.isEnabled());
+ return false;
+ }
}
+
}
if (node.type() == GATEWAY) {
@@ -610,6 +635,12 @@
return true;
}
+ private boolean hasPhyBridge(KubevirtNode node, String bridgeName) {
+ BridgeConfig bridgeConfig =
+ deviceService.getDevice(node.ovsdb()).as(BridgeConfig.class);
+ return bridgeConfig.getBridges().stream()
+ .anyMatch(br -> br.name().equals(bridgeName));
+ }
/**
* Configures the kubernetes node with new state.
*
@@ -630,14 +661,21 @@
String bridgeName = BRIDGE_PREFIX + pi.network();
String patchPortName =
structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX + pi.network());
-
- if (!hasPhyBridge(node, bridgeName)) {
+ if (node.type() == WORKER && !hasPhyBridge(node, bridgeName)) {
createPhysicalBridge(node, pi);
createPhysicalPatchPorts(node, pi);
attachPhysicalPort(node, pi);
- log.info("Creating physnet bridge {}", bridgeName);
- log.info("Creating patch ports for physnet {}", bridgeName);
+ log.info("Creating physnet bridge {} for worker node {}", bridgeName, node.hostname());
+ log.info("Creating patch ports for physnet {} for worker node {}", bridgeName, node.hostname());
+
+ } else if (node.type() == GATEWAY && (!deviceService.isAvailable(pi.physBridge()))) {
+ createPhysicalBridgeWithConnectedMode(node, pi);
+ createPhysicalPatchPorts(node, pi);
+ attachPhysicalPort(node, pi);
+
+ log.info("Creating physnet bridge {} for gateway node {}", bridgeName, node.hostname());
+ log.info("Creating patch ports for physnet {} for gateway node {}", bridgeName, node.hostname());
} else {
// in case physical bridge exists, but patch port is missing,
// we will add patch port to connect br-physnet with physical bridge
@@ -728,13 +766,6 @@
});
}
- private boolean hasPhyBridge(KubevirtNode node, String bridgeName) {
- BridgeConfig bridgeConfig =
- deviceService.getDevice(node.ovsdb()).as(BridgeConfig.class);
- return bridgeConfig.getBridges().stream()
- .anyMatch(br -> br.name().equals(bridgeName));
- }
-
private boolean hasPhyPatchPort(KubevirtNode node, String patchPortName) {
List<Port> ports = deviceService.getPorts(node.intgBridge());
return ports.stream().anyMatch(p ->
@@ -762,6 +793,44 @@
bridgeConfig.addBridge(builder.build());
}
+ private void createPhysicalBridgeWithConnectedMode(KubevirtNode osNode,
+ KubevirtPhyInterface phyInterface) {
+ Device device = deviceService.getDevice(osNode.ovsdb());
+ IpAddress controllerIp = apiConfigService.apiConfig().controllerIp();
+ String serviceFqdn = apiConfigService.apiConfig().serviceFqdn();
+ IpAddress serviceIp = null;
+
+ if (controllerIp == null) {
+ if (serviceFqdn != null) {
+ serviceIp = resolveHostname(serviceFqdn);
+ }
+
+ if (serviceIp != null) {
+ controllerIp = serviceIp;
+ } else {
+ controllerIp = apiConfigService.apiConfig().ipAddress();
+ }
+ }
+
+ ControllerInfo controlInfo = new ControllerInfo(controllerIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
+ List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
+
+ String dpid = phyInterface.physBridge().toString().substring(DPID_BEGIN);
+
+ String bridgeName = BRIDGE_PREFIX + phyInterface.network();
+
+ BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
+ .name(bridgeName)
+ .failMode(BridgeDescription.FailMode.SECURE)
+ .datapathId(dpid)
+ .mcastSnoopingEnable()
+ .disableInBand()
+ .controllers(controllers);
+
+ BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
+ bridgeConfig.addBridge(builder.build());
+ }
+
private void removePhysicalBridge(KubevirtNode node, String network) {
Device device = deviceService.getDevice(node.ovsdb());
@@ -843,6 +912,17 @@
addOrRemoveSystemInterface(node, physicalDeviceId, portName, deviceService, false);
}
+ private KubevirtNode nodeByTunOrPhyBridge(DeviceId deviceId) {
+ KubevirtNode node = nodeAdminService.nodeByTunBridge(deviceId);
+ if (node == null) {
+ node = nodeAdminService.nodeByPhyBridge(deviceId);
+ if (node == null) {
+ return null;
+ }
+ }
+ return node;
+ }
+
/**
* An internal OVSDB listener. This listener is used for listening the
* network facing events from OVSDB device. If a new OVSDB device is detected,
@@ -923,7 +1003,7 @@
break;
case PORT_UPDATED:
case PORT_ADDED:
- eventExecutor.execute(() -> processPortAddition(device, port));
+ eventExecutor.execute(() -> processPortAdditionOrUpdate(device, port));
break;
case PORT_REMOVED:
eventExecutor.execute(() -> processPortRemoval(device, port));
@@ -962,12 +1042,12 @@
}
}
- void processPortAddition(Device device, Port port) {
+ void processPortAdditionOrUpdate(Device device, Port port) {
if (!isRelevantHelper()) {
return;
}
- KubevirtNode node = nodeAdminService.nodeByTunBridge(device.id());
+ KubevirtNode node = nodeByTunOrPhyBridge(device.id());
if (node == null) {
return;
@@ -983,6 +1063,24 @@
portName, device.id());
bootstrapNode(node);
}
+
+ //When the physical port is down, in the middle of normal operation, we set the node state to INCOMPLTE
+ //so that respective handlers do their related jobs.
+ if (node.state() == COMPLETE && node.type().equals(GATEWAY) && !port.isEnabled()) {
+ node.phyIntfs().stream()
+ .filter(pi -> pi.intf().equals(portName))
+ .findAny()
+ .ifPresent(pi -> setState(node, INCOMPLETE));
+ }
+
+ //When the physical port up again, we set the node state to INIT
+ //so that respective handlers do their related jobs.
+ if (node.state() == INCOMPLETE && node.type().equals(GATEWAY) && port.isEnabled()) {
+ node.phyIntfs().stream()
+ .filter(pi -> pi.intf().equals(portName))
+ .findAny()
+ .ifPresent(pi -> setState(node, INIT));
+ }
}
void processPortRemoval(Device device, Port port) {
diff --git a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/KubevirtNodeManager.java b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/KubevirtNodeManager.java
index 4e7e39e..f16837e 100644
--- a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/KubevirtNodeManager.java
+++ b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/KubevirtNodeManager.java
@@ -61,6 +61,7 @@
import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
import static org.onosproject.kubevirtnode.impl.OsgiPropertyConstants.OVSDB_PORT;
import static org.onosproject.kubevirtnode.impl.OsgiPropertyConstants.OVSDB_PORT_NUM_DEFAULT;
+import static org.onosproject.kubevirtnode.util.KubevirtNodeUtil.genDpidFromName;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -305,6 +306,21 @@
.findFirst().orElse(null);
}
+ @Override
+ public KubevirtNode nodeByPhyBridge(DeviceId deviceId) {
+ return nodeStore.nodes().stream()
+ .filter(node -> hasPhyBridge(node, deviceId))
+ .findAny()
+ .orElse(null);
+ }
+
+ private boolean hasPhyBridge(KubevirtNode node, DeviceId deviceId) {
+ return node.phyIntfs().stream()
+ .filter(phyIntf -> phyIntf.physBridge().equals(deviceId))
+ .findAny()
+ .isPresent();
+ }
+
private boolean hasIntgBridge(DeviceId deviceId, String hostname) {
Optional<KubevirtNode> existNode = nodeStore.nodes().stream()
.filter(n -> !n.hostname().equals(hostname))
@@ -323,15 +339,6 @@
return existNode.isPresent();
}
- private String genDpidFromName(String name) {
- if (name != null) {
- String hexString = Integer.toHexString(name.hashCode());
- return OF_PREFIX + Strings.padStart(hexString, 16, '0');
- }
-
- return null;
- }
-
private class InternalNodeStoreDelegate implements KubevirtNodeStoreDelegate {
@Override
diff --git a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/util/KubevirtNodeUtil.java b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/util/KubevirtNodeUtil.java
index 66b1af8..7107285 100644
--- a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/util/KubevirtNodeUtil.java
+++ b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/util/KubevirtNodeUtil.java
@@ -38,6 +38,7 @@
import org.onosproject.kubevirtnode.api.KubevirtNodeState;
import org.onosproject.kubevirtnode.api.KubevirtPhyInterface;
import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.device.DeviceService;
@@ -86,6 +87,7 @@
private static final String GATEWAY_BRIDGE_NAME = "gatewayBridgeName";
private static final String NETWORK_KEY = "network";
private static final String INTERFACE_KEY = "interface";
+ private static final String PHYS_BRIDGE_ID = "physBridgeId";
private static final int PORT_NAME_MAX_LENGTH = 15;
@@ -365,8 +367,20 @@
String intf = object.getString(INTERFACE_KEY);
if (network != null && intf != null) {
+ String physBridgeId;
+ if (object.has(PHYS_BRIDGE_ID)) {
+ physBridgeId = object.getString(PHYS_BRIDGE_ID);
+ } else {
+ physBridgeId = genDpidFromName(network + intf + hostname);
+ log.trace("host {} physnet dpid for network {} intf {} is null so generate dpid {}",
+ hostname, network, intf, physBridgeId);
+ }
+
phys.add(DefaultKubevirtPhyInterface.builder()
- .network(network).intf(intf).build());
+ .network(network)
+ .intf(intf)
+ .physBridge(DeviceId.deviceId(physBridgeId))
+ .build());
}
}
}
@@ -414,6 +428,20 @@
}
/**
+ * Generates a unique dpid from given name.
+ *
+ * @param name name
+ * @return device id in string
+ */
+ public static String genDpidFromName(String name) {
+ if (name != null) {
+ String hexString = Integer.toHexString(name.hashCode());
+ return OF_PREFIX + Strings.padStart(hexString, 16, '0');
+ }
+ return null;
+ }
+
+ /**
* Resolve a DNS with the given DNS server and hostname.
*
* @param hostname hostname to be resolved