Simplified the port handling logic for VM live migration case
Change-Id: Ib28978bb2ee62c4719261c38eebb72a006f81f19
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
index 6094e72..b2af7b3 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
@@ -16,8 +16,6 @@
package org.onosproject.openstacknetworking.impl;
import com.google.common.base.Strings;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -32,9 +30,7 @@
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultHost;
import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
@@ -50,8 +46,7 @@
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
-import org.onosproject.openstacknetworking.api.InstancePort;
-import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.InstancePortAdminService;
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeEvent;
@@ -62,7 +57,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -70,11 +65,12 @@
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_CREATE_TIME;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_NETWORK_ID;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_PORT_ID;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_SEGMENT_ID;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
import static org.onosproject.openstacknetworking.api.Constants.portNamePrefixMap;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_CREATE_TIME;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
@Service
@@ -85,7 +81,6 @@
private static final String PORT_NAME_PREFIX_VM = "tap";
private static final String ERR_ADD_HOST = "Failed to add host: ";
- private static final String ANNOTATION_SEGMENT_ID = "segId";
private static final String SONA_HOST_SCHEME = "sona";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -110,7 +105,7 @@
protected OpenstackNodeService osNodeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected InstancePortService instancePortService;
+ protected InstancePortAdminService instancePortAdminService;
private final ExecutorService deviceEventExecutor =
Executors.newSingleThreadExecutor(groupedThreads("openstacknetworking", "device-event"));
@@ -119,9 +114,6 @@
private HostProviderService hostProvider;
- private Map<HostId, Device> hostDeviceMap = Maps.newConcurrentMap();
- private Set<Host> migratingHosts = Sets.newConcurrentHashSet();
-
/**
* Creates OpenStack switching host provider.
*/
@@ -183,58 +175,55 @@
return;
}
- MacAddress macAddr = MacAddress.valueOf(osPort.getMacAddress());
+ MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
+ HostId hostId = HostId.hostId(mac);
+
+ // typically one openstack port should only be bound to one fix IP address;
+ // however, openstack4j binds multiple fixed IPs to one port, this might
+ // be a defect of openstack4j implementation
+
+ // TODO: we need to find a way to bind multiple ports from multiple
+ // openstack networks into one host sooner or later
Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
- .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
- .collect(Collectors.toSet());
+ .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
+ .collect(Collectors.toSet());
+
+ // connect point is the combination of switch ID with port number where
+ // the host is attached to
ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
- HostId oldHostId = HostId.hostId(macAddr);
- // In VM migration case, a duplicated host port (port created in at new
- // compute node) will be detected at OVS; in this case, we will store
- // the old host instance into migration list, and overwrite old host
- // with new host instance issue host creation event to ONOS core
- Device oldDevice = hostDeviceMap.get(oldHostId);
+ long createTime = System.currentTimeMillis();
- if (device != null && oldDevice != null && !oldDevice.equals(device)) {
- Host host = hostService.getHost(oldHostId);
- if (host != null) {
- migratingHosts.add(host);
+ // we check whether the host already attached to some locations
+ Host host = hostService.getHost(hostId);
+ if (host != null) {
+ Set<HostLocation> locations = host.locations().stream()
+ .filter(l -> l.deviceId().equals(connectPoint.deviceId()))
+ .filter(l -> l.port().equals(connectPoint.port()))
+ .collect(Collectors.toSet());
+ if (locations.size() == 0) {
+ hostProvider.addLocationToHost(hostId,
+ new HostLocation(connectPoint, createTime));
}
- }
+ } else {
- if (device != null) {
- hostDeviceMap.put(oldHostId, device);
- }
+ DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+ .set(ANNOTATION_NETWORK_ID, osPort.getNetworkId())
+ .set(ANNOTATION_PORT_ID, osPort.getId())
+ .set(ANNOTATION_CREATE_TIME, String.valueOf(createTime));
- DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
- .set(ANNOTATION_NETWORK_ID, osPort.getNetworkId())
- .set(ANNOTATION_PORT_ID, osPort.getId())
- .set(ANNOTATION_CREATE_TIME, String.valueOf(System.currentTimeMillis()));
+ // FLAT does not require segment ID
+ if (osNet.getNetworkType() != NetworkType.FLAT) {
+ annotations.set(ANNOTATION_SEGMENT_ID, osNet.getProviderSegID());
+ }
- if (osNet.getNetworkType() != NetworkType.FLAT) {
- annotations.set(ANNOTATION_SEGMENT_ID, osNet.getProviderSegID());
-
- }
-
- long currentTime = System.currentTimeMillis();
-
- HostDescription hostDesc = new DefaultHostDescription(
- macAddr,
- VlanId.NONE,
- new HostLocation(connectPoint, currentTime),
- fixedIps,
- annotations.build());
-
- HostId hostId = HostId.hostId(macAddr);
- hostProvider.hostDetected(hostId, hostDesc, false);
-
- if (device != null && oldDevice != null && !oldDevice.equals(device)) {
- Host oldHost = hostService.getHost(oldHostId);
- Host newHost = new DefaultHost(oldHost.providerId(), hostId, macAddr,
- VlanId.NONE, new HostLocation(connectPoint, currentTime),
- fixedIps, annotations.build());
- instancePortService.migrationPortAdded(HostBasedInstancePort.of(newHost));
+ HostDescription hostDesc = new DefaultHostDescription(
+ mac,
+ VlanId.NONE,
+ new HostLocation(connectPoint, createTime),
+ fixedIps,
+ annotations.build());
+ hostProvider.hostDetected(hostId, hostDesc, false);
}
}
@@ -248,33 +237,26 @@
*/
private void processPortRemoved(DeviceEvent event) {
Port port = event.port();
- DeviceId deviceId = event.subject().id();
ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
- Set<Host> hostsToBeRemoved = hostService.getConnectedHosts(connectPoint);
+ Set<Host> hosts = hostService.getConnectedHosts(connectPoint);
- if (hostsToBeRemoved.size() == 0) {
+ hosts.forEach(h -> {
+ Optional<HostLocation> hostLocation = h.locations().stream()
+ .filter(l -> l.deviceId().equals(port.element().id()))
+ .filter(l -> l.port().equals(port.number())).findAny();
- for (Host host : migratingHosts) {
- if (host.location() == null) {
- continue;
- }
- String hostLocation = host.location().toString();
- StringBuilder deviceIdWithPort = new StringBuilder();
- deviceIdWithPort.append(deviceId.toString());
- deviceIdWithPort.append("/");
- deviceIdWithPort.append(port.number().toString());
-
- if (hostLocation.equals(deviceIdWithPort.toString())) {
- InstancePort instPort = HostBasedInstancePort.of(host);
- instancePortService.migrationPortRemoved(instPort);
- migratingHosts.remove(host);
- }
+ // if the host contains only one filtered location, we remove the host
+ if (h.locations().size() == 1) {
+ hostProvider.hostVanished(h.id());
}
- } else {
- hostsToBeRemoved.forEach(host -> hostProvider.hostVanished(host.id()));
- }
+ // if the host contains multiple locations, we simply remove the
+ // host location
+ if (h.locations().size() > 1 && hostLocation.isPresent()) {
+ hostProvider.removeLocationFromHost(h.id(), hostLocation.get());
+ }
+ });
}
/**