Fix for host store not updated when host moves
Change-Id: I39b4fdd3fdcd0074ba1ca8c3a521d7c9d203a391
diff --git a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
index 8cf463d..b2f90ee 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
@@ -85,7 +85,7 @@
private ConsistentMap<HostId, DefaultHost> hostsConsistentMap;
private Map<HostId, DefaultHost> hosts;
private Map<IpAddress, Set<Host>> hostsByIp;
- private MapEventListener<HostId, DefaultHost> hostLocationTracker =
+ MapEventListener<HostId, DefaultHost> hostLocationTracker =
new HostLocationTracker();
private ScheduledExecutorService executor;
@@ -421,6 +421,7 @@
}
private Set<Host> removeHosts(Set<Host> existingHosts, Host host) {
+
if (existingHosts != null) {
existingHosts.removeIf(existingHost -> existingHost.id().equals(host.id()));
}
@@ -432,11 +433,12 @@
}
private void updateHostsByIp(DefaultHost host, DefaultHost prevHost) {
- Set<IpAddress> oldIps = prevHost != null ? prevHost.ipAddresses() : Collections.emptySet();
- // Let's add first each new ip
- Sets.difference(host.ipAddresses(), oldIps).forEach(
+ // Let's update first the current ips
+ host.ipAddresses().forEach(
ip -> hostsByIp.compute(ip, (k, v) -> v == null ? addHosts(host) : updateHosts(v, host)));
+
// Let's remove then each old ip
+ Set<IpAddress> oldIps = prevHost != null ? prevHost.ipAddresses() : Collections.emptySet();
Sets.difference(oldIps, host.ipAddresses()).forEach(
ip -> hostsByIp.computeIfPresent(ip, (k, v) -> removeHosts(v, host)));
}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
index 0879885..a8caf2d 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
@@ -15,27 +15,34 @@
*/
package org.onosproject.store.host.impl;
+import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.TestStorageService;
import com.google.common.collect.Sets;
+import org.onosproject.store.service.Versioned;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.*;
/**
* Tests for the ECHostStore.
@@ -54,9 +61,42 @@
private static final ProviderId PID2 = new ProviderId("of", "foo2");
private static final HostDescription HOST_LEARNT =
- createHostDesc(HOSTID, Sets.newHashSet(IP1), false);
+ createHostDesc(HOSTID, Sets.newHashSet(IP1), false, Collections.emptySet());
private static final HostDescription HOST_CONFIGURED =
- createHostDesc(HOSTID, Sets.newHashSet(IP1), true);
+ createHostDesc(HOSTID, Sets.newHashSet(IP1), true, Collections.emptySet());
+ // Host with locations
+ private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
+ private static final PortNumber P1 = PortNumber.portNumber(1);
+ private static final PortNumber P2 = PortNumber.portNumber(2);
+ private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
+ private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
+ private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
+ private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
+ private static final Set<HostLocation> HOST_LOCATIONS = ImmutableSet.of(HOST_LOC11, HOST_LOC12);
+ private static final Set<HostLocation> HOST_LOCATION = ImmutableSet.of(HOST_LOC11);
+ private static final Set<HostLocation> NONE_LOCATION = ImmutableSet.of(HostLocation.NONE);
+ private static final Set<IpAddress> HOST_ADDRESS = ImmutableSet.of(IP1);
+ private static final Set<IpAddress> HOST_ADDRESSES = ImmutableSet.of(IP1, IP2);
+ private static final HostDescription HOST_LEARNT_WITH_LOCATIONS =
+ createHostDesc(HOSTID, HOST_ADDRESS, false, HOST_LOCATIONS);
+ private static final HostDescription HOST_LEARNT_WITH_ADDRESSES =
+ createHostDesc(HOSTID, Sets.newHashSet(IP1, IP2), false, Collections.emptySet());
+ private static final DefaultHost OLD_HOST = new DefaultHost(PID, HOSTID,
+ HOST_LEARNT_WITH_ADDRESSES.hwAddress(),
+ HOST_LEARNT_WITH_ADDRESSES.vlan(),
+ HOST_LEARNT_WITH_ADDRESSES.locations(),
+ HOST_LEARNT_WITH_ADDRESSES.ipAddress(),
+ HOST_LEARNT_WITH_ADDRESSES.configured(),
+ HOST_LEARNT_WITH_ADDRESSES.annotations());
+ private static final DefaultHost NEW_HOST = new DefaultHost(PID, HOSTID,
+ HOST_LEARNT_WITH_ADDRESSES.hwAddress(),
+ HOST_LEARNT_WITH_ADDRESSES.vlan(),
+ HOST_LEARNT_WITH_ADDRESSES.locations(),
+ HOST_ADDRESS,
+ HOST_LEARNT_WITH_ADDRESSES.configured(),
+ HOST_LEARNT_WITH_ADDRESSES.annotations());
+ private static final MapEvent<HostId, DefaultHost> HOST_EVENT =
+ new MapEvent<>("foobar", HOSTID, new Versioned<>(NEW_HOST, 0), new Versioned<>(OLD_HOST, 0));
@Before
public void setUp() {
@@ -146,16 +186,130 @@
assertEquals(PID2, hostInStore.providerId());
}
+ @Test
+ public void testRemoteUpdateHostsByIp() {
+ // Add host in the store
+ ecXHostStore.createOrUpdateHost(PID, HOSTID, HOST_LEARNT_WITH_ADDRESSES, false);
+
+ // Expected a learnt host with an IP
+ Host hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(NONE_LOCATION, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESSES, hostInHostsByIp.ipAddresses());
+
+ // Remove one ip - simulating the update in other instances
+ ecXHostStore.hostLocationTracker.event(HOST_EVENT);
+
+ // Expected null
+ hostInHostsByIp = ecXHostStore.getHosts(IP2).stream()
+ .findFirst().orElse(null);
+ assertNull(hostInHostsByIp);
+
+ // Expected an host with an ip address
+ hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(NONE_LOCATION, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESS, hostInHostsByIp.ipAddresses());
+
+ }
+
+ @Test
+ public void testLocalUpdateHostsByIp() {
+ // Add host in the store
+ ecXHostStore.createOrUpdateHost(PID, HOSTID, HOST_LEARNT_WITH_ADDRESSES, false);
+
+ // Expected a learnt host with an IP
+ Host hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(NONE_LOCATION, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESSES, hostInHostsByIp.ipAddresses());
+
+ // Remove one ip
+ ecXHostStore.removeIp(HOSTID, IP2);
+
+ // Expected null
+ hostInHostsByIp = ecXHostStore.getHosts(IP2).stream()
+ .findFirst().orElse(null);
+ assertNull(hostInHostsByIp);
+
+ // Expected an host with an ip address
+ hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(NONE_LOCATION, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESS, hostInHostsByIp.ipAddresses());
+
+ }
+
+ @Test
+ public void testUpdateLocationInHostsByIp() {
+ // Add host in the store
+ ecXHostStore.createOrUpdateHost(PID, HOSTID, HOST_LEARNT_WITH_LOCATIONS, false);
+ Host hostInHosts = ecXHostStore.getHost(HOSTID);
+
+ // Expected a learnt host with an IP
+ assertFalse(hostInHosts.configured());
+ assertEquals(HOSTID, hostInHosts.id());
+ assertEquals(PID, hostInHosts.providerId());
+ assertEquals(HOST_LOCATIONS, hostInHosts.locations());
+ assertEquals(HOST_ADDRESS, hostInHosts.ipAddresses());
+ Host hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(HOST_LOCATIONS, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESS, hostInHostsByIp.ipAddresses());
+
+ // Remove one location
+ ecXHostStore.removeLocation(HOSTID, HOST_LOC12);
+
+ // Verify hosts is updated
+ hostInHosts = ecXHostStore.getHost(HOSTID);
+ assertFalse(hostInHosts.configured());
+ assertEquals(HOSTID, hostInHosts.id());
+ assertEquals(PID, hostInHosts.providerId());
+ assertEquals(HOST_LOCATION, hostInHosts.locations());
+ assertEquals(HOST_ADDRESS, hostInHosts.ipAddresses());
+
+ // Verify hostsByIp is updated
+ hostInHostsByIp = ecXHostStore.getHosts(IP1).stream()
+ .findFirst().orElse(null);
+ assertNotNull(hostInHostsByIp);
+ assertFalse(hostInHostsByIp.configured());
+ assertEquals(HOSTID, hostInHostsByIp.id());
+ assertEquals(PID, hostInHostsByIp.providerId());
+ assertEquals(HOST_LOCATION, hostInHostsByIp.locations());
+ assertEquals(HOST_ADDRESS, hostInHostsByIp.ipAddresses());
+ }
+
+
private static HostDescription createHostDesc(HostId hostId, Set<IpAddress> ips) {
- return createHostDesc(hostId, ips, false);
+ return createHostDesc(hostId, ips, false, Collections.emptySet());
}
private static HostDescription createHostDesc(HostId hostId, Set<IpAddress> ips,
- boolean configured) {
- return new DefaultHostDescription(hostId.mac(),
- hostId.vlanId(),
- HostLocation.NONE,
- ips,
- configured);
+ boolean configured, Set<HostLocation> locations) {
+ return locations.isEmpty() ?
+ new DefaultHostDescription(hostId.mac(), hostId.vlanId(), HostLocation.NONE, ips, configured) :
+ new DefaultHostDescription(hostId.mac(), hostId.vlanId(), locations, ips, configured);
+
}
+
}