CORD-417 Update group buckets when a VM is created or terminated
Change-Id: Ib1aba443708a13499f21c08b39b777c876595fac
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index d119a5a..127c7c9 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -103,7 +103,6 @@
.register(NodeState.class);
private static final String DEFAULT_BRIDGE = "br-int";
private static final String VPORT_PREFIX = "tap";
- private static final String GWPORT_PREFIX = "qr-";
private static final String DEFAULT_TUNNEL = "vxlan";
private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
{
@@ -379,13 +378,14 @@
* @param node cordvtn node
*/
private void postInit(CordVtnNode node) {
- log.info("Initializing {}", node.hostname());
disconnect(node);
ruleInstaller.init(node.intBrId(), getTunnelPort(node.intBrId()));
hostService.getConnectedHosts(node.intBrId())
.stream()
.forEach(vmHandler::connected);
+
+ log.info("Finished initializing {}", node.hostname());
}
/**
@@ -646,13 +646,16 @@
private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
checkNotNull(vNet);
- return openstackService.ports(vNet.id()).stream()
+ Set<Host> hosts = openstackService.ports(vNet.id()).stream()
.filter(port -> port.deviceOwner().contains("compute"))
.map(port -> hostService.getHostsByMac(port.macAddress())
.stream()
.findFirst()
.orElse(null))
.collect(Collectors.toSet());
+
+ hosts.remove(null);
+ return hosts;
}
/**
@@ -687,16 +690,15 @@
}
/**
- * Returns if the host is gateway interface.
- * This codes should be removed after adding proxy arp for the gateway.
+ * Returns if the host is VM or not.
*
* @param host host
- * @return true if the host is gateway
+ * @return true if the host is a VM.
*/
- private boolean isGateway(Host host) {
+ private boolean isVm(Host host) {
Port port = deviceService.getPort(host.location().deviceId(),
host.location().port());
- return port.annotations().value("portName").contains(GWPORT_PREFIX);
+ return port.annotations().value("portName").contains(VPORT_PREFIX);
}
/**
@@ -892,8 +894,8 @@
@Override
public void connected(Host host) {
- // TODO remove check gateway here after applying network config host provider
- if (isGateway(host)) {
+ // TODO remove check VM here after applying network config host provider
+ if (!isVm(host)) {
return;
}
@@ -924,7 +926,11 @@
checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
vNet);
- // TODO add new VM to related service group if exists
+ CordService service = getCordService(vNet);
+ // TODO check if the service needs an update on its group buckets after done CORD-433
+ if (service != null) {
+ ruleInstaller.updateServiceGroup(service);
+ }
}
@Override
@@ -943,7 +949,12 @@
log.info("VM {} is vanished", host.id());
ruleInstaller.removeBasicConnectionRules(host);
- // TODO remove the VM from related service group if exists
+ CordService service = getCordService(vNet);
+ // TODO check if the service needs an update on its group buckets after done CORD-433
+ if (service != null) {
+ ruleInstaller.updateServiceGroup(service);
+ }
+
hostNetMap.remove(host.id());
}
}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java
index 4e044e1..1984629 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java
@@ -70,6 +70,7 @@
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.slf4j.Logger;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -188,40 +189,6 @@
}
/**
- * Populates service dependency rules.
- *
- * @param tService tenant cord service
- * @param pService provider cord service
- */
- public void populateServiceDependencyRules(CordService tService, CordService pService) {
- checkNotNull(tService);
- checkNotNull(pService);
-
- Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
- Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
- Ip4Address serviceIp = pService.serviceIp().getIp4Address();
-
- Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
- Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
-
- for (Device device : deviceService.getAvailableDevices(SWITCH)) {
- GroupId groupId = createServiceGroup(device.id(), pService);
- outGroups.put(device.id(), groupId);
-
- Set<PortNumber> vms = tService.hosts().keySet()
- .stream()
- .filter(host -> host.location().deviceId().equals(device.id()))
- .map(host -> host.location().port())
- .collect(Collectors.toSet());
- inPorts.put(device.id(), vms);
- }
-
- populateIndirectAccessRule(srcRange, serviceIp, outGroups);
- populateDirectAccessRule(srcRange, dstRange);
- populateInServiceRule(inPorts, outGroups);
- }
-
- /**
* Removes basic rules related to a given flow information.
*
* @param host host to be removed
@@ -263,13 +230,46 @@
if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
processFlowRule(false, flowRule);
}
-
}
// TODO uninstall same network access rule in access table if no vm exists in the network
}
/**
+ * Populates service dependency rules.
+ *
+ * @param tService tenant cord service
+ * @param pService provider cord service
+ */
+ public void populateServiceDependencyRules(CordService tService, CordService pService) {
+ checkNotNull(tService);
+ checkNotNull(pService);
+
+ Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
+ Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
+ Ip4Address serviceIp = pService.serviceIp().getIp4Address();
+
+ Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
+ Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
+
+ for (Device device : deviceService.getAvailableDevices(SWITCH)) {
+ GroupId groupId = createServiceGroup(device.id(), pService);
+ outGroups.put(device.id(), groupId);
+
+ Set<PortNumber> vms = tService.hosts().keySet()
+ .stream()
+ .filter(host -> host.location().deviceId().equals(device.id()))
+ .map(host -> host.location().port())
+ .collect(Collectors.toSet());
+ inPorts.put(device.id(), vms);
+ }
+
+ populateIndirectAccessRule(srcRange, serviceIp, outGroups);
+ populateDirectAccessRule(srcRange, dstRange);
+ populateInServiceRule(inPorts, outGroups);
+ }
+
+ /**
* Removes service dependency rules.
*
* @param tService tenant cord service
@@ -324,6 +324,58 @@
}
/**
+ * Updates group buckets for a given service to all devices.
+ *
+ * @param service cord service
+ */
+ public void updateServiceGroup(CordService service) {
+ checkNotNull(service);
+
+ GroupKey groupKey = getGroupKey(service.id());
+
+ for (Device device : deviceService.getAvailableDevices(SWITCH)) {
+ DeviceId deviceId = device.id();
+ if (!mastershipService.isLocalMaster(deviceId)) {
+ continue;
+ }
+
+ Group group = groupService.getGroup(deviceId, groupKey);
+ if (group == null) {
+ log.debug("No group exists for service {} in {}", service.id(), deviceId);
+ continue;
+ }
+
+ List<GroupBucket> oldBuckets = group.buckets().buckets();
+ List<GroupBucket> newBuckets = getServiceGroupBuckets(
+ deviceId, service.segmentationId(), service.hosts()).buckets();
+
+ if (oldBuckets.equals(newBuckets)) {
+ continue;
+ }
+
+ List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
+ bucketsToRemove.removeAll(newBuckets);
+ if (!bucketsToRemove.isEmpty()) {
+ groupService.removeBucketsFromGroup(
+ deviceId,
+ groupKey,
+ new GroupBuckets(bucketsToRemove),
+ groupKey, appId);
+ }
+
+ List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
+ bucketsToAdd.removeAll(oldBuckets);
+ if (!bucketsToAdd.isEmpty()) {
+ groupService.addBucketsToGroup(
+ deviceId,
+ groupKey,
+ new GroupBuckets(bucketsToAdd),
+ groupKey, appId);
+ }
+ }
+ }
+
+ /**
* Creates a new group for a given service.
*
* @param deviceId device id to create a group