[ONOS-8087] Per device purgeOnDisconnection Flag

Change-Id: I7cb1db12a4d910d70123f116107a898bf9e6d278
This commit is contained in:
Andrea Campanella 2020-03-27 12:53:46 +01:00
parent ec6baf4b19
commit 32a9c0b2d9
9 changed files with 125 additions and 14 deletions

View File

@ -486,10 +486,6 @@ public class SegmentRoutingManager implements SegmentRoutingService {
l2TunnelHandler = new DefaultL2TunnelHandler(this);
topologyHandler = new TopologyHandler(this);
compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
"purgeOnDisconnection", "true", false);
compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
"purgeOnDisconnection", "true", false);
compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
"requestInterceptsEnabled", "false", false);
compCfgService.preSetProperty("org.onosproject.net.neighbour.impl.NeighbourResolutionManager",

View File

@ -35,6 +35,7 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigException;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.basics.InterfaceConfig;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intf.Interface;
@ -109,6 +110,12 @@ public class DeviceConfiguration implements DeviceProperties {
Set<DeviceId> deviceSubjects =
srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
deviceSubjects.forEach(subject -> {
//Setting purge on disconnection flag for the device SR has control over.
// addConfig returns a config if it exists or creates a new one.
log.info("PurgeOnDisconnection set to true for device {}", subject);
BasicDeviceConfig basicDeviceConfig = srManager.cfgService.addConfig(subject, BasicDeviceConfig.class);
basicDeviceConfig.purgeOnDisconnection(true);
srManager.cfgService.applyConfig(subject, BasicDeviceConfig.class, basicDeviceConfig.node());
SegmentRoutingDeviceConfig config =
srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
SegmentRouterInfo info = new SegmentRouterInfo();

View File

@ -139,6 +139,7 @@ public class IcmpHandlerTest {
// Apply config
MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
mockNetworkConfigRegistry.applyConfig(remoteLeafConfig);
mockNetworkConfigRegistry.applyConfig(remoteLeafPorts1Config);
mockNetworkConfigRegistry.applyConfig(remoteLeafPorts2Config);

View File

@ -16,10 +16,14 @@
package org.onosproject.segmentrouting;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import java.util.Objects;
import java.util.Set;
@ -43,6 +47,25 @@ class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
return (C) c;
}
@Override
public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
Config c = configs.stream()
.filter(config -> subject.equals(config.subject()))
.filter(config -> configClass.equals(config.getClass()))
.findFirst().orElseGet(() -> {
if (configClass.equals(BasicDeviceConfig.class)) {
BasicDeviceConfig deviceConfig = new BasicDeviceConfig();
ObjectMapper mapper = new ObjectMapper();
deviceConfig.init((DeviceId) subject, ((DeviceId) subject).toString(),
JsonNodeFactory.instance.objectNode(), mapper, config -> {
});
return deviceConfig;
}
return null;
});
return (C) c;
}
@Override
public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subject, Class<C> configClass) {
ImmutableSet.Builder<S> builder = ImmutableSet.builder();

View File

@ -18,6 +18,7 @@ package org.onosproject.segmentrouting.config;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.junit.Before;
@ -29,6 +30,7 @@ import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.basics.InterfaceConfig;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intf.Interface;
@ -73,10 +75,12 @@ public class DeviceConfigurationTest {
private DeviceConfiguration devConfig;
private NetworkConfigRegistry networkConfigService;
@Before
public void setUp() throws Exception {
InterfaceService interfaceService;
NetworkConfigRegistry networkConfigService;
networkConfigService = null;
NeighbourResolutionService neighbourResolutionService;
SegmentRoutingManager srManager;
@ -86,6 +90,10 @@ public class DeviceConfigurationTest {
JsonNode jsonNode = mapper.readTree(jsonStream);
SegmentRoutingDeviceConfig srDevConfig = new SegmentRoutingDeviceConfig();
srDevConfig.init(DEV1, CONFIG_KEY, jsonNode, mapper, config -> { });
BasicDeviceConfig basicDeviceConfig = new BasicDeviceConfig();
basicDeviceConfig.init(DEV1, DEV1.toString(), JsonNodeFactory.instance.objectNode(), mapper, config -> { });
BasicDeviceConfig purgeOnDisconnectConfig = basicDeviceConfig.purgeOnDisconnection(true);
// Mock interface netcfg
jsonStream = InterfaceConfig.class.getResourceAsStream("/interface1.json");
@ -102,6 +110,12 @@ public class DeviceConfigurationTest {
.andReturn(Sets.newHashSet(DEV1)).anyTimes();
expect(networkConfigService.getConfig(DEV1, SegmentRoutingDeviceConfig.class))
.andReturn(srDevConfig).anyTimes();
expect(networkConfigService.addConfig(DEV1, BasicDeviceConfig.class))
.andReturn(basicDeviceConfig).anyTimes();
expect(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class))
.andReturn(basicDeviceConfig).anyTimes();
expect(networkConfigService.applyConfig(DEV1, BasicDeviceConfig.class, purgeOnDisconnectConfig.node()))
.andReturn(purgeOnDisconnectConfig).anyTimes();
expect(networkConfigService.getSubjects(ConnectPoint.class, InterfaceConfig.class))
.andReturn(Sets.newHashSet(CP1, CP2)).anyTimes();
expect(networkConfigService.getConfig(CP1, InterfaceConfig.class)).andReturn(interfaceConfig1).anyTimes();
@ -157,4 +171,10 @@ public class DeviceConfigurationTest {
assertTrue(devConfig.inSameSubnet(DEV1, PREFIX2.address()));
assertFalse(devConfig.inSameSubnet(DEV1, ROUTE1.address()));
}
@Test
public void getPurgeOnDisconnect() {
assertNotNull(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class));
assertTrue(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class).purgeOnDisconnection());
}
}

View File

@ -34,6 +34,7 @@ public final class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
private static final String HW_VERSION = "hwVersion";
private static final String SW_VERSION = "swVersion";
private static final String SERIAL = "serial";
private static final String PURGE_ON_DISCONNECT = "purgeOnDisconnection";
private static final String DEVICE_KEY_ID = "deviceKeyId";
private static final int DRIVER_MAX_LENGTH = 256;
@ -54,7 +55,7 @@ public final class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
&& hasOnlyFields(ALLOWED, NAME, LOC_TYPE, LATITUDE, LONGITUDE,
GRID_Y, GRID_X, UI_TYPE, RACK_ADDRESS, OWNER, TYPE, DRIVER, ROLES,
MANUFACTURER, HW_VERSION, SW_VERSION, SERIAL,
MANAGEMENT_ADDRESS, PIPECONF, DEVICE_KEY_ID)
MANAGEMENT_ADDRESS, PIPECONF, DEVICE_KEY_ID, PURGE_ON_DISCONNECT)
&& isValidLength(DRIVER, DRIVER_MAX_LENGTH)
&& isValidLength(MANUFACTURER, MANUFACTURER_MAX_LENGTH)
&& isValidLength(HW_VERSION, MANUFACTURER_MAX_LENGTH)
@ -252,6 +253,34 @@ public final class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
deviceKeyId != null ? deviceKeyId.id() : null);
}
/**
* Returns the device purgeOnDisconnection flag for this device.
*
* @return device purgeOnDisconnection, false if not set.
*/
public boolean purgeOnDisconnection() {
return get(PURGE_ON_DISCONNECT, false);
}
/**
* Sets the purgeOnDisconnection flag for the device.
*
* @param purgeOnDisconnection purges flows, groups, meters on disconnection.
* @return self
*/
public BasicDeviceConfig purgeOnDisconnection(boolean purgeOnDisconnection) {
return (BasicDeviceConfig) setOrClear(PURGE_ON_DISCONNECT, purgeOnDisconnection);
}
/**
* Returns if the device purgeOnDisconnection flag for this device has been explicitly configured.
*
* @return device purgeOnDisconnection explicitly configured, false if not.
*/
public boolean isPurgeOnDisconnectionConfigured() {
return hasField(PURGE_ON_DISCONNECT);
}
// TODO: device port meta-data to be configured via BasicPortsConfig
// TODO: device credentials/keys; in a separate config

View File

@ -31,6 +31,8 @@ import org.onosproject.core.IdGenerator;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@ -174,6 +176,9 @@ public class FlowRuleManager
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected NetworkConfigRegistry netCfgService;
@Activate
public void activate(ComponentContext context) {
store.setDelegate(delegate);
@ -828,7 +833,14 @@ public class FlowRuleManager
case DEVICE_AVAILABILITY_CHANGED:
DeviceId deviceId = event.subject().id();
if (!deviceService.isAvailable(deviceId)) {
if (purgeOnDisconnection) {
BasicDeviceConfig cfg = netCfgService.getConfig(deviceId, BasicDeviceConfig.class);
//if purgeOnDisconnection is set for the device or it's a global configuration
// lets remove the flows. Priority is given to the per device flag
boolean purge = cfg != null && cfg.isPurgeOnDisconnectionConfigured() ?
cfg.purgeOnDisconnection() : purgeOnDisconnection;
if (purge) {
log.info("PurgeOnDisconnection is requested for device {}, " +
"removing flows", deviceId);
store.purgeFlowRule(deviceId);
}
}

View File

@ -21,6 +21,8 @@ import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@ -114,6 +116,9 @@ public class GroupManager
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected MastershipService mastershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected NetworkConfigRegistry netCfgService;
/** Frequency (in seconds) for polling groups via fallback provider. */
private int fallbackGroupPollFrequency = GM_POLL_FREQUENCY_DEFAULT;
@ -169,11 +174,11 @@ public class GroupManager
flag = Tools.isPropertyEnabled(properties, GM_PURGE_ON_DISCONNECTION);
if (flag == null) {
log.info("PurgeOnDisconnection is not configured, " +
"using current value of {}", purgeOnDisconnection);
"using current value of {}", purgeOnDisconnection);
} else {
purgeOnDisconnection = flag;
log.info("Configured. PurgeOnDisconnection is {}",
purgeOnDisconnection ? "enabled" : "disabled");
purgeOnDisconnection ? "enabled" : "disabled");
}
String s = get(properties, GM_POLL_FREQUENCY);
try {
@ -451,8 +456,14 @@ public class GroupManager
log.debug("Device {} became unavailable for {}; clearing initial audit status",
deviceId, event.type());
store.deviceInitialAuditCompleted(deviceId, false);
if (purgeOnDisconnection) {
BasicDeviceConfig cfg = netCfgService.getConfig(deviceId, BasicDeviceConfig.class);
//if purgeOnDisconnection is set for the device or it's a global configuration
// lets remove the groups.
boolean purge = cfg != null && cfg.isPurgeOnDisconnectionConfigured() ?
cfg.purgeOnDisconnection() : purgeOnDisconnection;
if (purge) {
log.info("PurgeOnDisconnection is requested for device {}, " +
"removing groups", deviceId);
store.purgeGroupEntry(deviceId);
}
}

View File

@ -20,6 +20,8 @@ import org.onlab.util.TriConsumer;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@ -114,6 +116,9 @@ public class MeterManager
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected MastershipService mastershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected NetworkConfigRegistry netCfgService;
/** Number of worker threads. */
private int numThreads = MM_NUM_THREADS_DEFAULT;
@ -189,11 +194,11 @@ public class MeterManager
flag = Tools.isPropertyEnabled(properties, MM_PURGE_ON_DISCONNECTION);
if (flag == null) {
log.info("PurgeOnDisconnection is not configured," +
"using current value of {}", purgeOnDisconnection);
"using current value of {}", purgeOnDisconnection);
} else {
purgeOnDisconnection = flag;
log.info("Configured. PurgeOnDisconnection is {}",
purgeOnDisconnection ? "enabled" : "disabled");
purgeOnDisconnection ? "enabled" : "disabled");
}
String s = get(properties, MM_FALLBACK_METER_POLL_FREQUENCY);
@ -442,7 +447,14 @@ public class MeterManager
case DEVICE_AVAILABILITY_CHANGED:
DeviceId deviceId = event.subject().id();
if (!deviceService.isAvailable(deviceId)) {
if (purgeOnDisconnection) {
BasicDeviceConfig cfg = netCfgService.getConfig(deviceId, BasicDeviceConfig.class);
//if purgeOnDisconnection is set for the device or it's a global configuration
// lets remove the meters.
boolean purge = cfg != null && cfg.isPurgeOnDisconnectionConfigured() ?
cfg.purgeOnDisconnection() : purgeOnDisconnection;
if (purge) {
log.info("PurgeOnDisconnection is requested for device {}, " +
"removing meters", deviceId);
store.purgeMeter(deviceId);
}
}