[VOL-3922] Dynamic configuration of the required drivers property to ensure correct driver is assigned to the device at all times, both instance restart and application update
Change-Id: I1c54d2e260aecd1e33b15c06bcb1f6c857603355
diff --git a/impl/src/main/java/org/opencord/olt/driver/OltDriversLoader.java b/impl/src/main/java/org/opencord/olt/driver/OltDriversLoader.java
index a91621f..f6714d4 100644
--- a/impl/src/main/java/org/opencord/olt/driver/OltDriversLoader.java
+++ b/impl/src/main/java/org/opencord/olt/driver/OltDriversLoader.java
@@ -16,18 +16,57 @@
package org.opencord.olt.driver;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
import org.onosproject.net.driver.AbstractDriverLoader;
+import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
+import java.util.Dictionary;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onlab.util.Tools.get;
+import static org.opencord.olt.impl.OsgiPropertyConstants.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Loader for olt device drivers.
*/
-@Component(immediate = true)
+@Component(immediate = true, property = {
+ REQUIRED_DRIVERS_PROPERTY_DELAY + ":Integer=" + REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT
+})
public class OltDriversLoader extends AbstractDriverLoader {
+ public static final String DRIVER_REGISTRY_MANAGER =
+ "org.onosproject.net.driver.impl.DriverRegistryManager";
+ public static final String REQUIRED_DRIVERS = "requiredDrivers";
+ public static final String VOLTHA_DRIVER_NAME = "voltha";
+ public static final String DRIVER_UPDATE_LEADSHIP_TOPIC = "driver-update";
+ public static final String OLT_DRIVERS_LOADER = "org.opencord.olt.driver.OltDriversLoader";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ private ComponentConfigService compCfgService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected LeadershipService leadershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected ClusterService clusterService;
+
+ /**
+ * Default amounts of eapol retry.
+ **/
+ protected int requiredDriversPropertyDelay = REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT;
+
private final Logger log = getLogger(getClass());
public OltDriversLoader() {
@@ -36,11 +75,102 @@
@Override
public void activate() {
+ log.info("Activating OLT Driver loader");
+ compCfgService.registerProperties(getClass());
+ //The AbstractDriversLoader does not pass the context, to avoid changes to all
+ // inheriting classes getting the property differently
+ ConfigProperty requiredDriversPropertyDelayNew =
+ compCfgService.getProperty(OLT_DRIVERS_LOADER, REQUIRED_DRIVERS_PROPERTY_DELAY);
+ requiredDriversPropertyDelay = requiredDriversPropertyDelayNew == null ?
+ REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT : requiredDriversPropertyDelayNew.asInteger();
+ log.info("OLT Driver loader requiredDriversPropertyDelay: {}", requiredDriversPropertyDelay);
super.activate();
+ // Verify if this node is the leader
+ NodeId leader = leadershipService.runForLeadership(DRIVER_UPDATE_LEADSHIP_TOPIC).leaderNodeId();
+ if (clusterService.getLocalNode().id().equals(leader)) {
+ Thread thread = new Thread(() -> {
+ // Sleep is needed to allow driver correct initialization and
+ // flow objective cache invalidation.
+ try {
+ TimeUnit.SECONDS.sleep(requiredDriversPropertyDelay);
+ } catch (InterruptedException e) {
+ log.error("Interrupted thread while activating", e);
+ }
+ String currentRequiredDrivers =
+ compCfgService.getProperty(DRIVER_REGISTRY_MANAGER, REQUIRED_DRIVERS)
+ .asString();
+ //insertion of voltha in the required drivers
+ if (!currentRequiredDrivers.contains(VOLTHA_DRIVER_NAME)) {
+ String updatedRequiredDrivers = currentRequiredDrivers;
+ if (!updatedRequiredDrivers.endsWith(",")) {
+ updatedRequiredDrivers = updatedRequiredDrivers + ",";
+ }
+ updatedRequiredDrivers = updatedRequiredDrivers + VOLTHA_DRIVER_NAME;
+ compCfgService.setProperty(DRIVER_REGISTRY_MANAGER,
+ REQUIRED_DRIVERS, updatedRequiredDrivers);
+ log.debug("Added voltha driver to required drivers {}",
+ updatedRequiredDrivers);
+ }
+ });
+ thread.start();
+ }
+ }
+
+ @Modified
+ public void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
+ try {
+ String requiredDriversPropertyDelayNew = get(properties, REQUIRED_DRIVERS_PROPERTY_DELAY);
+ requiredDriversPropertyDelay = isNullOrEmpty(requiredDriversPropertyDelayNew) ?
+ REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT :
+ Integer.parseInt(requiredDriversPropertyDelayNew.trim());
+
+ log.info("OLT Driver loader requiredDriversPropertyDelay: {}", requiredDriversPropertyDelay);
+
+ } catch (Exception e) {
+ log.error("Error while modifying the properties", e);
+ requiredDriversPropertyDelay = REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT;
+ }
}
@Override
public void deactivate() {
+ log.info("Deactivating OLT Driver loader");
+ //The AbstractDriversLoader does not pass the context, to avoid changes to all
+ // inheriting classes getting the property differently
+ ConfigProperty requiredDriversPropertyDelayNew =
+ compCfgService.getProperty(OLT_DRIVERS_LOADER, REQUIRED_DRIVERS_PROPERTY_DELAY);
+ requiredDriversPropertyDelay = requiredDriversPropertyDelayNew == null ?
+ REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT : requiredDriversPropertyDelayNew.asInteger();
+ log.info("OLT Driver loader requiredDriversPropertyDelay: {}", requiredDriversPropertyDelay);
+ NodeId leader = leadershipService.runForLeadership(DRIVER_UPDATE_LEADSHIP_TOPIC).leaderNodeId();
+ if (clusterService.getLocalNode().id().equals(leader)) {
+ String currentRequiredDrivers =
+ compCfgService.getProperty(DRIVER_REGISTRY_MANAGER, REQUIRED_DRIVERS)
+ .asString();
+ //removal of voltha from the required driver
+ if (currentRequiredDrivers.contains(VOLTHA_DRIVER_NAME)) {
+ String updatedRequiredDrivers = currentRequiredDrivers.replace(VOLTHA_DRIVER_NAME, "");
+ //handling the case where `voltha` was not the last required driver in the list
+ if (updatedRequiredDrivers.contains(",,")) {
+ updatedRequiredDrivers = updatedRequiredDrivers.replace(",,", ",");
+ }
+ if (updatedRequiredDrivers.endsWith(",")) {
+ updatedRequiredDrivers = updatedRequiredDrivers.substring(0, updatedRequiredDrivers.length() - 1);
+ }
+ compCfgService.setProperty(DRIVER_REGISTRY_MANAGER,
+ REQUIRED_DRIVERS, updatedRequiredDrivers);
+ log.debug("Removed voltha from required drivers {}", updatedRequiredDrivers);
+ }
+ }
+ // Sleep is needed to allow proper property sharing across the instances through accumulator
+ // of component config manager
+ try {
+ TimeUnit.SECONDS.sleep(requiredDriversPropertyDelay);
+ } catch (InterruptedException e) {
+ log.error("Interrupted while de-activating", e);
+ }
+ compCfgService.unregisterProperties(getClass(), false);
super.deactivate();
}
}
diff --git a/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java b/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
index 84a56ca..5232eb8 100644
--- a/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
+++ b/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
@@ -161,6 +161,8 @@
accumulator = new ObjectiveAccumulator(context.accumulatorMaxObjectives(),
context.accumulatorMaxBatchMillis(),
context.accumulatorMaxIdleMillis());
+ } else {
+ log.debug("Olt Pipeliner accumulator is disabled, processing immediately");
}
@@ -1213,10 +1215,12 @@
GroupKey key = event.subject().appCookie();
NextObjective obj = pendingGroups.getIfPresent(key);
if (obj == null) {
- log.debug("No pending group for {}, moving on", key);
+ if (log.isTraceEnabled()) {
+ log.trace("No pending group for {}, moving on", key);
+ }
return;
}
- log.trace("Event {} for group {}, handling pending" +
+ log.debug("Event {} for group {}, handling pending" +
"NextGroup {}", event.type(), key, obj.id());
if (event.type() == GroupEvent.Type.GROUP_ADDED ||
event.type() == GroupEvent.Type.GROUP_UPDATED) {
diff --git a/impl/src/main/java/org/opencord/olt/impl/Olt.java b/impl/src/main/java/org/opencord/olt/impl/Olt.java
index f822ae3..76f3013 100644
--- a/impl/src/main/java/org/opencord/olt/impl/Olt.java
+++ b/impl/src/main/java/org/opencord/olt/impl/Olt.java
@@ -41,6 +41,7 @@
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -134,9 +135,14 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected DeviceService deviceService;
+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
+ //Dependency on driver service is to ensure correct startup order
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected DriverService driverService;
+
@Reference(cardinality = ReferenceCardinality.OPTIONAL,
bind = "bindSadisService",
unbind = "unbindSadisService",
@@ -1236,7 +1242,8 @@
log.info("checkAndCreateDeviceFlows: deviceInfo {}", deviceInfo);
if (deviceInfo != null) {
- // This is an OLT device as per Sadis, we create flows for UNI and NNI ports
+ log.debug("Driver for device {} is {}", dev.id(),
+ driverService.getDriver(dev.id()));
for (Port p : deviceService.getPorts(dev.id())) {
if (PortNumber.LOCAL.equals(p.number()) || !p.isEnabled()) {
continue;
diff --git a/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java b/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
index caeab28..fed9546 100644
--- a/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
+++ b/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
@@ -246,7 +246,7 @@
log.info("modified. Values = enableDhcpOnNni: {}, enableDhcpV4: {}, " +
"enableDhcpV6:{}, enableIgmpOnNni:{}, " +
- "enableEapol{}, enablePppoe{}, defaultTechProfileId: {}",
+ "enableEapol:{}, enablePppoe:{}, defaultTechProfileId:{}",
enableDhcpOnNni, enableDhcpV4, enableDhcpV6,
enableIgmpOnNni, enableEapol, enablePppoe,
defaultTechProfileId);
@@ -681,8 +681,8 @@
@Override
public void onSuccess(Objective objective) {
log.info("Eapol filter {} for {} on {}/{} with meter {}.",
- objective.id(), fi.getDevId(), fi.getUniPort(),
- (install) ? INSTALLED : REMOVED, mId);
+ objective.id(), (install) ? INSTALLED : REMOVED,
+ fi.getDevId(), fi.getUniPort(), mId);
if (filterFuture != null) {
filterFuture.complete(null);
}
diff --git a/impl/src/main/java/org/opencord/olt/impl/OsgiPropertyConstants.java b/impl/src/main/java/org/opencord/olt/impl/OsgiPropertyConstants.java
index 3d76ef6..1db37e5 100644
--- a/impl/src/main/java/org/opencord/olt/impl/OsgiPropertyConstants.java
+++ b/impl/src/main/java/org/opencord/olt/impl/OsgiPropertyConstants.java
@@ -59,4 +59,7 @@
public static final String PROVISION_DELAY = "provisionDelay";
public static final int PROVISION_DELAY_DEFAULT = 100;
+
+ public static final String REQUIRED_DRIVERS_PROPERTY_DELAY = "requiredDriversPropertyDelay";
+ public static final int REQUIRED_DRIVERS_PROPERTY_DELAY_DEFAULT = 5;
}