Hyunsun Moon

CORD-417 Update group buckets when a VM is created or terminated

Change-Id: Ib1aba443708a13499f21c08b39b777c876595fac
......@@ -103,7 +103,6 @@ public class CordVtn implements CordVtnService {
.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 @@ public class CordVtn implements CordVtnService {
* @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 @@ public class CordVtn implements CordVtnService {
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 @@ public class CordVtn implements CordVtnService {
}
/**
* 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 @@ public class CordVtn implements CordVtnService {
@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 @@ public class CordVtn implements CordVtnService {
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 @@ public class CordVtn implements CordVtnService {
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());
}
}
......
......@@ -70,6 +70,7 @@ import org.onosproject.openstackswitching.OpenstackNetwork;
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 @@ public class CordVtnRuleInstaller {
}
/**
* 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 @@ public class CordVtnRuleInstaller {
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 @@ public class CordVtnRuleInstaller {
}
/**
* 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
......