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 { ...@@ -103,7 +103,6 @@ public class CordVtn implements CordVtnService {
103 .register(NodeState.class); 103 .register(NodeState.class);
104 private static final String DEFAULT_BRIDGE = "br-int"; 104 private static final String DEFAULT_BRIDGE = "br-int";
105 private static final String VPORT_PREFIX = "tap"; 105 private static final String VPORT_PREFIX = "tap";
106 - private static final String GWPORT_PREFIX = "qr-";
107 private static final String DEFAULT_TUNNEL = "vxlan"; 106 private static final String DEFAULT_TUNNEL = "vxlan";
108 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() { 107 private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
109 { 108 {
...@@ -379,13 +378,14 @@ public class CordVtn implements CordVtnService { ...@@ -379,13 +378,14 @@ public class CordVtn implements CordVtnService {
379 * @param node cordvtn node 378 * @param node cordvtn node
380 */ 379 */
381 private void postInit(CordVtnNode node) { 380 private void postInit(CordVtnNode node) {
382 - log.info("Initializing {}", node.hostname());
383 disconnect(node); 381 disconnect(node);
384 382
385 ruleInstaller.init(node.intBrId(), getTunnelPort(node.intBrId())); 383 ruleInstaller.init(node.intBrId(), getTunnelPort(node.intBrId()));
386 hostService.getConnectedHosts(node.intBrId()) 384 hostService.getConnectedHosts(node.intBrId())
387 .stream() 385 .stream()
388 .forEach(vmHandler::connected); 386 .forEach(vmHandler::connected);
387 +
388 + log.info("Finished initializing {}", node.hostname());
389 } 389 }
390 390
391 /** 391 /**
...@@ -646,13 +646,16 @@ public class CordVtn implements CordVtnService { ...@@ -646,13 +646,16 @@ public class CordVtn implements CordVtnService {
646 private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) { 646 private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
647 checkNotNull(vNet); 647 checkNotNull(vNet);
648 648
649 - return openstackService.ports(vNet.id()).stream() 649 + Set<Host> hosts = openstackService.ports(vNet.id()).stream()
650 .filter(port -> port.deviceOwner().contains("compute")) 650 .filter(port -> port.deviceOwner().contains("compute"))
651 .map(port -> hostService.getHostsByMac(port.macAddress()) 651 .map(port -> hostService.getHostsByMac(port.macAddress())
652 .stream() 652 .stream()
653 .findFirst() 653 .findFirst()
654 .orElse(null)) 654 .orElse(null))
655 .collect(Collectors.toSet()); 655 .collect(Collectors.toSet());
656 +
657 + hosts.remove(null);
658 + return hosts;
656 } 659 }
657 660
658 /** 661 /**
...@@ -687,16 +690,15 @@ public class CordVtn implements CordVtnService { ...@@ -687,16 +690,15 @@ public class CordVtn implements CordVtnService {
687 } 690 }
688 691
689 /** 692 /**
690 - * Returns if the host is gateway interface. 693 + * Returns if the host is VM or not.
691 - * This codes should be removed after adding proxy arp for the gateway.
692 * 694 *
693 * @param host host 695 * @param host host
694 - * @return true if the host is gateway 696 + * @return true if the host is a VM.
695 */ 697 */
696 - private boolean isGateway(Host host) { 698 + private boolean isVm(Host host) {
697 Port port = deviceService.getPort(host.location().deviceId(), 699 Port port = deviceService.getPort(host.location().deviceId(),
698 host.location().port()); 700 host.location().port());
699 - return port.annotations().value("portName").contains(GWPORT_PREFIX); 701 + return port.annotations().value("portName").contains(VPORT_PREFIX);
700 } 702 }
701 703
702 /** 704 /**
...@@ -892,8 +894,8 @@ public class CordVtn implements CordVtnService { ...@@ -892,8 +894,8 @@ public class CordVtn implements CordVtnService {
892 894
893 @Override 895 @Override
894 public void connected(Host host) { 896 public void connected(Host host) {
895 - // TODO remove check gateway here after applying network config host provider 897 + // TODO remove check VM here after applying network config host provider
896 - if (isGateway(host)) { 898 + if (!isVm(host)) {
897 return; 899 return;
898 } 900 }
899 901
...@@ -924,7 +926,11 @@ public class CordVtn implements CordVtnService { ...@@ -924,7 +926,11 @@ public class CordVtn implements CordVtnService {
924 checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(), 926 checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
925 vNet); 927 vNet);
926 928
927 - // TODO add new VM to related service group if exists 929 + CordService service = getCordService(vNet);
930 + // TODO check if the service needs an update on its group buckets after done CORD-433
931 + if (service != null) {
932 + ruleInstaller.updateServiceGroup(service);
933 + }
928 } 934 }
929 935
930 @Override 936 @Override
...@@ -943,7 +949,12 @@ public class CordVtn implements CordVtnService { ...@@ -943,7 +949,12 @@ public class CordVtn implements CordVtnService {
943 log.info("VM {} is vanished", host.id()); 949 log.info("VM {} is vanished", host.id());
944 ruleInstaller.removeBasicConnectionRules(host); 950 ruleInstaller.removeBasicConnectionRules(host);
945 951
946 - // TODO remove the VM from related service group if exists 952 + CordService service = getCordService(vNet);
953 + // TODO check if the service needs an update on its group buckets after done CORD-433
954 + if (service != null) {
955 + ruleInstaller.updateServiceGroup(service);
956 + }
957 +
947 hostNetMap.remove(host.id()); 958 hostNetMap.remove(host.id());
948 } 959 }
949 } 960 }
......
...@@ -70,6 +70,7 @@ import org.onosproject.openstackswitching.OpenstackNetwork; ...@@ -70,6 +70,7 @@ import org.onosproject.openstackswitching.OpenstackNetwork;
70 import org.onosproject.openstackswitching.OpenstackSubnet; 70 import org.onosproject.openstackswitching.OpenstackSubnet;
71 import org.slf4j.Logger; 71 import org.slf4j.Logger;
72 72
73 +import java.util.ArrayList;
73 import java.util.List; 74 import java.util.List;
74 import java.util.Map; 75 import java.util.Map;
75 import java.util.NoSuchElementException; 76 import java.util.NoSuchElementException;
...@@ -188,40 +189,6 @@ public class CordVtnRuleInstaller { ...@@ -188,40 +189,6 @@ public class CordVtnRuleInstaller {
188 } 189 }
189 190
190 /** 191 /**
191 - * Populates service dependency rules.
192 - *
193 - * @param tService tenant cord service
194 - * @param pService provider cord service
195 - */
196 - public void populateServiceDependencyRules(CordService tService, CordService pService) {
197 - checkNotNull(tService);
198 - checkNotNull(pService);
199 -
200 - Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
201 - Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
202 - Ip4Address serviceIp = pService.serviceIp().getIp4Address();
203 -
204 - Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
205 - Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
206 -
207 - for (Device device : deviceService.getAvailableDevices(SWITCH)) {
208 - GroupId groupId = createServiceGroup(device.id(), pService);
209 - outGroups.put(device.id(), groupId);
210 -
211 - Set<PortNumber> vms = tService.hosts().keySet()
212 - .stream()
213 - .filter(host -> host.location().deviceId().equals(device.id()))
214 - .map(host -> host.location().port())
215 - .collect(Collectors.toSet());
216 - inPorts.put(device.id(), vms);
217 - }
218 -
219 - populateIndirectAccessRule(srcRange, serviceIp, outGroups);
220 - populateDirectAccessRule(srcRange, dstRange);
221 - populateInServiceRule(inPorts, outGroups);
222 - }
223 -
224 - /**
225 * Removes basic rules related to a given flow information. 192 * Removes basic rules related to a given flow information.
226 * 193 *
227 * @param host host to be removed 194 * @param host host to be removed
...@@ -263,13 +230,46 @@ public class CordVtnRuleInstaller { ...@@ -263,13 +230,46 @@ public class CordVtnRuleInstaller {
263 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) { 230 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
264 processFlowRule(false, flowRule); 231 processFlowRule(false, flowRule);
265 } 232 }
266 -
267 } 233 }
268 234
269 // TODO uninstall same network access rule in access table if no vm exists in the network 235 // TODO uninstall same network access rule in access table if no vm exists in the network
270 } 236 }
271 237
272 /** 238 /**
239 + * Populates service dependency rules.
240 + *
241 + * @param tService tenant cord service
242 + * @param pService provider cord service
243 + */
244 + public void populateServiceDependencyRules(CordService tService, CordService pService) {
245 + checkNotNull(tService);
246 + checkNotNull(pService);
247 +
248 + Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
249 + Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
250 + Ip4Address serviceIp = pService.serviceIp().getIp4Address();
251 +
252 + Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
253 + Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
254 +
255 + for (Device device : deviceService.getAvailableDevices(SWITCH)) {
256 + GroupId groupId = createServiceGroup(device.id(), pService);
257 + outGroups.put(device.id(), groupId);
258 +
259 + Set<PortNumber> vms = tService.hosts().keySet()
260 + .stream()
261 + .filter(host -> host.location().deviceId().equals(device.id()))
262 + .map(host -> host.location().port())
263 + .collect(Collectors.toSet());
264 + inPorts.put(device.id(), vms);
265 + }
266 +
267 + populateIndirectAccessRule(srcRange, serviceIp, outGroups);
268 + populateDirectAccessRule(srcRange, dstRange);
269 + populateInServiceRule(inPorts, outGroups);
270 + }
271 +
272 + /**
273 * Removes service dependency rules. 273 * Removes service dependency rules.
274 * 274 *
275 * @param tService tenant cord service 275 * @param tService tenant cord service
...@@ -324,6 +324,58 @@ public class CordVtnRuleInstaller { ...@@ -324,6 +324,58 @@ public class CordVtnRuleInstaller {
324 } 324 }
325 325
326 /** 326 /**
327 + * Updates group buckets for a given service to all devices.
328 + *
329 + * @param service cord service
330 + */
331 + public void updateServiceGroup(CordService service) {
332 + checkNotNull(service);
333 +
334 + GroupKey groupKey = getGroupKey(service.id());
335 +
336 + for (Device device : deviceService.getAvailableDevices(SWITCH)) {
337 + DeviceId deviceId = device.id();
338 + if (!mastershipService.isLocalMaster(deviceId)) {
339 + continue;
340 + }
341 +
342 + Group group = groupService.getGroup(deviceId, groupKey);
343 + if (group == null) {
344 + log.debug("No group exists for service {} in {}", service.id(), deviceId);
345 + continue;
346 + }
347 +
348 + List<GroupBucket> oldBuckets = group.buckets().buckets();
349 + List<GroupBucket> newBuckets = getServiceGroupBuckets(
350 + deviceId, service.segmentationId(), service.hosts()).buckets();
351 +
352 + if (oldBuckets.equals(newBuckets)) {
353 + continue;
354 + }
355 +
356 + List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
357 + bucketsToRemove.removeAll(newBuckets);
358 + if (!bucketsToRemove.isEmpty()) {
359 + groupService.removeBucketsFromGroup(
360 + deviceId,
361 + groupKey,
362 + new GroupBuckets(bucketsToRemove),
363 + groupKey, appId);
364 + }
365 +
366 + List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
367 + bucketsToAdd.removeAll(oldBuckets);
368 + if (!bucketsToAdd.isEmpty()) {
369 + groupService.addBucketsToGroup(
370 + deviceId,
371 + groupKey,
372 + new GroupBuckets(bucketsToAdd),
373 + groupKey, appId);
374 + }
375 + }
376 + }
377 +
378 + /**
327 * Creates a new group for a given service. 379 * Creates a new group for a given service.
328 * 380 *
329 * @param deviceId device id to create a group 381 * @param deviceId device id to create a group
......