Sahil Lele
Committed by Gerrit Code Review

Devices,hosts, and links can be blocked and kicked off with the network configuration api

Change-Id: I68d427f4886a7b63475df8d35383e2e347946946
......@@ -76,6 +76,18 @@ public class DefaultDeviceDescription extends AbstractDescription
base.chassisId(), annotations);
}
/**
* Creates a device description using the supplied information.
* @param base DeviceDescription to basic information (except for type)
* @param type device type
* @param annotations Annotations to use.
*/
public DefaultDeviceDescription(DeviceDescription base, Type type, SparseAnnotations... annotations) {
this(base.deviceURI(), type, base.manufacturer(),
base.hwVersion(), base.swVersion(), base.serialNumber(),
base.chassisId(), annotations);
}
@Override
public URI deviceURI() {
return uri;
......
......@@ -39,4 +39,12 @@ public interface LinkAdminService extends LinkService {
*/
void removeLinks(DeviceId deviceId);
/**
* Removes all links between between the specified src and
* dst connection points.
*
* @param src link source
* @param dst link destination
*/
void removeLink(ConnectPoint src, ConnectPoint dst);
}
......
......@@ -59,12 +59,25 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-incubator-api</artifactId>
<scope>test</scope>
<classifier>tests</classifier>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-incubator-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
......
......@@ -16,6 +16,7 @@
package org.onosproject.net.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.MastershipRole.MASTER;
......@@ -45,17 +46,23 @@ import org.onosproject.cluster.NodeId;
import org.onosproject.core.Permission;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.incubator.net.config.NetworkConfigEvent;
import org.onosproject.incubator.net.config.NetworkConfigListener;
import org.onosproject.incubator.net.config.NetworkConfigService;
import org.onosproject.incubator.net.config.basics.BasicDeviceConfig;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipTerm;
import org.onosproject.mastership.MastershipTermService;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.Device.Type;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceAdminService;
......@@ -104,6 +111,8 @@ public class DeviceManager
private ScheduledExecutorService backgroundService;
private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceStore store;
......@@ -122,6 +131,11 @@ public class DeviceManager
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceClockProviderService deviceClockProviderService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
@Activate
public void activate() {
backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "manager-background"));
......@@ -130,6 +144,7 @@ public class DeviceManager
store.setDelegate(delegate);
eventDispatcher.addSink(DeviceEvent.class, listenerRegistry);
mastershipService.addListener(mastershipListener);
networkConfigService.addListener(networkConfigListener);
backgroundService.scheduleWithFixedDelay(new Runnable() {
......@@ -148,7 +163,7 @@ public class DeviceManager
@Deactivate
public void deactivate() {
backgroundService.shutdown();
networkConfigService.removeListener(networkConfigListener);
store.unsetDelegate(delegate);
mastershipService.removeListener(mastershipListener);
eventDispatcher.removeSink(DeviceEvent.class);
......@@ -286,7 +301,8 @@ public class DeviceManager
continue;
}
log.info("{} is reachable but did not have a valid role, reasserting", deviceId);
log.info("{} is reachable but did not have a valid role, reasserting",
deviceId);
// isReachable but was not MASTER or STANDBY, get a role and apply
// Note: NONE triggers request to MastershipService
......@@ -319,7 +335,8 @@ public class DeviceManager
DeviceProvider provider = provider();
if (provider == null) {
log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole);
log.warn("Provider for {} was not found. Cannot apply role {}",
deviceId, newRole);
return false;
}
provider.roleChanged(deviceId, newRole);
......@@ -335,8 +352,8 @@ public class DeviceManager
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
checkValidity();
deviceDescription = validateDevice(deviceDescription, deviceId);
log.info("Device {} connected", deviceId);
// check my Role
CompletableFuture<MastershipRole> role = mastershipService.requestRoleFor(deviceId);
try {
......@@ -362,16 +379,33 @@ public class DeviceManager
deviceClockProviderService.setMastershipTerm(deviceId, term);
applyRole(deviceId, MastershipRole.MASTER);
}
DeviceEvent event = store.createOrUpdateDevice(provider().id(),
deviceId, deviceDescription);
DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId,
deviceDescription);
if (event != null) {
log.trace("event: {} {}", event.type(), event);
post(event);
}
}
// returns a DeviceDescription made from the union of the BasicDeviceConfig
// annotations if it exists
private DeviceDescription validateDevice(DeviceDescription deviceDescription, DeviceId deviceId) {
BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
checkState(cfg == null || cfg.isAllowed(), "Device " + deviceId + " is not allowed");
log.info("Device {} connected", deviceId);
if (cfg != null) {
SparseAnnotations finalSparse = processAnnotations(cfg, deviceDescription, deviceId);
if (cfg.type() != Type.SWITCH) {
deviceDescription = new DefaultDeviceDescription(deviceDescription,
cfg.type(), finalSparse);
} else {
deviceDescription = new DefaultDeviceDescription(deviceDescription,
deviceDescription.type(), finalSparse);
}
}
return deviceDescription;
}
@Override
public void deviceDisconnected(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
......@@ -433,7 +467,7 @@ public class DeviceManager
List<PortDescription> portDescriptions) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(portDescriptions,
"Port descriptions list cannot be null");
"Port descriptions list cannot be null");
checkValidity();
if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
// Never been a master for this device
......@@ -459,7 +493,8 @@ public class DeviceManager
if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
// Never been a master for this device
// any update will be ignored.
log.trace("Ignoring {} port update on standby node. {}", deviceId, portDescription);
log.trace("Ignoring {} port update on standby node. {}", deviceId,
portDescription);
return;
}
......@@ -486,7 +521,7 @@ public class DeviceManager
// FIXME: implement response to this notification
log.debug("got reply to a role request for {}: asked for {}, and got {}",
deviceId, requested, response);
deviceId, requested, response);
if (requested == null && response == null) {
// something was off with DeviceProvider, maybe check channel too?
......@@ -525,6 +560,37 @@ public class DeviceManager
deviceId, portStatistics);
post(event);
}
// supplements or replaces deviceDescription annotations with
// BasicDeviceConfig annotations
private SparseAnnotations processAnnotations(BasicDeviceConfig cfg, DeviceDescription deviceDescription,
DeviceId deviceId) {
SparseAnnotations originalAnnotations = deviceDescription.annotations();
DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
if (cfg.driver() != deviceId.toString()) {
newBuilder.set(cfg.DRIVER, cfg.driver());
}
if (cfg.type() != Type.SWITCH) {
newBuilder.set(cfg.TYPE, cfg.type().toString());
}
if (cfg.name() != null) {
newBuilder.set(cfg.NAME, cfg.name());
}
if (cfg.latitude() != -1) {
newBuilder.set(cfg.LATITUDE, Double.toString(cfg.latitude()));
}
if (cfg.longitude() != -1) {
newBuilder.set(cfg.LONGITUDE, Double.toString(cfg.longitude()));
}
if (cfg.rackAddress() != null) {
newBuilder.set(cfg.RACK_ADDRESS, cfg.rackAddress());
}
if (cfg.owner() != null) {
newBuilder.set(cfg.OWNER, cfg.owner());
}
DefaultAnnotations newAnnotations = newBuilder.build();
return DefaultAnnotations.union(originalAnnotations, newAnnotations);
}
}
// Posts the specified event to the local event dispatcher.
......@@ -727,4 +793,30 @@ public class DeviceManager
}
return results;
}
private class InternalNetworkConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
event.configClass().equals(BasicDeviceConfig.class)) {
log.info("Detected Device network config event {}", event.type());
kickOutBadDevice(((DeviceId) event.subject()));
}
}
}
// checks if the specified device is allowed by the BasicDeviceConfig
// and if not, removes it
private void kickOutBadDevice(DeviceId deviceId) {
BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
if (!cfg.isAllowed()) {
Device badDevice = getDevice(deviceId);
if (badDevice != null) {
removeDevice(deviceId);
} else {
log.info("Failed removal: Device {} does not exist", deviceId);
}
}
}
}
......
......@@ -27,11 +27,18 @@ import org.onlab.packet.VlanId;
import org.onosproject.core.Permission;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.incubator.net.config.NetworkConfigEvent;
import org.onosproject.incubator.net.config.NetworkConfigListener;
import org.onosproject.incubator.net.config.NetworkConfigService;
import org.onosproject.incubator.net.config.basics.BasicHostConfig;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostAdminService;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostEvent;
......@@ -51,6 +58,7 @@ import org.slf4j.Logger;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppGuard.checkPermission;
......@@ -70,6 +78,8 @@ public class HostManager
private final ListenerRegistry<HostEvent, HostListener>
listenerRegistry = new ListenerRegistry<>();
private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
private HostStoreDelegate delegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -84,6 +94,9 @@ public class HostManager
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
private HostMonitor monitor;
@Activate
......@@ -91,7 +104,7 @@ public class HostManager
log.info("Started");
store.setDelegate(delegate);
eventDispatcher.addSink(HostEvent.class, listenerRegistry);
networkConfigService.addListener(networkConfigListener);
monitor = new HostMonitor(deviceService, packetService, this);
monitor.start();
}
......@@ -100,6 +113,7 @@ public class HostManager
public void deactivate() {
store.unsetDelegate(delegate);
eventDispatcher.removeSink(HostEvent.class);
networkConfigService.removeListener(networkConfigListener);
log.info("Stopped");
}
......@@ -246,7 +260,6 @@ public class HostManager
private class InternalHostProviderService
extends AbstractProviderService<HostProvider>
implements HostProviderService {
InternalHostProviderService(HostProvider provider) {
super(provider);
}
......@@ -255,6 +268,7 @@ public class HostManager
public void hostDetected(HostId hostId, HostDescription hostDescription) {
checkNotNull(hostId, HOST_ID_NULL);
checkValidity();
hostDescription = validateHost(hostDescription, hostId);
HostEvent event = store.createOrUpdateHost(provider().id(), hostId,
hostDescription);
if (event != null) {
......@@ -262,6 +276,21 @@ public class HostManager
}
}
// returns a HostDescription made from the union of the BasicHostConfig
// annotations if it exists
private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
if (cfg != null) {
SparseAnnotations finalSparse = processAnnotations(cfg, hostDescription);
hostDescription = new DefaultHostDescription(hostId.mac(),
hostDescription.vlan(),
hostDescription.location(),
finalSparse);
}
return hostDescription;
}
@Override
public void hostVanished(HostId hostId) {
checkNotNull(hostId, HOST_ID_NULL);
......@@ -273,6 +302,30 @@ public class HostManager
}
}
// Supplements or replaces hostDescriptions's annotations with BasicHostConfig's
// annotations
private SparseAnnotations processAnnotations(BasicHostConfig cfg, HostDescription hostDescription) {
SparseAnnotations originalAnnotations = hostDescription.annotations();
DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
if (cfg.name() != null) {
newBuilder.set(cfg.NAME, cfg.name());
}
if (cfg.latitude() != -1) {
newBuilder.set(cfg.LATITUDE, Double.toString(cfg.latitude()));
}
if (cfg.longitude() != -1) {
newBuilder.set(cfg.LONGITUDE, Double.toString(cfg.longitude()));
}
if (cfg.rackAddress() != null) {
newBuilder.set(cfg.RACK_ADDRESS, cfg.rackAddress());
}
if (cfg.owner() != null) {
newBuilder.set(cfg.OWNER, cfg.owner());
}
DefaultAnnotations newAnnotations = newBuilder.build();
return DefaultAnnotations.union(originalAnnotations, newAnnotations);
}
// Posts the specified event to the local event dispatcher.
private void post(HostEvent event) {
if (event != null) {
......@@ -287,4 +340,32 @@ public class HostManager
post(event);
}
}
// listens for NetworkConfigEvents of type BasicHostConfig and removes
// links that the config does not allow
private class InternalNetworkConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
event.configClass().equals(BasicHostConfig.class)) {
log.info("Detected Host network config event {}", event.type());
kickOutBadHost(((HostId) event.subject()));
}
}
}
// checks if the specified host is allowed by the BasicHostConfig
// and if not, removes it
private void kickOutBadHost(HostId hostId) {
BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
if (cfg != null && !cfg.isAllowed()) {
Host badHost = getHost(hostId);
if (badHost != null) {
removeHost(hostId);
} else {
log.info("Failed removal: Host {} does not exist", hostId);
}
}
}
}
......
......@@ -27,14 +27,22 @@ import org.apache.felix.scr.annotations.Service;
import org.onosproject.core.Permission;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.incubator.net.config.NetworkConfigEvent;
import org.onosproject.incubator.net.config.NetworkConfigListener;
import org.onosproject.incubator.net.config.NetworkConfigService;
import org.onosproject.incubator.net.config.basics.BasicLinkConfig;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Link.State;
import org.onosproject.net.LinkKey;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkAdminService;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkEvent;
......@@ -49,9 +57,12 @@ import org.onosproject.net.provider.AbstractProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
import org.slf4j.Logger;
import java.time.Duration;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.onosproject.net.LinkKey.linkKey;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppGuard.checkPermission;
......@@ -78,6 +89,8 @@ public class LinkManager
private final DeviceListener deviceListener = new InternalDeviceListener();
private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkStore store;
......@@ -87,11 +100,15 @@ public class LinkManager
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
@Activate
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(LinkEvent.class, listenerRegistry);
deviceService.addListener(deviceListener);
networkConfigService.addListener(networkConfigListener);
log.info("Started");
}
......@@ -100,6 +117,7 @@ public class LinkManager
store.unsetDelegate(delegate);
eventDispatcher.removeSink(LinkEvent.class);
deviceService.removeListener(deviceListener);
networkConfigService.removeListener(networkConfigListener);
log.info("Stopped");
}
......@@ -206,17 +224,19 @@ public class LinkManager
removeLinks(getDeviceLinks(deviceId), false);
}
public void removeLink(ConnectPoint src, ConnectPoint dst) {
post(store.removeLink(src, dst));
}
@Override
public void addListener(LinkListener listener) {
checkPermission(Permission.LINK_EVENT);
listenerRegistry.addListener(listener);
}
@Override
public void removeListener(LinkListener listener) {
checkPermission(Permission.LINK_EVENT);
listenerRegistry.removeListener(listener);
}
......@@ -229,7 +249,7 @@ public class LinkManager
removeLinks(event.subject().id());
} else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
removeLinks(new ConnectPoint(event.subject().id(),
event.port().number()));
event.port().number()));
}
}
}
......@@ -252,15 +272,62 @@ public class LinkManager
public void linkDetected(LinkDescription linkDescription) {
checkNotNull(linkDescription, LINK_DESC_NULL);
checkValidity();
linkDescription = validateLink(linkDescription);
LinkEvent event = store.createOrUpdateLink(provider().id(),
linkDescription);
linkDescription);
if (event != null) {
log.info("Link {} detected", linkDescription);
post(event);
}
}
// returns a LinkDescription made from the union of the BasicLinkConfig
// annotations if it exists
private LinkDescription validateLink(LinkDescription linkDescription) {
// TODO Investigate whether this can be made more efficient
BasicLinkConfig cfg = networkConfigService.getConfig(linkKey(linkDescription.src(),
linkDescription.dst()),
BasicLinkConfig.class);
BasicLinkConfig cfgTwo = networkConfigService.getConfig(linkKey(linkDescription.dst(),
linkDescription.src()),
BasicLinkConfig.class);
checkState(cfg == null || cfg.isAllowed(), "Link " + linkDescription.toString() + " is not allowed");
checkState(cfgTwo == null || cfgTwo.isAllowed(), "Link " + linkDescription.toString() + " is not allowed");
if (cfg != null) {
SparseAnnotations finalSparse = processAnnotations(cfg, linkDescription);
// check whether config has a specified type
if (cfg.type() != Link.Type.DIRECT) {
linkDescription = new DefaultLinkDescription(linkDescription.src(),
linkDescription.dst(),
cfg.type(), finalSparse);
} else {
linkDescription = new DefaultLinkDescription(linkDescription.src(),
linkDescription.dst(),
linkDescription.type(), finalSparse);
}
}
return linkDescription;
}
// supplements or replaces linkDescriptions's annotations with BasicLinkConfig's
// annotations
private SparseAnnotations processAnnotations(BasicLinkConfig cfg, LinkDescription linkDescription) {
SparseAnnotations originalAnnotations = linkDescription.annotations();
DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
if (cfg.type() != Link.Type.DIRECT) {
newBuilder.set(cfg.TYPE, cfg.type().toString());
}
if (cfg.latency() != Duration.ofNanos(-1)) {
newBuilder.set(cfg.LATENCY, cfg.latency().toString());
}
if (cfg.bandwidth() != -1) {
newBuilder.set(cfg.BANDWIDTH, String.valueOf(cfg.bandwidth()));
}
DefaultAnnotations newAnnotations = newBuilder.build();
return DefaultAnnotations.union(originalAnnotations, newAnnotations);
}
@Override
public void linkVanished(LinkDescription linkDescription) {
checkNotNull(linkDescription, LINK_DESC_NULL);
......@@ -297,7 +364,7 @@ public class LinkManager
}
// Removes all links in the specified set and emits appropriate events.
private void removeLinks(Set<Link> links, boolean isSoftRemove) {
private void removeLinks(Set<Link> links, boolean isSoftRemove) {
for (Link link : links) {
LinkEvent event = isSoftRemove ?
store.removeOrDownLink(link.src(), link.dst()) :
......@@ -323,4 +390,24 @@ public class LinkManager
post(event);
}
}
// listens for NetworkConfigEvents of type BasicLinkConfig and removes
// links that the config does not allow
private class InternalNetworkConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
event.configClass().equals(BasicLinkConfig.class)) {
log.info("Detected Link network config event {}", event.type());
LinkKey lk = (LinkKey) event.subject();
BasicLinkConfig cfg = networkConfigService.getConfig(lk, BasicLinkConfig.class);
if (cfg != null && !cfg.isAllowed()) {
log.info("Kicking out links between {} and {}", lk.src(), lk.dst());
removeLink(lk.src(), lk.dst());
removeLink(lk.dst(), lk.src());
}
}
}
}
}
......
......@@ -32,6 +32,7 @@ import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.event.Event;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.incubator.net.config.NetworkConfigServiceAdapter;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.mastership.MastershipTerm;
import org.onosproject.mastership.MastershipTermService;
......@@ -115,8 +116,10 @@ public class DeviceManagerTest {
mgr.termService = mastershipManager;
mgr.clusterService = new TestClusterService();
mgr.deviceClockProviderService = new TestClockProviderService();
mgr.networkConfigService = new TestNetworkConfigService();
mgr.activate();
service.addListener(listener);
provider = new TestProvider();
......@@ -349,4 +352,7 @@ public class DeviceManagerTest {
return registerdBefore.contains(deviceId);
}
}
private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
}
}
......
......@@ -37,6 +37,7 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.event.Event;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.incubator.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
......@@ -123,6 +124,7 @@ public class HostManagerTest {
mgr.store = new SimpleHostStore();
mgr.eventDispatcher = new TestEventDispatcher();
registry = mgr;
mgr.networkConfigService = new TestNetworkConfigService();
mgr.activate();
mgr.addListener(listener);
......@@ -520,4 +522,7 @@ public class HostManagerTest {
assertTrue(storedAddresses.size() == 2);
assertTrue(storedAddresses.equals(Sets.newHashSet(add1, add2)));
}
private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
}
}
......
......@@ -20,6 +20,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.event.Event;
import org.onosproject.incubator.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
......@@ -86,6 +87,7 @@ public class LinkManagerTest {
protected DeviceManager devmgr = new TestDeviceManager();
@Before
public void setUp() {
mgr = new LinkManager();
......@@ -95,6 +97,7 @@ public class LinkManagerTest {
mgr.store = new SimpleLinkStore();
mgr.eventDispatcher = new TestEventDispatcher();
mgr.deviceService = devmgr;
mgr.networkConfigService = new TestNetworkConfigService();
mgr.activate();
DEVICEIDMAP.put(DID1, DEV1);
......@@ -302,5 +305,6 @@ public class LinkManagerTest {
}
}
private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
}
}
......
package org.onosproject.incubator.net.config;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Set;
/**
* Test adapter for network configuration service.
*/
public class NetworkConfigServiceAdapter implements NetworkConfigService {
@Override
public Set<Class> getSubjectClasses() {
return null;
}
@Override
public SubjectFactory getSubjectFactory(String subjectKey) {
return null;
}
@Override
public SubjectFactory getSubjectFactory(Class subjectClass) {
return null;
}
@Override
public Class<? extends Config> getConfigClass(String subjectKey, String configKey) {
return null;
}
@Override
public <S> Set<S> getSubjects(Class<S> subjectClass) {
return null;
}
@Override
public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
return null;
}
@Override
public <S> Set<? extends Config<S>> getConfigs(S subject) {
return null;
}
@Override
public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
return null;
}
@Override
public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
return null;
}
@Override
public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, ObjectNode json) {
return null;
}
@Override
public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
}
@Override
public void addListener(NetworkConfigListener listener) {
}
@Override
public void removeListener(NetworkConfigListener listener) {
}
}
......@@ -270,7 +270,11 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
private void updateLocation(HostId hid, MacAddress mac,
VlanId vlan, HostLocation hloc) {
HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
providerService.hostDetected(hid, desc);
try {
providerService.hostDetected(hid, desc);
} catch (IllegalStateException e) {
log.debug("Host {} suppressed", hid);
}
}
/**
......@@ -286,7 +290,11 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
VlanId vlan, HostLocation hloc,
IpAddress ip) {
HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ip);
providerService.hostDetected(hid, desc);
try {
providerService.hostDetected(hid, desc);
} catch (IllegalStateException e) {
log.debug("Host {} suppressed", hid);
}
}
@Override
......
......@@ -229,7 +229,12 @@ public class LinkDiscovery implements TimerTask {
} else {
ld = new DefaultLinkDescription(src, dst, Type.DIRECT);
}
linkProvider.linkDetected(ld);
try {
linkProvider.linkDetected(ld);
} catch (IllegalStateException e) {
return true;
}
return true;
}
return false;
......
{
"devices": {
"of:0000000000000009": {
"basic": {
"allowed": true,
"owner": "Luigi"
}
},
"of:0000000000000008": {
"basic": {
"name": "NameChangeAgain",
"allowed": true,
"owner": "Mario"
}
},
"of:0000000000000007": {
"basic": {
"allowed": true,
"owner": "Peach",
"latitude": "25"
}
}
},
"links": {
"of:0000000000000006/2-of:0000000000000007/2": {
"basic": {
"allowed": true
}
}
},
"hosts": {
"00:00:00:00:00:03/-1": {
"basic": {
"allowed": true
}
}
}
}
\ No newline at end of file
{
"devices": {
"of:001122334455667788" : {
"basic" : {
"allowed": false,
"name": "Bad Device",
"of:0000000000000009": {
"basic": {
"allowed": true,
"owner": "Luigi"
}
},
"of:0000000000000008": {
"basic": {
"name": "NameChange",
"allowed": true,
"owner": "Mario"
}
},
"of:0000000000000007": {
"basic": {
"allowed": true,
"owner": "Peach",
"latitude": "25"
}
},
"of:0000000000000003": {
"basic": {
"allowed": true,
"owner": "Wario"
}
}
},
"links": {
"of:0000000000000006/2-of:0000000000000007/2": {
"basic": {
"allowed": true
}
}
},
"hosts": {},
"links": {}
"hosts": {
"00:00:00:00:00:03/-1": {
"basic": {
"allowed": false
}
},
"00:00:00:00:00:02/-1": {
"basic": {
"allowed": false
}
},
"00:00:00:00:00:01/-1": {
"basic": {
"allowed": false
}
}
}
}
\ No newline at end of file
......
......@@ -87,7 +87,7 @@ public class NetworkConfigWebResource extends AbstractWebResource {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = mapper().createObjectNode();
produceSubjectJson(service, root,
service.getSubjectFactory(subjectKey).createSubject(subject));
service.getSubjectFactory(subjectKey).createSubject(subject));
return ok(root).build();
}
......@@ -140,7 +140,7 @@ public class NetworkConfigWebResource extends AbstractWebResource {
ObjectNode root = (ObjectNode) mapper().readTree(request);
root.fieldNames()
.forEachRemaining(sk -> consumeJson(service, (ObjectNode) root.path(sk),
service.getSubjectFactory(sk)));
service.getSubjectFactory(sk)));
return Response.ok().build();
}
......@@ -183,8 +183,8 @@ public class NetworkConfigWebResource extends AbstractWebResource {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
consumeSubjectJson(service, root,
service.getSubjectFactory(subjectKey).createSubject(subject),
subjectKey);
service.getSubjectFactory(subjectKey).createSubject(subject),
subjectKey);
return Response.ok().build();
}
......@@ -210,16 +210,16 @@ public class NetworkConfigWebResource extends AbstractWebResource {
NetworkConfigService service = get(NetworkConfigService.class);
ObjectNode root = (ObjectNode) mapper().readTree(request);
service.applyConfig(service.getSubjectFactory(subjectKey).createSubject(subject),
service.getConfigClass(subjectKey, configKey), root);
service.getConfigClass(subjectKey, configKey), root);
return Response.ok().build();
}
private void consumeJson(NetworkConfigService service, ObjectNode classNode,
SubjectFactory subjectFactory) {
classNode.fieldNames().forEachRemaining(s ->
consumeSubjectJson(service, (ObjectNode) classNode.path(s),
subjectFactory.createSubject(s),
subjectFactory.subjectKey()));
consumeSubjectJson(service, (ObjectNode) classNode.path(s),
subjectFactory.createSubject(s),
subjectFactory.subjectKey()));
}
private void consumeSubjectJson(NetworkConfigService service,
......@@ -227,7 +227,7 @@ public class NetworkConfigWebResource extends AbstractWebResource {
String subjectKey) {
subjectNode.fieldNames().forEachRemaining(c ->
service.applyConfig(subject, service.getConfigClass(subjectKey, c),
(ObjectNode) subjectNode.path(c)));
(ObjectNode) subjectNode.path(c)));
}
......@@ -272,4 +272,46 @@ public class NetworkConfigWebResource extends AbstractWebResource {
return Response.ok().build();
}
/**
* Clears all network configurations.
*
* @return empty response
*/
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response upload() {
NetworkConfigService service = get(NetworkConfigService.class);
service.getSubjectClasses().forEach(subjectClass -> {
service.getSubjects(subjectClass).forEach(subject -> {
service.getConfigs(subject).forEach(config -> {
service.removeConfig(subject, config.getClass());
});
});
});
return Response.ok().build();
}
// TODO: this one below doesn't work correctly
/**
* Clears network configuration for the specified subject class.
*
* @param subjectKey subject class key
* @return empty response
*/
@DELETE
@Path("{subjectKey}/")
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public Response upload(@PathParam("subjectKey") String subjectKey) {
NetworkConfigService service = get(NetworkConfigService.class);
service.getSubjects(service.getSubjectFactory(subjectKey).getClass()).forEach(subject -> {
service.getConfigs(subject).forEach(config -> {
service.removeConfig(subject, config.getClass());
});
});
return Response.ok().build();
}
}
......