Hyunsun Moon
Committed by Gerrit Code Review

CORD-506 Apply existing service dependency when VM is detected

Change-Id: Ib0872c823347bfb6091d6c5f872657f10b7b1083
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 category="Traffic Steering" url="http://onosproject.org" title="CORD Virtual Tenant Network" 18 category="Traffic Steering" url="http://onosproject.org" title="CORD Virtual Tenant Network"
19 featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features" 19 featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
20 features="${project.artifactId}" 20 features="${project.artifactId}"
21 - apps="org.onosproject.ovsdb-base,org.onosproject.dhcp"> 21 + apps="org.onosproject.ovsdb-base,org.onosproject.dhcp,org.onosproject.xosclient">
22 <description>${project.description}</description> 22 <description>${project.description}</description>
23 <artifact>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</artifact> 23 <artifact>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</artifact>
24 </app> 24 </app>
......
...@@ -103,6 +103,11 @@ ...@@ -103,6 +103,11 @@
103 <version>${project.version}</version> 103 <version>${project.version}</version>
104 </dependency> 104 </dependency>
105 <dependency> 105 <dependency>
106 + <groupId>org.onosproject</groupId>
107 + <artifactId>onos-app-xos-client</artifactId>
108 + <version>${project.version}</version>
109 + </dependency>
110 + <dependency>
106 <groupId>com.jcraft</groupId> 111 <groupId>com.jcraft</groupId>
107 <artifactId>jsch</artifactId> 112 <artifactId>jsch</artifactId>
108 <version>0.1.53</version> 113 <version>0.1.53</version>
......
...@@ -43,6 +43,7 @@ public final class CordService { ...@@ -43,6 +43,7 @@ public final class CordService {
43 private final IpAddress serviceIp; 43 private final IpAddress serviceIp;
44 private final Map<Host, IpAddress> hosts; 44 private final Map<Host, IpAddress> hosts;
45 private final Set<CordServiceId> tenantServices; 45 private final Set<CordServiceId> tenantServices;
46 + private final Set<CordServiceId> providerServices;
46 47
47 /** 48 /**
48 * Default constructor. 49 * Default constructor.
...@@ -51,9 +52,11 @@ public final class CordService { ...@@ -51,9 +52,11 @@ public final class CordService {
51 * @param osSubnet OpenStack subnet 52 * @param osSubnet OpenStack subnet
52 * @param hosts host and tunnel ip map 53 * @param hosts host and tunnel ip map
53 * @param tenantServices list of tenant service ids 54 * @param tenantServices list of tenant service ids
55 + * @param providerServices list of provider service ids
54 */ 56 */
55 public CordService(Network osNet, Subnet osSubnet, 57 public CordService(Network osNet, Subnet osSubnet,
56 - Map<Host, IpAddress> hosts, Set<CordServiceId> tenantServices) { 58 + Map<Host, IpAddress> hosts, Set<CordServiceId> tenantServices,
59 + Set<CordServiceId> providerServices) {
57 this.id = CordServiceId.of(osNet.getId()); 60 this.id = CordServiceId.of(osNet.getId());
58 this.segmentationId = Long.parseLong(osNet.getProviderSegID()); 61 this.segmentationId = Long.parseLong(osNet.getProviderSegID());
59 this.serviceType = getServiceType(osNet.getName()); 62 this.serviceType = getServiceType(osNet.getName());
...@@ -61,6 +64,7 @@ public final class CordService { ...@@ -61,6 +64,7 @@ public final class CordService {
61 this.serviceIp = IpAddress.valueOf(osSubnet.getGateway()); 64 this.serviceIp = IpAddress.valueOf(osSubnet.getGateway());
62 this.hosts = hosts; 65 this.hosts = hosts;
63 this.tenantServices = tenantServices; 66 this.tenantServices = tenantServices;
67 + this.providerServices = providerServices;
64 } 68 }
65 69
66 /** 70 /**
...@@ -126,6 +130,15 @@ public final class CordService { ...@@ -126,6 +130,15 @@ public final class CordService {
126 return tenantServices; 130 return tenantServices;
127 } 131 }
128 132
133 + /**
134 + * Returns provider service IDs.
135 + *
136 + * @return list of provider service id
137 + */
138 + public Set<CordServiceId> providerServices() {
139 + return providerServices;
140 + }
141 +
129 @Override 142 @Override
130 public int hashCode() { 143 public int hashCode() {
131 return Objects.hash(id); 144 return Objects.hash(id);
...@@ -152,6 +165,7 @@ public final class CordService { ...@@ -152,6 +165,7 @@ public final class CordService {
152 .add("serviceIpRange", serviceIpRange) 165 .add("serviceIpRange", serviceIpRange)
153 .add("serviceIp", serviceIp) 166 .add("serviceIp", serviceIp)
154 .add("tenantServices", tenantServices) 167 .add("tenantServices", tenantServices)
168 + .add("providerServices", providerServices)
155 .toString(); 169 .toString();
156 } 170 }
157 171
...@@ -162,7 +176,7 @@ public final class CordService { ...@@ -162,7 +176,7 @@ public final class CordService {
162 * @param netName network name 176 * @param netName network name
163 * @return network type, or PRIVATE if it doesn't match any type 177 * @return network type, or PRIVATE if it doesn't match any type
164 */ 178 */
165 - private ServiceType getServiceType(String netName) { 179 + public static ServiceType getServiceType(String netName) {
166 checkNotNull(netName); 180 checkNotNull(netName);
167 181
168 String name = netName.toUpperCase(); 182 String name = netName.toUpperCase();
......
...@@ -25,6 +25,7 @@ import org.onlab.packet.TpPort; ...@@ -25,6 +25,7 @@ import org.onlab.packet.TpPort;
25 import org.onosproject.core.ApplicationId; 25 import org.onosproject.core.ApplicationId;
26 import org.onosproject.net.DeviceId; 26 import org.onosproject.net.DeviceId;
27 import org.onosproject.net.config.Config; 27 import org.onosproject.net.config.Config;
28 +import org.onosproject.xosclient.api.XosAccess;
28 import org.slf4j.Logger; 29 import org.slf4j.Logger;
29 30
30 import java.util.Map; 31 import java.util.Map;
...@@ -59,10 +60,12 @@ public class CordVtnConfig extends Config<ApplicationId> { ...@@ -59,10 +60,12 @@ public class CordVtnConfig extends Config<ApplicationId> {
59 public static final String SSH_KEY_FILE = "sshKeyFile"; 60 public static final String SSH_KEY_FILE = "sshKeyFile";
60 61
61 public static final String OPENSTACK = "openstack"; 62 public static final String OPENSTACK = "openstack";
62 - public static final String OPENSTACK_ENDPOINT = "endpoint"; 63 + public static final String XOS = "xos";
63 - public static final String OPENSTACK_TENANT = "tenant"; 64 +
64 - public static final String OPENSTACK_USER = "user"; 65 + public static final String ENDPOINT = "endpoint";
65 - public static final String OPENSTACK_PASSWORD = "password"; 66 + public static final String TENANT = "tenant";
67 + public static final String USER = "user";
68 + public static final String PASSWORD = "password";
66 69
67 /** 70 /**
68 * Returns the set of nodes read from network config. 71 * Returns the set of nodes read from network config.
...@@ -183,6 +186,28 @@ public class CordVtnConfig extends Config<ApplicationId> { ...@@ -183,6 +186,28 @@ public class CordVtnConfig extends Config<ApplicationId> {
183 } 186 }
184 187
185 /** 188 /**
189 + * Returns XOS access information.
190 + *
191 + * @return XOS access, or null
192 + */
193 + public XosAccess xosAccess() {
194 + JsonNode jsonNode = object.get(XOS);
195 + if (jsonNode == null) {
196 + log.error("Failed to get XOS configurations");
197 + return null;
198 + }
199 +
200 + try {
201 + return new XosAccess(getConfig(jsonNode, ENDPOINT),
202 + getConfig(jsonNode, USER),
203 + getConfig(jsonNode, PASSWORD));
204 + } catch (NullPointerException e) {
205 + log.error("Failed to get XOS access");
206 + return null;
207 + }
208 + }
209 +
210 + /**
186 * Returns OpenStack API access information. 211 * Returns OpenStack API access information.
187 * 212 *
188 * @return openstack config 213 * @return openstack config
...@@ -196,10 +221,10 @@ public class CordVtnConfig extends Config<ApplicationId> { ...@@ -196,10 +221,10 @@ public class CordVtnConfig extends Config<ApplicationId> {
196 221
197 try { 222 try {
198 return new OpenStackConfig( 223 return new OpenStackConfig(
199 - jsonNode.path(OPENSTACK_ENDPOINT).asText(), 224 + jsonNode.path(ENDPOINT).asText(),
200 - jsonNode.path(OPENSTACK_TENANT).asText(), 225 + jsonNode.path(TENANT).asText(),
201 - jsonNode.path(OPENSTACK_USER).asText(), 226 + jsonNode.path(USER).asText(),
202 - jsonNode.path(OPENSTACK_PASSWORD).asText()); 227 + jsonNode.path(PASSWORD).asText());
203 } catch (IllegalArgumentException | NullPointerException e) { 228 } catch (IllegalArgumentException | NullPointerException e) {
204 log.error("Failed to get OpenStack configurations"); 229 log.error("Failed to get OpenStack configurations");
205 return null; 230 return null;
......
...@@ -30,6 +30,7 @@ import org.onlab.packet.IpAddress; ...@@ -30,6 +30,7 @@ import org.onlab.packet.IpAddress;
30 import org.onlab.packet.MacAddress; 30 import org.onlab.packet.MacAddress;
31 import org.onlab.packet.VlanId; 31 import org.onlab.packet.VlanId;
32 import org.onosproject.cordvtn.api.CordService; 32 import org.onosproject.cordvtn.api.CordService;
33 +import org.onosproject.cordvtn.api.CordService.ServiceType;
33 import org.onosproject.cordvtn.api.CordServiceId; 34 import org.onosproject.cordvtn.api.CordServiceId;
34 import org.onosproject.cordvtn.api.CordVtnConfig; 35 import org.onosproject.cordvtn.api.CordVtnConfig;
35 import org.onosproject.cordvtn.api.CordVtnNode; 36 import org.onosproject.cordvtn.api.CordVtnNode;
...@@ -66,6 +67,8 @@ import org.onosproject.net.packet.PacketProcessor; ...@@ -66,6 +67,8 @@ import org.onosproject.net.packet.PacketProcessor;
66 import org.onosproject.net.packet.PacketService; 67 import org.onosproject.net.packet.PacketService;
67 import org.onosproject.net.provider.AbstractProvider; 68 import org.onosproject.net.provider.AbstractProvider;
68 import org.onosproject.net.provider.ProviderId; 69 import org.onosproject.net.provider.ProviderId;
70 +import org.onosproject.xosclient.api.XosAccess;
71 +import org.onosproject.xosclient.api.XosClientService;
69 import org.openstack4j.api.OSClient; 72 import org.openstack4j.api.OSClient;
70 import org.openstack4j.api.exceptions.AuthenticationException; 73 import org.openstack4j.api.exceptions.AuthenticationException;
71 import org.openstack4j.model.identity.Access; 74 import org.openstack4j.model.identity.Access;
...@@ -85,6 +88,7 @@ import java.util.stream.StreamSupport; ...@@ -85,6 +88,7 @@ import java.util.stream.StreamSupport;
85 import static com.google.common.base.Preconditions.checkNotNull; 88 import static com.google.common.base.Preconditions.checkNotNull;
86 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; 89 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
87 import static org.onlab.util.Tools.groupedThreads; 90 import static org.onlab.util.Tools.groupedThreads;
91 +import static org.onosproject.cordvtn.api.CordService.getServiceType;
88 import static org.slf4j.LoggerFactory.getLogger; 92 import static org.slf4j.LoggerFactory.getLogger;
89 93
90 /** 94 /**
...@@ -130,6 +134,9 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -130,6 +134,9 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected DhcpService dhcpService; 135 protected DhcpService dhcpService;
132 136
137 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 + protected XosClientService xosClient;
139 +
133 private final ConfigFactory configFactory = 140 private final ConfigFactory configFactory =
134 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") { 141 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
135 @Override 142 @Override
...@@ -412,23 +419,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -412,23 +419,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
412 return null; 419 return null;
413 } 420 }
414 421
415 - // here it assumes all cord service networks has only one subnet 422 + return getCordService(osNet);
416 - Subnet osSubnet = osNet.getNeutronSubnets().stream()
417 - .findFirst()
418 - .orElse(null);
419 - if (osSubnet == null) {
420 - log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
421 - return null;
422 - }
423 -
424 - Set<CordServiceId> tServices = Sets.newHashSet();
425 - // TODO get tenant services from XOS
426 -
427 - Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
428 - .stream()
429 - .collect(Collectors.toMap(host -> host, this::getTunnelIp));
430 -
431 - return new CordService(osNet, osSubnet, hosts, tServices);
432 } 423 }
433 424
434 /** 425 /**
...@@ -450,14 +441,28 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -450,14 +441,28 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
450 return null; 441 return null;
451 } 442 }
452 443
453 - Set<CordServiceId> tServices = Sets.newHashSet();
454 - // TODO get tenant services from XOS
455 -
456 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet) 444 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
457 .stream() 445 .stream()
458 .collect(Collectors.toMap(host -> host, this::getTunnelIp)); 446 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
459 447
460 - return new CordService(osNet, osSubnet, hosts, tServices); 448 + ServiceType serviceType = getServiceType(osNet.getName());
449 + // allows working without XOS for now
450 + Set<CordServiceId> tServices = Sets.newHashSet();
451 + Set<CordServiceId> pServices = Sets.newHashSet();
452 +
453 + if (xosClient.access() != null && serviceType != ServiceType.MANAGEMENT) {
454 + tServices = xosClient.vtnServiceApi().getTenantServices(serviceId.id())
455 + .stream()
456 + .map(CordServiceId::of)
457 + .collect(Collectors.toSet());
458 +
459 + pServices = xosClient.vtnServiceApi().getProviderServices(serviceId.id())
460 + .stream()
461 + .map(CordServiceId::of)
462 + .collect(Collectors.toSet());
463 + }
464 +
465 + return new CordService(osNet, osSubnet, hosts, tServices, pServices);
461 } 466 }
462 467
463 /** 468 /**
...@@ -576,6 +581,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -576,6 +581,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
576 581
577 CordService service = getCordService(osNet); 582 CordService service = getCordService(osNet);
578 if (service == null) { 583 if (service == null) {
584 + log.warn("Failed to get CordService for {}", osNet.getName());
579 return; 585 return;
580 } 586 }
581 587
...@@ -587,7 +593,12 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -587,7 +593,12 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
587 arpProxy.addGateway(service.serviceIp(), privateGatewayMac); 593 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
588 case PUBLIC: 594 case PUBLIC:
589 default: 595 default:
590 - // TODO check if the service needs an update on its group buckets after done CORD-433 596 + // TODO get bidirectional information from XOS once XOS supports
597 + service.tenantServices().stream().forEach(
598 + tServiceId -> createServiceDependency(tServiceId, service.id(), true));
599 + service.providerServices().stream().forEach(
600 + pServiceId -> createServiceDependency(service.id(), pServiceId, true));
601 +
591 ruleInstaller.updateServiceGroup(service); 602 ruleInstaller.updateServiceGroup(service);
592 // sends gratuitous ARP here for the case of adding existing VMs 603 // sends gratuitous ARP here for the case of adding existing VMs
593 // when ONOS or cordvtn app is restarted 604 // when ONOS or cordvtn app is restarted
...@@ -648,8 +659,9 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -648,8 +659,9 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
648 } 659 }
649 case PUBLIC: 660 case PUBLIC:
650 default: 661 default:
651 - // TODO check if the service needs an update on its group buckets after done CORD-433 662 + if (!service.tenantServices().isEmpty()) {
652 - ruleInstaller.updateServiceGroup(service); 663 + ruleInstaller.updateServiceGroup(service);
664 + }
653 break; 665 break;
654 } 666 }
655 } 667 }
...@@ -717,6 +729,8 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -717,6 +729,8 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
717 * @param newMac mac address to update 729 * @param newMac mac address to update
718 */ 730 */
719 private void setPrivateGatewayMac(MacAddress newMac) { 731 private void setPrivateGatewayMac(MacAddress newMac) {
732 + checkNotNull(osAccess, "OpenStack access is not set");
733 +
720 if (newMac == null || newMac.equals(privateGatewayMac)) { 734 if (newMac == null || newMac.equals(privateGatewayMac)) {
721 // no updates, do nothing 735 // no updates, do nothing
722 return; 736 return;
...@@ -725,13 +739,11 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -725,13 +739,11 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
725 privateGatewayMac = newMac; 739 privateGatewayMac = newMac;
726 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString()); 740 log.debug("Set service gateway MAC address to {}", privateGatewayMac.toString());
727 741
728 - // TODO get existing service list from XOS and replace the loop below 742 + OSClient osClient = OSFactory.clientFromAccess(osAccess);
729 - Set<String> vNets = Sets.newHashSet(); 743 + List<Network> vNets = Lists.newArrayList(osClient.networking().network().list().iterator());
730 - hostService.getHosts().forEach(host -> vNets.add(host.annotations().value(SERVICE_ID)));
731 - vNets.remove(null);
732 744
733 vNets.stream().forEach(vNet -> { 745 vNets.stream().forEach(vNet -> {
734 - CordService service = getCordService(CordServiceId.of(vNet)); 746 + CordService service = getCordService(vNet);
735 if (service != null) { 747 if (service != null) {
736 arpProxy.addGateway(service.serviceIp(), privateGatewayMac); 748 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
737 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet()); 749 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), service.hosts().keySet());
...@@ -763,6 +775,8 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -763,6 +775,8 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
763 * @param osConfig openstack config 775 * @param osConfig openstack config
764 */ 776 */
765 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) { 777 private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
778 + checkNotNull(osConfig, "OpenStack access is not configured");
779 +
766 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}", 780 log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
767 osConfig.endpoint(), 781 osConfig.endpoint(),
768 osConfig.tenant(), 782 osConfig.tenant(),
...@@ -781,6 +795,22 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -781,6 +795,22 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
781 } 795 }
782 796
783 /** 797 /**
798 + * Sets XOS access information.
799 + *
800 + * @param xosAccess xos access
801 + */
802 + private void setXosAccess(XosAccess xosAccess) {
803 + checkNotNull(xosAccess, "XOS access is not configured");
804 +
805 + log.debug("Set XOS access with Endpoint: {} User: {} Passwd: {}",
806 + xosAccess.endpoint(),
807 + xosAccess.username(),
808 + xosAccess.password());
809 +
810 + xosClient.setAccess(xosAccess);
811 + }
812 +
813 + /**
784 * Updates configurations. 814 * Updates configurations.
785 */ 815 */
786 private void readConfiguration() { 816 private void readConfiguration() {
...@@ -790,6 +820,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -790,6 +820,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
790 return; 820 return;
791 } 821 }
792 822
823 + setXosAccess(config.xosAccess());
793 setOpenstackAccess(config.openstackConfig()); 824 setOpenstackAccess(config.openstackConfig());
794 setPrivateGatewayMac(config.privateGatewayMac()); 825 setPrivateGatewayMac(config.privateGatewayMac());
795 setPublicGatewayMac(config.publicGateways()); 826 setPublicGatewayMac(config.publicGateways());
......
...@@ -282,12 +282,12 @@ public class CordVtnRuleInstaller { ...@@ -282,12 +282,12 @@ public class CordVtnRuleInstaller {
282 GroupId groupId = createServiceGroup(deviceId, pService); 282 GroupId groupId = createServiceGroup(deviceId, pService);
283 outGroups.put(deviceId, groupId); 283 outGroups.put(deviceId, groupId);
284 284
285 - Set<PortNumber> vms = tService.hosts().keySet() 285 + Set<PortNumber> tServiceVms = tService.hosts().keySet()
286 .stream() 286 .stream()
287 .filter(host -> host.location().deviceId().equals(deviceId)) 287 .filter(host -> host.location().deviceId().equals(deviceId))
288 .map(host -> host.location().port()) 288 .map(host -> host.location().port())
289 .collect(Collectors.toSet()); 289 .collect(Collectors.toSet());
290 - inPorts.put(deviceId, vms); 290 + inPorts.put(deviceId, tServiceVms);
291 }); 291 });
292 292
293 populateIndirectAccessRule(srcRange, serviceIp, outGroups); 293 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
......