Separated ARP proxy as an independent component and some renaming
- Renamed CordVtnService to DependencyService
- Renamed CordVtnInstanceManager to InstanceManager and added
InstanceService as an interface of the manager implementation
- Renamed package name impl.service to impl.handler
- Added Constants class
Change-Id: I249708c008d5105957aa1d1a796f0ca32025e75c
diff --git a/src/main/java/org/opencord/cordvtn/api/Constants.java b/src/main/java/org/opencord/cordvtn/api/Constants.java
new file mode 100644
index 0000000..b4c7329
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/Constants.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api;
+
+/**
+ * Provides constants used in CORD VTN services.
+ */
+public final class Constants {
+
+ private Constants() {
+ }
+
+ public static final String CORDVTN_APP_ID = "org.opencord.vtn";
+
+ public static final String ERROR_XOS_ACCESS = "XOS access is not configured";
+ public static final String ERROR_OPENSTACK_ACCESS = "OpenStack access is not configured";
+ public static final String MSG_OK = "OK";
+ public static final String MSG_NO = "NO";
+
+ public static final String PORT_NAME = "portName";
+ public static final String DEFAULT_TUNNEL = "vxlan";
+ public static final String DEFAULT_BRIDGE = "br-int";
+ public static final String VPORT_PREFIX = "tap";
+}
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnService.java b/src/main/java/org/opencord/cordvtn/api/DependencyService.java
similarity index 76%
rename from src/main/java/org/opencord/cordvtn/api/CordVtnService.java
rename to src/main/java/org/opencord/cordvtn/api/DependencyService.java
index 16d26f7..48905da 100644
--- a/src/main/java/org/opencord/cordvtn/api/CordVtnService.java
+++ b/src/main/java/org/opencord/cordvtn/api/DependencyService.java
@@ -18,11 +18,9 @@
import org.onosproject.xosclient.api.VtnServiceId;
/**
- * Service for provisioning overlay virtual networks on compute nodes.
+ * Provides dependency services.
*/
-public interface CordVtnService {
-
- String CORDVTN_APP_ID = "org.opencord.vtn";
+public interface DependencyService {
/**
* Creates dependencies for a given tenant service.
@@ -31,8 +29,7 @@
* @param pServiceId id of the service which provide dependency
* @param isBidirectional true to enable bidirectional connectivity between two services
*/
- void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
- boolean isBidirectional);
+ void createDependency(VtnServiceId tServiceId, VtnServiceId pServiceId, boolean isBidirectional);
/**
* Removes all dependencies from a given tenant service.
@@ -40,5 +37,5 @@
* @param tServiceId id of the service which has a dependency
* @param pServiceId id of the service which provide dependency
*/
- void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId);
+ void removeDependency(VtnServiceId tServiceId, VtnServiceId pServiceId);
}
diff --git a/src/main/java/org/opencord/cordvtn/api/InstanceService.java b/src/main/java/org/opencord/cordvtn/api/InstanceService.java
new file mode 100644
index 0000000..a8e0f77
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/api/InstanceService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.api;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.HostId;
+import org.onosproject.net.host.HostDescription;
+
+/**
+ * Provides service instance addition or removal.
+ */
+public interface InstanceService {
+
+ /**
+ * Adds a service instance on a given connect point.
+ *
+ * @param connectPoint connect point of the instance
+ */
+ void addInstance(ConnectPoint connectPoint);
+
+ /**
+ * Removes a service instance from a given connect point.
+ *
+ * @param connectPoint connect point
+ */
+ void removeInstance(ConnectPoint connectPoint);
+
+ /**
+ * Adds a nested instance with given host ID and host description.
+ * Nested instance can be a container inside a virtual machine, for example.
+ * DHCP is not supported for the nested instance.
+ *
+ * @param hostId host id
+ * @param description host description
+ */
+ void addNestedInstance(HostId hostId, HostDescription description);
+
+ /**
+ * Removes nested instance with a given host ID.
+ *
+ * @param hostId host id
+ */
+ void removeNestedInstance(HostId hostId);
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java
index 29868b4..d714e3e 100644
--- a/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/AbstractInstanceHandler.java
@@ -37,8 +37,8 @@
import org.onosproject.xosclient.api.VtnServiceId;
import org.onosproject.xosclient.api.XosAccess;
import org.onosproject.xosclient.api.XosClientService;
+import org.opencord.cordvtn.api.Constants;
import org.opencord.cordvtn.api.CordVtnConfig;
-import org.opencord.cordvtn.api.CordVtnService;
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
import org.slf4j.Logger;
@@ -51,6 +51,10 @@
import java.util.stream.StreamSupport;
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.opencord.cordvtn.api.Constants.ERROR_OPENSTACK_ACCESS;
+import static org.opencord.cordvtn.api.Constants.ERROR_XOS_ACCESS;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -65,19 +69,16 @@
protected NetworkConfigRegistry configRegistry;
protected HostService hostService;
protected XosClientService xosClient;
- protected CordVtnPipeline pipeline;
- protected CordVtnNodeManager nodeManager;
protected ApplicationId appId;
- protected ExecutorService eventExecutor;
protected Optional<ServiceType> serviceType = Optional.empty();
protected NetworkConfigListener configListener = new InternalConfigListener();
protected HostListener hostListener = new InternalHostListener();
- private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
- private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
private XosAccess xosAccess = null;
private OpenStackAccess osAccess = null;
+ private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
+ groupedThreads(this.getClass().getSimpleName(), "event-handler"));
protected void activate() {
ServiceDirectory services = new DefaultServiceDirectory();
@@ -86,10 +87,8 @@
mastershipService = services.get(MastershipService.class);
hostService = services.get(HostService.class);
xosClient = services.get(XosClientService.class);
- pipeline = services.get(CordVtnPipeline.class);
- nodeManager = services.get(CordVtnNodeManager.class);
- appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
+ appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
hostService.addListener(hostListener);
configRegistry.addListener(configListener);
@@ -105,8 +104,8 @@
}
protected VtnService getVtnService(VtnServiceId serviceId) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
+ checkNotNull(osAccess, ERROR_OPENSTACK_ACCESS);
+ checkNotNull(xosAccess, ERROR_XOS_ACCESS);
// TODO remove openstack access when XOS provides all information
VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
@@ -118,8 +117,8 @@
}
protected VtnPort getVtnPort(Instance instance) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
+ checkNotNull(osAccess, ERROR_OPENSTACK_ACCESS);
+ checkNotNull(xosAccess, ERROR_XOS_ACCESS);
VtnPortId vtnPortId = instance.portId();
VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
index 6d29a7d..9e8d313 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
@@ -16,20 +16,27 @@
package org.opencord.cordvtn.impl;
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;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.Instance;
-import org.onosproject.core.ApplicationId;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
@@ -42,37 +49,41 @@
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.PRIVATE;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles ARP requests for virtual network service IPs.
*/
-public class CordVtnArpProxy {
+@Component(immediate = true)
+public class CordVtnArpProxy extends AbstractInstanceHandler {
protected final Logger log = getLogger(getClass());
- private final ApplicationId appId;
- private final PacketService packetService;
- private final HostService hostService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+ private final PacketProcessor packetProcessor = new InternalPacketProcessor();
private final Map<Ip4Address, MacAddress> gateways = Maps.newConcurrentMap();
- /**
- * Default constructor.
- *
- * @param appId application id
- * @param packetService packet service
- * @param hostService host service reference
- */
- public CordVtnArpProxy(ApplicationId appId, PacketService packetService, HostService hostService) {
- this.appId = appId;
- this.packetService = packetService;
- this.hostService = hostService;
+ private MacAddress privateGatewayMac = MacAddress.NONE;
+
+ @Activate
+ protected void activate() {
+ super.activate();
+ packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
+ requestPacket();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ packetService.removeProcessor(packetProcessor);
+ super.deactivate();
}
/**
* Requests ARP packet.
*/
- public void requestPacket() {
+ private void requestPacket() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.build();
@@ -86,7 +97,7 @@
/**
* Cancels ARP packet.
*/
- public void cancelPacket() {
+ private void cancelPacket() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.build();
@@ -103,7 +114,7 @@
* @param gatewayIp gateway ip address
* @param gatewayMac gateway mac address
*/
- public void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
+ private void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
checkNotNull(gatewayIp);
checkNotNull(gatewayMac);
gateways.put(gatewayIp.getIp4Address(), gatewayMac);
@@ -114,7 +125,7 @@
*
* @param gatewayIp gateway ip address
*/
- public void removeGateway(IpAddress gatewayIp) {
+ private void removeGateway(IpAddress gatewayIp) {
checkNotNull(gatewayIp);
gateways.remove(gatewayIp.getIp4Address());
}
@@ -128,7 +139,7 @@
* @param context packet context
* @param ethPacket ethernet packet
*/
- public void processArpPacket(PacketContext context, Ethernet ethPacket) {
+ private void processArpPacket(PacketContext context, Ethernet ethPacket) {
ARP arpPacket = (ARP) ethPacket.getPayload();
if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
return;
@@ -169,7 +180,7 @@
* @param gatewayIp gateway ip address to update MAC
* @param instances set of instances to send gratuitous ARP packet
*/
- public void sendGratuitousArpForGateway(IpAddress gatewayIp, Set<Instance> instances) {
+ private void sendGratuitousArp(IpAddress gatewayIp, Set<Instance> instances) {
MacAddress gatewayMac = gateways.get(gatewayIp.getIp4Address());
if (gatewayMac == null) {
log.debug("Gateway {} is not registered to ARP proxy", gatewayIp.toString());
@@ -241,4 +252,69 @@
return MacAddress.NONE;
}
}
+
+ private class InternalPacketProcessor implements PacketProcessor {
+
+ @Override
+ public void process(PacketContext context) {
+ if (context.isHandled()) {
+ return;
+ }
+ Ethernet ethPacket = context.inPacket().parsed();
+ if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
+ return;
+ }
+ processArpPacket(context, ethPacket);
+ }
+ }
+
+ @Override
+ public void instanceDetected(Instance instance) {
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ return;
+ }
+
+ if (service.networkType().equals(PRIVATE)) {
+ log.trace("Added IP:{} MAC:{}", service.serviceIp(), privateGatewayMac);
+ addGateway(service.serviceIp(), privateGatewayMac);
+ // send gratuitous ARP for the existing VMs when ONOS is restarted
+ sendGratuitousArp(service.serviceIp(), Sets.newHashSet(instance));
+ }
+ }
+
+ @Override
+ public void instanceRemoved(Instance instance) {
+ VtnService service = getVtnService(instance.serviceId());
+ if (service == null) {
+ return;
+ }
+
+ // remove this network gateway from proxy ARP if no instance presents
+ if (service.networkType().equals(PRIVATE) &&
+ getInstances(service.id()).isEmpty()) {
+ removeGateway(service.serviceIp());
+ }
+ }
+
+ @Override
+ protected void readConfiguration() {
+ CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
+ if (config == null) {
+ log.debug("No configuration found");
+ return;
+ }
+
+ privateGatewayMac = config.privateGatewayMac();
+ log.debug("Added private gateway MAC {}", privateGatewayMac);
+
+ config.publicGateways().entrySet().stream().forEach(entry -> {
+ addGateway(entry.getKey(), entry.getValue());
+ log.debug("Added public gateway IP {}, MAC {}",
+ entry.getKey(), entry.getValue());
+ });
+ // TODO send gratuitous arp in case the MAC is changed
+
+ super.readConfiguration();
+ }
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java
deleted file mode 100644
index bb5e067..0000000
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnInstanceManager.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.opencord.cordvtn.impl;
-
-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;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.opencord.cordvtn.api.CordVtnConfig;
-import org.opencord.cordvtn.api.CordVtnService;
-import org.opencord.cordvtn.api.Instance;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.dhcp.DhcpService;
-import org.onosproject.dhcp.IpAssignment;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.host.DefaultHostDescription;
-import org.onosproject.net.host.HostDescription;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostProvider;
-import org.onosproject.net.host.HostProviderRegistry;
-import org.onosproject.net.host.HostProviderService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.provider.AbstractProvider;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.xosclient.api.OpenStackAccess;
-import org.onosproject.xosclient.api.VtnPort;
-import org.onosproject.xosclient.api.VtnPortApi;
-import org.onosproject.xosclient.api.VtnService;
-import org.onosproject.xosclient.api.VtnServiceApi;
-import org.onosproject.xosclient.api.VtnServiceId;
-import org.onosproject.xosclient.api.XosAccess;
-import org.onosproject.xosclient.api.XosClientService;
-import org.slf4j.Logger;
-
-import java.util.Date;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
-import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.MANAGEMENT;
-import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.PRIVATE;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Adds or removes instances to network services.
- */
-@Component(immediate = true)
-@Service(value = CordVtnInstanceManager.class)
-public class CordVtnInstanceManager extends AbstractProvider implements HostProvider {
-
- protected final Logger log = getLogger(getClass());
-
- private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
- private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
- private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
- private static final int DHCP_INFINITE_LEASE = -1;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigRegistry configRegistry;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostProviderRegistry hostProviderRegistry;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PacketService packetService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DhcpService dhcpService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected XosClientService xosClient;
-
- private final ConfigFactory configFactory =
- new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
- @Override
- public CordVtnConfig createConfig() {
- return new CordVtnConfig();
- }
- };
-
- private final ExecutorService eventExecutor =
- newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-instance", "event-handler"));
- private final PacketProcessor packetProcessor = new InternalPacketProcessor();
- private final HostListener hostListener = new InternalHostListener();
- private final NetworkConfigListener configListener = new InternalConfigListener();
-
- private ApplicationId appId;
- private HostProviderService hostProvider;
- private CordVtnArpProxy arpProxy; // TODO make it a component service
- private MacAddress privateGatewayMac = MacAddress.NONE;
- private XosAccess xosAccess = null;
- private OpenStackAccess osAccess = null;
-
- /**
- * Creates an cordvtn host location provider.
- */
- public CordVtnInstanceManager() {
- super(new ProviderId("host", CordVtnService.CORDVTN_APP_ID));
- }
-
- @Activate
- protected void activate() {
- appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
-
- arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
- packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
- arpProxy.requestPacket();
-
- hostService.addListener(hostListener);
- hostProvider = hostProviderRegistry.register(this);
-
- configRegistry.registerConfigFactory(configFactory);
- configRegistry.addListener(configListener);
-
- log.info("Started");
- }
-
- @Deactivate
- protected void deactivate() {
- hostProviderRegistry.unregister(this);
- hostService.removeListener(hostListener);
-
- packetService.removeProcessor(packetProcessor);
-
- configRegistry.unregisterConfigFactory(configFactory);
- configRegistry.removeListener(configListener);
-
- eventExecutor.shutdown();
- log.info("Stopped");
- }
-
- @Override
- public void triggerProbe(Host host) {
- /*
- * Note: In CORD deployment, we assume that all hosts are configured.
- * Therefore no probe is required.
- */
- }
-
- /**
- * Adds a service instance at a given connect point.
- *
- * @param connectPoint connect point of the instance
- */
- public void addInstance(ConnectPoint connectPoint) {
- Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
- if (port == null) {
- log.debug("No port found from {}", connectPoint);
- return;
- }
-
- VtnPort vtnPort = getVtnPort(port.annotations().value("portName"));
- if (vtnPort == null) {
- return;
- }
-
- VtnService vtnService = getVtnService(vtnPort.serviceId());
- if (vtnService == null) {
- return;
- }
-
- // Added CREATE_TIME intentionally to trigger HOST_UPDATED event for the
- // existing instances.
- DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
- .set(Instance.SERVICE_TYPE, vtnService.serviceType().toString())
- .set(Instance.SERVICE_ID, vtnPort.serviceId().id())
- .set(Instance.PORT_ID, vtnPort.id().id())
- .set(Instance.CREATE_TIME, String.valueOf(System.currentTimeMillis()));
-
- HostDescription hostDesc = new DefaultHostDescription(
- vtnPort.mac(),
- VlanId.NONE,
- new HostLocation(connectPoint, System.currentTimeMillis()),
- Sets.newHashSet(vtnPort.ip()),
- annotations.build());
-
- HostId hostId = HostId.hostId(vtnPort.mac());
- hostProvider.hostDetected(hostId, hostDesc, false);
- }
-
- /**
- * Adds a service instance with given host ID and host description.
- *
- * @param hostId host id
- * @param description host description
- */
- public void addInstance(HostId hostId, HostDescription description) {
- hostProvider.hostDetected(hostId, description, false);
- }
-
- /**
- * Removes a service instance from a given connect point.
- *
- * @param connectPoint connect point
- */
- public void removeInstance(ConnectPoint connectPoint) {
- hostService.getConnectedHosts(connectPoint)
- .stream()
- .forEach(host -> hostProvider.hostVanished(host.id()));
- }
-
- /**
- * Removes service instance with given host ID.
- *
- * @param hostId host id
- */
- public void removeInstance(HostId hostId) {
- hostProvider.hostVanished(hostId);
- }
-
- private void instanceDetected(Instance instance) {
- VtnService service = getVtnService(instance.serviceId());
- if (service == null) {
- return;
- }
-
- if (service.networkType().equals(PRIVATE)) {
- arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
- arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance));
- }
- if (!instance.isNestedInstance()) {
- registerDhcpLease(instance, service);
- }
- }
-
- private void instanceRemoved(Instance instance) {
- VtnService service = getVtnService(instance.serviceId());
- if (service == null) {
- return;
- }
-
- if (service.networkType().equals(PRIVATE) && getInstances(service.id()).isEmpty()) {
- arpProxy.removeGateway(service.serviceIp());
- }
-
- if (!instance.isNestedInstance()) {
- dhcpService.removeStaticMapping(instance.mac());
- }
- }
-
- private void registerDhcpLease(Instance instance, VtnService service) {
- Ip4Address broadcast = Ip4Address.makeMaskedAddress(
- instance.ipAddress(),
- service.subnet().prefixLength());
-
- IpAssignment.Builder ipBuilder = IpAssignment.builder()
- .ipAddress(instance.ipAddress())
- .leasePeriod(DHCP_INFINITE_LEASE)
- .timestamp(new Date())
- .subnetMask(Ip4Address.makeMaskPrefix(service.subnet().prefixLength()))
- .broadcast(broadcast)
- .domainServer(DEFAULT_DNS)
- .assignmentStatus(Option_RangeNotEnforced);
-
- if (service.networkType() != MANAGEMENT) {
- ipBuilder = ipBuilder.routerAddress(service.serviceIp().getIp4Address());
- }
-
- log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress());
- dhcpService.setStaticMapping(instance.mac(), ipBuilder.build());
- }
-
- private VtnService getVtnService(VtnServiceId serviceId) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
- // TODO remove openstack access when XOS provides all information
- VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
- VtnService service = serviceApi.service(serviceId, osAccess);
- if (service == null) {
- log.warn("Failed to get VtnService for {}", serviceId);
- }
- return service;
- }
-
- private VtnPort getVtnPort(String portName) {
- checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
- checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
- // TODO remove openstack access when XOS provides all information
- VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
- VtnPort vtnPort = portApi.vtnPort(portName, osAccess);
- if (vtnPort == null) {
- log.warn("Failed to get port information of {}", portName);
- }
- return vtnPort;
- }
-
- private Set<Instance> getInstances(VtnServiceId serviceId) {
- return StreamSupport.stream(hostService.getHosts().spliterator(), false)
- .filter(host -> Objects.equals(
- serviceId.id(),
- host.annotations().value(Instance.SERVICE_ID)))
- .map(Instance::of)
- .collect(Collectors.toSet());
- }
-
- private void readConfiguration() {
- CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
- if (config == null) {
- log.debug("No configuration found");
- return;
- }
-
- log.info("Load CORD-VTN configurations");
-
- xosAccess = config.xosAccess();
- osAccess = config.openstackAccess();
- privateGatewayMac = config.privateGatewayMac();
-
- Map<IpAddress, MacAddress> publicGateways = config.publicGateways();
- publicGateways.entrySet()
- .stream()
- .forEach(entry -> {
- arpProxy.addGateway(entry.getKey(), entry.getValue());
- log.debug("Added public gateway IP {}, MAC {}",
- entry.getKey(), entry.getValue());
- });
- // TODO notice gateway MAC change to VMs holds this gateway IP
- }
-
- private class InternalHostListener implements HostListener {
-
- @Override
- public void event(HostEvent event) {
- Host host = event.subject();
- if (!mastershipService.isLocalMaster(host.location().deviceId())) {
- // do not allow to proceed without mastership
- return;
- }
-
- Instance instance = Instance.of(host);
- switch (event.type()) {
- case HOST_UPDATED:
- case HOST_ADDED:
- eventExecutor.execute(() -> instanceDetected(instance));
- break;
- case HOST_REMOVED:
- eventExecutor.execute(() -> instanceRemoved(instance));
- break;
- default:
- break;
- }
- }
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
-
- @Override
- public void process(PacketContext context) {
- if (context.isHandled()) {
- return;
- }
- Ethernet ethPacket = context.inPacket().parsed();
- if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
- return;
- }
- arpProxy.processArpPacket(context, ethPacket);
- }
- }
-
- private class InternalConfigListener implements NetworkConfigListener {
-
- @Override
- public void event(NetworkConfigEvent event) {
- if (!event.configClass().equals(CordVtnConfig.class)) {
- return;
- }
-
- switch (event.type()) {
- case CONFIG_ADDED:
- case CONFIG_UPDATED:
- readConfiguration();
- break;
- default:
- break;
- }
- }
- }
-}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
index c037c05..fbac581 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
@@ -33,7 +33,7 @@
import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.CordVtnNode;
import org.opencord.cordvtn.api.CordVtnNodeState;
-import org.opencord.cordvtn.api.CordVtnService;
+import org.opencord.cordvtn.api.InstanceService;
import org.opencord.cordvtn.api.NetworkAddress;
import org.opencord.cordvtn.api.SshAccessInfo;
import org.onosproject.core.ApplicationId;
@@ -85,9 +85,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
-import static org.opencord.cordvtn.impl.CordVtnPipeline.DEFAULT_TUNNEL;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
+import static org.opencord.cordvtn.api.Constants.*;
import static org.opencord.cordvtn.impl.RemoteIpCommandUtil.*;
import static org.slf4j.LoggerFactory.getLogger;
@@ -109,11 +109,6 @@
.register(SshAccessInfo.class)
.register(NetworkAddress.class);
- private static final String DEFAULT_BRIDGE = "br-int";
- private static final String VPORT_PREFIX = "tap";
- private static final String OK = "OK";
- private static final String NO = "NO";
-
private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
{
put("key", "flow");
@@ -154,7 +149,7 @@
protected LeadershipService leadershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CordVtnInstanceManager instanceManager;
+ protected InstanceService instanceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CordVtnPipeline pipeline;
@@ -219,7 +214,7 @@
@Activate
protected void activate() {
- appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID);
+ appId = coreService.getAppId(CORDVTN_APP_ID);
localNodeId = clusterService.getLocalNode().id();
leadershipService.runForLeadership(appId.name());
@@ -315,13 +310,13 @@
"Data plane IP added to br-int : %s (%s)%n" +
"Local management IP added to br-int : %s (%s)",
node.state(),
- isBrIntCreated(node) ? OK : NO, node.intBrId(),
- isTunnelIntfCreated(node) ? OK : NO,
- isDataPlaneIntfAdded(node) ? OK : NO, node.dpIntf(),
+ isBrIntCreated(node) ? MSG_OK : MSG_NO, node.intBrId(),
+ isTunnelIntfCreated(node) ? MSG_OK : MSG_NO,
+ isDataPlaneIntfAdded(node) ? MSG_OK : MSG_NO, node.dpIntf(),
isInterfaceUp(session, node.dpIntf()) &&
- getCurrentIps(session, node.dpIntf()).isEmpty() ? OK : NO, node.dpIntf(),
- intBrIps.contains(node.dpIp().ip()) ? OK : NO, node.dpIp().cidr(),
- intBrIps.contains(node.localMgmtIp().ip()) ? OK : NO, node.localMgmtIp().cidr());
+ getCurrentIps(session, node.dpIntf()).isEmpty() ? MSG_OK : MSG_NO, node.dpIntf(),
+ intBrIps.contains(node.dpIp().ip()) ? MSG_OK : MSG_NO, node.dpIp().cidr(),
+ intBrIps.contains(node.localMgmtIp().ip()) ? MSG_OK : MSG_NO, node.localMgmtIp().cidr());
disconnect(session);
@@ -449,12 +444,12 @@
deviceService.getPorts(node.intBrId()).stream()
.filter(port -> portName(port).startsWith(VPORT_PREFIX) &&
port.isEnabled())
- .forEach(port -> instanceManager.addInstance(connectPoint(port)));
+ .forEach(port -> instanceService.addInstance(connectPoint(port)));
hostService.getHosts().forEach(host -> {
if (deviceService.getPort(host.location().deviceId(),
host.location().port()) == null) {
- instanceManager.removeInstance(connectPoint(host));
+ instanceService.removeInstance(connectPoint(host));
}
});
@@ -872,7 +867,7 @@
if (portName.startsWith(VPORT_PREFIX)) {
if (isNodeStateComplete(node)) {
- instanceManager.addInstance(connectPoint(port));
+ instanceService.addInstance(connectPoint(port));
} else {
log.debug("VM is detected on incomplete node, ignore it.", portName);
}
@@ -900,7 +895,7 @@
if (portName.startsWith(VPORT_PREFIX)) {
if (isNodeStateComplete(node)) {
- instanceManager.removeInstance(connectPoint(port));
+ instanceService.removeInstance(connectPoint(port));
} else {
log.debug("VM is vanished from incomplete node, ignore it.", portName);
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnPipeline.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnPipeline.java
index f5799c3..8aa0946 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnPipeline.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnPipeline.java
@@ -28,8 +28,8 @@
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onlab.util.ItemNotFoundException;
+import org.opencord.cordvtn.api.Constants;
import org.opencord.cordvtn.api.CordVtnNode;
-import org.opencord.cordvtn.api.CordVtnService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Device;
@@ -90,14 +90,12 @@
public static final int VXLAN_UDP_PORT = 4789;
public static final VlanId VLAN_WAN = VlanId.vlanId((short) 500);
- public static final String DEFAULT_TUNNEL = "vxlan";
- private static final String PORT_NAME = "portName";
private ApplicationId appId;
@Activate
protected void activate() {
- appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
+ appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
log.info("Started");
}
@@ -388,18 +386,17 @@
public ExtensionTreatment tunnelDstTreatment(DeviceId deviceId, Ip4Address remoteIp) {
try {
Device device = deviceService.getDevice(deviceId);
-
- if (device.is(ExtensionTreatmentResolver.class)) {
- ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
- ExtensionTreatment treatment =
- resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
- treatment.setPropertyValue("tunnelDst", remoteIp);
- return treatment;
- } else {
- log.warn("The extension treatment resolving behaviour is not supported in device {}",
- device.id().toString());
+ if (!device.is(ExtensionTreatmentResolver.class)) {
+ log.error("The extension treatment is not supported");
return null;
+
}
+
+ ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
+ ExtensionTreatment treatment =
+ resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ treatment.setPropertyValue("tunnelDst", remoteIp);
+ return treatment;
} catch (ItemNotFoundException | UnsupportedOperationException |
ExtensionPropertyException e) {
log.error("Failed to get extension instruction {}", deviceId);
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtn.java b/src/main/java/org/opencord/cordvtn/impl/DependencyManager.java
similarity index 93%
rename from src/main/java/org/opencord/cordvtn/impl/CordVtn.java
rename to src/main/java/org/opencord/cordvtn/impl/DependencyManager.java
index 854bd40..2eb73db 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtn.java
+++ b/src/main/java/org/opencord/cordvtn/impl/DependencyManager.java
@@ -28,7 +28,7 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.opencord.cordvtn.api.CordVtnNode;
-import org.opencord.cordvtn.api.CordVtnService;
+import org.opencord.cordvtn.api.DependencyService;
import org.opencord.cordvtn.api.Instance;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
@@ -59,8 +59,6 @@
import java.util.Set;
import java.util.stream.Collectors;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
import static org.opencord.cordvtn.impl.CordVtnPipeline.*;
import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
import static org.slf4j.LoggerFactory.getLogger;
@@ -70,16 +68,21 @@
*/
@Component(immediate = true)
@Service
-public class CordVtn extends AbstractInstanceHandler implements CordVtnService {
+public class DependencyManager extends AbstractInstanceHandler implements DependencyService {
protected final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected GroupService groupService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnPipeline pipeline;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnNodeManager nodeManager;
+
@Activate
protected void activate() {
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
super.activate();
}
@@ -89,7 +92,7 @@
}
@Override
- public void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
+ public void createDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
boolean isBidirectional) {
VtnService tService = getVtnService(tServiceId);
VtnService pService = getVtnService(pServiceId);
@@ -105,7 +108,7 @@
}
@Override
- public void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId) {
+ public void removeDependency(VtnServiceId tServiceId, VtnServiceId pServiceId) {
VtnService tService = getVtnService(tServiceId);
VtnService pService = getVtnService(pServiceId);
@@ -128,9 +131,9 @@
// TODO get bidirectional information from XOS once XOS supports
service.tenantServices().stream().forEach(
- tServiceId -> createServiceDependency(tServiceId, service.id(), true));
+ tServiceId -> createDependency(tServiceId, service.id(), true));
service.providerServices().stream().forEach(
- pServiceId -> createServiceDependency(service.id(), pServiceId, true));
+ pServiceId -> createDependency(service.id(), pServiceId, true));
updateProviderServiceInstances(service);
}
@@ -180,6 +183,7 @@
groupKey,
new GroupBuckets(bucketsToRemove),
groupKey, appId);
+ log.debug("Removes instances from {} : {}", service.name(), bucketsToRemove);
}
List<GroupBucket> bucketsToAdd = Lists.newArrayList(newBuckets);
@@ -190,6 +194,7 @@
groupKey,
new GroupBuckets(bucketsToAdd),
groupKey, appId);
+ log.debug("Adds instances to {} : {}", service.name(), bucketsToRemove);
}
}
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/InstanceManager.java b/src/main/java/org/opencord/cordvtn/impl/InstanceManager.java
new file mode 100644
index 0000000..3041bbf
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/InstanceManager.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2015-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opencord.cordvtn.impl;
+
+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;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.opencord.cordvtn.api.CordVtnConfig;
+import org.opencord.cordvtn.api.Instance;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.dhcp.DhcpService;
+import org.onosproject.dhcp.IpAssignment;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Port;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.DefaultHostDescription;
+import org.onosproject.net.host.HostDescription;
+import org.onosproject.net.host.HostProvider;
+import org.onosproject.net.host.HostProviderRegistry;
+import org.onosproject.net.host.HostProviderService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.xosclient.api.OpenStackAccess;
+import org.onosproject.xosclient.api.VtnPort;
+import org.onosproject.xosclient.api.VtnPortApi;
+import org.onosproject.xosclient.api.VtnService;
+import org.onosproject.xosclient.api.VtnServiceApi;
+import org.onosproject.xosclient.api.VtnServiceId;
+import org.onosproject.xosclient.api.XosAccess;
+import org.onosproject.xosclient.api.XosClientService;
+import org.opencord.cordvtn.api.InstanceService;
+import org.slf4j.Logger;
+
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
+import static org.onosproject.xosclient.api.VtnServiceApi.NetworkType.MANAGEMENT;
+import static org.opencord.cordvtn.api.Constants.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Adds or removes instances to network services.
+ */
+@Component(immediate = true)
+@Service
+public class InstanceManager extends AbstractProvider implements HostProvider,
+ InstanceService {
+
+ protected final Logger log = getLogger(getClass());
+
+ private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
+ private static final int DHCP_INFINITE_LEASE = -1;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry configRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostProviderRegistry hostProviderRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DhcpService dhcpService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected XosClientService xosClient;
+
+ private final ConfigFactory configFactory =
+ new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
+ @Override
+ public CordVtnConfig createConfig() {
+ return new CordVtnConfig();
+ }
+ };
+
+ private final ExecutorService eventExecutor =
+ newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-instance", "event-handler"));
+ private final NetworkConfigListener configListener = new InternalConfigListener();
+
+ private ApplicationId appId;
+ private HostProviderService hostProvider;
+ private XosAccess xosAccess = null;
+ private OpenStackAccess osAccess = null;
+
+ /**
+ * Creates an cordvtn host location provider.
+ */
+ public InstanceManager() {
+ super(new ProviderId("host", CORDVTN_APP_ID));
+ }
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication(CORDVTN_APP_ID);
+
+ hostProvider = hostProviderRegistry.register(this);
+ configRegistry.registerConfigFactory(configFactory);
+ configRegistry.addListener(configListener);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ hostProviderRegistry.unregister(this);
+
+ configRegistry.unregisterConfigFactory(configFactory);
+ configRegistry.removeListener(configListener);
+
+ eventExecutor.shutdown();
+ log.info("Stopped");
+ }
+
+ @Override
+ public void triggerProbe(Host host) {
+ /*
+ * Note: In CORD deployment, we assume that all hosts are configured.
+ * Therefore no probe is required.
+ */
+ }
+
+ @Override
+ public void addInstance(ConnectPoint connectPoint) {
+ Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
+ if (port == null) {
+ log.debug("No port found from {}", connectPoint);
+ return;
+ }
+
+ VtnPort vtnPort = getVtnPort(port.annotations().value(PORT_NAME));
+ if (vtnPort == null) {
+ return;
+ }
+
+ VtnService vtnService = getVtnService(vtnPort.serviceId());
+ if (vtnService == null) {
+ return;
+ }
+
+ // register DHCP lease for the new instance
+ registerDhcpLease(vtnPort.mac(), vtnPort.ip().getIp4Address(), vtnService);
+
+ // Added CREATE_TIME intentionally to trigger HOST_UPDATED event for the
+ // existing instances.
+ DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+ .set(Instance.SERVICE_TYPE, vtnService.serviceType().toString())
+ .set(Instance.SERVICE_ID, vtnPort.serviceId().id())
+ .set(Instance.PORT_ID, vtnPort.id().id())
+ .set(Instance.CREATE_TIME, String.valueOf(System.currentTimeMillis()));
+
+ HostDescription hostDesc = new DefaultHostDescription(
+ vtnPort.mac(),
+ VlanId.NONE,
+ new HostLocation(connectPoint, System.currentTimeMillis()),
+ Sets.newHashSet(vtnPort.ip()),
+ annotations.build());
+
+ HostId hostId = HostId.hostId(vtnPort.mac());
+ hostProvider.hostDetected(hostId, hostDesc, false);
+ }
+
+ @Override
+ public void addNestedInstance(HostId hostId, HostDescription description) {
+ DefaultAnnotations annotations = DefaultAnnotations.builder()
+ .set(Instance.NESTED_INSTANCE, Instance.TRUE)
+ .build();
+ annotations = annotations.merge(annotations, description.annotations());
+
+ HostDescription nestedHost = new DefaultHostDescription(
+ description.hwAddress(),
+ description.vlan(),
+ description.location(),
+ description.ipAddress(),
+ annotations);
+
+ hostProvider.hostDetected(hostId, nestedHost, false);
+ }
+
+ @Override
+ public void removeInstance(ConnectPoint connectPoint) {
+ hostService.getConnectedHosts(connectPoint).stream()
+ .forEach(host -> {
+ dhcpService.removeStaticMapping(host.mac());
+ hostProvider.hostVanished(host.id());
+ });
+ }
+
+ @Override
+ public void removeNestedInstance(HostId hostId) {
+ hostProvider.hostVanished(hostId);
+ }
+
+ private void registerDhcpLease(MacAddress macAddr, Ip4Address ipAddr, VtnService service) {
+ Ip4Address broadcast = Ip4Address.makeMaskedAddress(
+ ipAddr,
+ service.subnet().prefixLength());
+
+ IpAssignment.Builder ipBuilder = IpAssignment.builder()
+ .ipAddress(ipAddr)
+ .leasePeriod(DHCP_INFINITE_LEASE)
+ .timestamp(new Date())
+ .subnetMask(Ip4Address.makeMaskPrefix(service.subnet().prefixLength()))
+ .broadcast(broadcast)
+ .domainServer(DEFAULT_DNS)
+ .assignmentStatus(Option_RangeNotEnforced);
+
+ if (service.networkType() != MANAGEMENT) {
+ ipBuilder = ipBuilder.routerAddress(service.serviceIp().getIp4Address());
+ }
+
+ log.debug("Set static DHCP mapping for {} {}", macAddr, ipAddr);
+ dhcpService.setStaticMapping(macAddr, ipBuilder.build());
+ }
+
+ private VtnService getVtnService(VtnServiceId serviceId) {
+ checkNotNull(osAccess, ERROR_OPENSTACK_ACCESS);
+ checkNotNull(xosAccess, ERROR_XOS_ACCESS);
+
+ // TODO remove openstack access when XOS provides all information
+ VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
+ VtnService service = serviceApi.service(serviceId, osAccess);
+ if (service == null) {
+ log.warn("Failed to get VtnService for {}", serviceId);
+ }
+ return service;
+ }
+
+ private VtnPort getVtnPort(String portName) {
+ checkNotNull(osAccess, ERROR_OPENSTACK_ACCESS);
+ checkNotNull(xosAccess, ERROR_XOS_ACCESS);
+
+ // TODO remove openstack access when XOS provides all information
+ VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
+ VtnPort vtnPort = portApi.vtnPort(portName, osAccess);
+ if (vtnPort == null) {
+ log.warn("Failed to get port information of {}", portName);
+ }
+ return vtnPort;
+ }
+
+ private void readConfiguration() {
+ CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
+ if (config == null) {
+ log.debug("No configuration found");
+ return;
+ }
+
+ log.info("Load CORD-VTN configurations");
+ xosAccess = config.xosAccess();
+ osAccess = config.openstackAccess();
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (!event.configClass().equals(CordVtnConfig.class)) {
+ return;
+ }
+
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ readConfiguration();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/handler/DefaultInstanceHandler.java
similarity index 95%
rename from src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
rename to src/main/java/org/opencord/cordvtn/impl/handler/DefaultInstanceHandler.java
index 0c19509..98673cf 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/handler/DefaultInstanceHandler.java
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.opencord.cordvtn.impl.service;
+package org.opencord.cordvtn.impl.handler;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
@@ -34,12 +36,11 @@
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.impl.CordVtnNodeManager;
import org.opencord.cordvtn.impl.CordVtnPipeline;
import java.util.Optional;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.DEFAULT;
/**
@@ -48,10 +49,15 @@
@Component(immediate = true)
public class DefaultInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnPipeline pipeline;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnNodeManager nodeManager;
+
@Activate
protected void activate() {
serviceType = Optional.of(DEFAULT);
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-default", "event-handler"));
super.activate();
}
@@ -112,7 +118,6 @@
.transition(CordVtnPipeline.TABLE_ACCESS_TYPE)
.build();
-
FlowRule flowRule = DefaultFlowRule.builder()
.fromApp(appId)
.withSelector(selector)
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/handler/ManagementInstanceHandler.java
similarity index 85%
rename from src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
rename to src/main/java/org/opencord/cordvtn/impl/handler/ManagementInstanceHandler.java
index 2e49a0b..fe30781 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/handler/ManagementInstanceHandler.java
@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.opencord.cordvtn.impl.service;
+package org.opencord.cordvtn.impl.handler;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
@@ -34,8 +36,6 @@
import java.util.Optional;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.MANAGEMENT;
/**
@@ -44,10 +44,12 @@
@Component(immediate = true)
public class ManagementInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnPipeline pipeline;
+
@Activate
protected void activate() {
serviceType = Optional.of(MANAGEMENT);
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-mgmt", "event-handler"));
super.activate();
}
@@ -153,7 +155,7 @@
.withTreatment(treatment)
.withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
.forDevice(instance.deviceId())
- .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+ .forTable(CordVtnPipeline.TABLE_ZERO)
.makePermanent()
.build();
@@ -182,5 +184,27 @@
.build();
pipeline.processFlowRule(install, flowRule);
+
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(instance.ipAddress().toIpPrefix())
+ .build();
+
+ treatment = DefaultTrafficTreatment.builder()
+ .setEthDst(instance.mac())
+ .setOutput(instance.portNumber())
+ .build();
+
+ flowRule = DefaultFlowRule.builder()
+ .fromApp(appId)
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+ .forDevice(instance.deviceId())
+ .forTable(CordVtnPipeline.TABLE_DST_IP)
+ .makePermanent()
+ .build();
+
+ pipeline.processFlowRule(install, flowRule);
}
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/handler/OltAgentInstanceHandler.java
similarity index 93%
rename from src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
rename to src/main/java/org/opencord/cordvtn/impl/handler/OltAgentInstanceHandler.java
index b409e79..853963e 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/handler/OltAgentInstanceHandler.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.opencord.cordvtn.impl.service;
+package org.opencord.cordvtn.impl.handler;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
@@ -37,8 +37,6 @@
import java.util.Optional;
import java.util.Set;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.OLT_AGENT;
/**
@@ -62,12 +60,10 @@
@Activate
protected void activate() {
serviceType = Optional.of(OLT_AGENT);
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-olt", "event-handler"));
+ configListener = new InternalConfigListener();
+ super.activate();
configRegistry.registerConfigFactory(configFactory);
- configListener = new InternalConfigListener();
-
- super.activate();
}
@Deactivate
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/handler/VsgInstanceHandler.java
similarity index 95%
rename from src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
rename to src/main/java/org/opencord/cordvtn/impl/handler/VsgInstanceHandler.java
index e6fd643..1f96023 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/handler/VsgInstanceHandler.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.opencord.cordvtn.impl.service;
+package org.opencord.cordvtn.impl.handler;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
@@ -28,10 +28,10 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.opencord.cordvtn.api.InstanceService;
import org.opencord.cordvtn.impl.AbstractInstanceHandler;
import org.opencord.cordvtn.api.Instance;
import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceManager;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
@@ -50,6 +50,7 @@
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.xosclient.api.VtnPort;
+import org.opencord.cordvtn.impl.CordVtnNodeManager;
import org.opencord.cordvtn.impl.CordVtnPipeline;
import java.util.Map;
@@ -57,8 +58,6 @@
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.VSG;
@@ -70,6 +69,12 @@
@Service(value = VsgInstanceHandler.class)
public final class VsgInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnPipeline pipeline;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CordVtnNodeManager nodeManager;
+
private static final String STAG = "stag";
private static final String VSG_VM = "vsgVm";
@@ -77,12 +82,11 @@
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CordVtnInstanceManager instanceManager;
+ protected InstanceService instanceService;
@Activate
protected void activate() {
serviceType = Optional.of(VSG);
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-vsg", "event-handler"));
super.activate();
}
@@ -106,9 +110,9 @@
Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
VtnPort vtnPort = getVtnPort(vsgVm);
if (vtnPort == null || getStag(vtnPort) == null) {
+ log.warn("Failed to get vSG information {}", vsgVm);
return;
}
-
populateVsgRules(vsgVm, getStag(vtnPort),
nodeManager.dpPort(vsgVm.deviceId()),
vtnPort.addressPairs().keySet(),
@@ -119,7 +123,6 @@
if (vtnPort == null || getStag(vtnPort) == null) {
return;
}
-
log.info("vSG VM detected {}", instance);
// insert vSG containers inside the vSG VM as a host
@@ -197,7 +200,7 @@
.filter(host -> !vsgInstances.values().contains(host.mac()))
.forEach(host -> {
log.info("Removed vSG {}", host.toString());
- instanceManager.removeInstance(host.id());
+ instanceService.removeNestedInstance(host.id());
});
}
@@ -212,7 +215,6 @@
.set(Instance.SERVICE_TYPE, vsgVm.serviceType().toString())
.set(Instance.SERVICE_ID, vsgVm.serviceId().id())
.set(Instance.PORT_ID, vsgVm.portId().id())
- .set(Instance.NESTED_INSTANCE, Instance.TRUE)
.set(STAG, stag)
.set(VSG_VM, vsgVm.host().id().toString())
.set(Instance.CREATE_TIME, String.valueOf(System.currentTimeMillis()));
@@ -224,7 +226,7 @@
Sets.newHashSet(vsgWanIp),
annotations.build());
- instanceManager.addInstance(hostId, hostDesc);
+ instanceService.addNestedInstance(hostId, hostDesc);
}
private void populateVsgRules(Instance vsgVm, VlanId stag, PortNumber dpPort,
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/package-info.java b/src/main/java/org/opencord/cordvtn/impl/handler/package-info.java
similarity index 94%
rename from src/main/java/org/opencord/cordvtn/impl/service/package-info.java
rename to src/main/java/org/opencord/cordvtn/impl/handler/package-info.java
index 7d00d9f..c4c0aa0 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/package-info.java
+++ b/src/main/java/org/opencord/cordvtn/impl/handler/package-info.java
@@ -17,4 +17,4 @@
/**
* Implementation of instance handlers for various network services.
*/
-package org.opencord.cordvtn.impl.service;
\ No newline at end of file
+package org.opencord.cordvtn.impl.handler;
\ No newline at end of file
diff --git a/src/main/java/org/opencord/cordvtn/rest/NeutronMl2PortsWebResource.java b/src/main/java/org/opencord/cordvtn/rest/NeutronMl2PortsWebResource.java
index f47f9db..560d01d 100644
--- a/src/main/java/org/opencord/cordvtn/rest/NeutronMl2PortsWebResource.java
+++ b/src/main/java/org/opencord/cordvtn/rest/NeutronMl2PortsWebResource.java
@@ -21,7 +21,7 @@
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
-import org.opencord.cordvtn.impl.service.VsgInstanceHandler;
+import org.opencord.cordvtn.impl.handler.VsgInstanceHandler;
import org.onosproject.net.HostId;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
diff --git a/src/main/java/org/opencord/cordvtn/rest/ServiceDependencyWebResource.java b/src/main/java/org/opencord/cordvtn/rest/ServiceDependencyWebResource.java
index 4d27856..9c58757 100644
--- a/src/main/java/org/opencord/cordvtn/rest/ServiceDependencyWebResource.java
+++ b/src/main/java/org/opencord/cordvtn/rest/ServiceDependencyWebResource.java
@@ -15,9 +15,9 @@
*/
package org.opencord.cordvtn.rest;
-import org.opencord.cordvtn.api.CordVtnService;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.xosclient.api.VtnServiceId;
+import org.opencord.cordvtn.api.DependencyService;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
@@ -33,7 +33,7 @@
@Path("service-dependency")
public class ServiceDependencyWebResource extends AbstractWebResource {
- private final CordVtnService service = get(CordVtnService.class);
+ private final DependencyService service = get(DependencyService.class);
private static final String BIDIRECTION = "b";
/**
@@ -48,9 +48,9 @@
@Produces(MediaType.APPLICATION_JSON)
public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId) {
- service.createServiceDependency(VtnServiceId.of(tServiceId),
- VtnServiceId.of(pServiceId),
- false);
+ service.createDependency(VtnServiceId.of(tServiceId),
+ VtnServiceId.of(pServiceId),
+ false);
return Response.status(Response.Status.OK).build();
}
@@ -68,9 +68,9 @@
public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId,
@PathParam("direction") String direction) {
- service.createServiceDependency(VtnServiceId.of(tServiceId),
- VtnServiceId.of(pServiceId),
- direction.equals(BIDIRECTION));
+ service.createDependency(VtnServiceId.of(tServiceId),
+ VtnServiceId.of(pServiceId),
+ direction.equals(BIDIRECTION));
return Response.status(Response.Status.OK).build();
}
@@ -85,7 +85,7 @@
@Path("{tenantServiceId}/{providerServiceId}")
public Response removeServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId) {
- service.removeServiceDependency(VtnServiceId.of(tServiceId), VtnServiceId.of(pServiceId));
+ service.removeDependency(VtnServiceId.of(tServiceId), VtnServiceId.of(pServiceId));
return Response.noContent().build();
}
}