2 * Copyright (c) 2015 Huawei Technologies and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.groupbasedpolicy.renderer.faas;
11 import static com.google.common.base.Preconditions.checkNotNull;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.base.Optional;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.List;
18 import java.util.UUID;
19 import java.util.concurrent.Executor;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
28 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
29 import org.opendaylight.groupbasedpolicy.util.IetfModelCodec;
30 import org.opendaylight.groupbasedpolicy.util.IidFactory;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContext;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.endpoints.locations.rev151013.endpoints.locations.container.endpoints.locations.EndpointLocationBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIps;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIpsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpoint;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
48 import org.opendaylight.yangtools.concepts.ListenerRegistration;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class FaasEndpointManagerListener implements AutoCloseable {
54 private static final Logger LOG = LoggerFactory.getLogger(FaasEndpointManagerListener.class);
55 private final List<ListenerRegistration<?>> listenerRegistrations = new ArrayList<>();
56 private final FaasPolicyManager policyManager;
57 private final DataBroker dataProvider;
59 public FaasEndpointManagerListener(FaasPolicyManager policyManager, DataBroker dataProvider,
61 this.policyManager = policyManager;
62 this.dataProvider = dataProvider;
64 checkNotNull(dataProvider);
65 listenerRegistrations.add(dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
66 LogicalDatastoreType.OPERATIONAL, IidFactory.endpointsIidWildcard().child(Endpoint.class)),
67 changes -> executor.execute(() -> onEndpointChanged(changes))));
69 listenerRegistrations.add(dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
70 LogicalDatastoreType.OPERATIONAL, IidFactory.endpointsIidWildcard().child(EndpointL3.class)),
71 changes -> executor.execute(() -> onEndpointL3Changed(changes))));
75 public void close() throws Exception {
76 for (ListenerRegistration<?> reg: listenerRegistrations) {
81 private void onEndpointChanged(Collection<DataTreeModification<Endpoint>> changes) {
82 for (DataTreeModification<Endpoint> change: changes) {
83 DataObjectModification<Endpoint> rootNode = change.getRootNode();
84 switch (rootNode.getModificationType()) {
85 case SUBTREE_MODIFIED:
87 Endpoint updatedEndpoint = rootNode.getDataAfter();
88 LOG.debug("Updated Endpoint {}", updatedEndpoint);
89 if (validate(updatedEndpoint)) {
90 policyManager.registerTenant(updatedEndpoint.getTenant(), updatedEndpoint.getEndpointGroup());
91 processEndpoint(updatedEndpoint);
95 Endpoint deletedEndpoint = rootNode.getDataBefore();
96 LOG.debug("Removed Endpoint {}", deletedEndpoint);
97 removeFaasEndpointLocationIfExist(deletedEndpoint.getTenant(), deletedEndpoint.getL2Context(),
98 deletedEndpoint.getMacAddress());
106 private void onEndpointL3Changed(Collection<DataTreeModification<EndpointL3>> changes) {
107 for (DataTreeModification<EndpointL3> change: changes) {
108 DataObjectModification<EndpointL3> rootNode = change.getRootNode();
109 switch (rootNode.getModificationType()) {
110 case SUBTREE_MODIFIED:
112 LOG.debug("Updated EndpointL3 {}", rootNode.getDataAfter());
115 EndpointL3 endpoint = rootNode.getDataBefore();
116 LOG.debug("Removed EndpointL3 {}", endpoint);
117 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
118 endpoint.getMacAddress());
126 protected void processEndpoint(Endpoint endpoint) {
127 Uuid tenantId = policyManager.getFaasTenantId(endpoint.getTenant());
128 if (tenantId == null) {
129 LOG.error("Failed Endpoint Registration. Couldn't find faas tenant Id. Endpoint {}", endpoint);
132 EndpointLocationBuilder epLocBuilder = new EndpointLocationBuilder();
133 epLocBuilder.setDescription(new Text("gbp-endpoint"));
134 epLocBuilder.setName(new Text(endpoint.getL2Context().getValue()));
135 epLocBuilder.setTenantId(tenantId);
136 epLocBuilder.setFaasPortRefId(endpoint.getAugmentation(FaasEndpointContext.class).getFaasPortRefId());
137 Uuid epId = getFaasEndpointId(endpoint);
139 LOG.error("Failed Endpoint registration. Couldn't Create Faas Endpoint Id");
142 epLocBuilder.setUuid(epId);
143 Uuid faasSubnetId = getFaasSubnetId(endpoint);
144 List<PrivateIps> privateIpAddresses = new ArrayList<>();
145 for (L3Address ip : endpoint.getL3Address()) {
146 PrivateIpsBuilder ipBuilder = new PrivateIpsBuilder();
147 ipBuilder.setIpAddress(IetfModelCodec.ipAddress2013(ip.getIpAddress()));
148 ipBuilder.setSubnetId(faasSubnetId);
149 privateIpAddresses.add(ipBuilder.build());
151 if (!UlnDatastoreApi.attachEndpointToSubnet(epLocBuilder, faasSubnetId, IetfModelCodec.macAddress2013(endpoint.getMacAddress()),
152 privateIpAddresses, null)) {
153 LOG.error("Failed Endpoint Registration. Failed to Attach Endpoint to Faas Logical Network. Endpoint {}",
158 private Uuid getFaasEndpointId(Endpoint endpoint) {
159 MappedEndpoint mEndpoint1 = getMappedEndpoint(endpoint);
160 if (mEndpoint1 != null) {
161 return mEndpoint1.getEndpointLocation();
163 synchronized (this) {// must be atomic
164 MappedEndpoint mEndpoint2 = getMappedEndpoint(endpoint);
165 if (mEndpoint2 != null) {
166 return mEndpoint2.getEndpointLocation();
168 MappedEndpointBuilder mBuilder = new MappedEndpointBuilder();
169 mBuilder.setL2Context(endpoint.getL2Context());
170 mBuilder.setMacAddress(endpoint.getMacAddress());
171 mBuilder.setEndpointLocation(new Uuid(UUID.randomUUID().toString()));
172 MappedEndpoint mEndpoint = mBuilder.build();
173 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
174 wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedEndpointIid(
175 endpoint.getTenant(), new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress())),
177 if (DataStoreHelper.submitToDs(wTx)) {
178 LOG.debug("Cached in Datastore Mapped Endpoint {}", mEndpoint);
179 return mEndpoint.getEndpointLocation();
181 LOG.error("Couldn't Cache in Datastore Mapped Endpoint {}", mEndpoint);
188 Uuid getFaasSubnetId(Endpoint endpoint) {
189 if (endpoint.getEndpointGroup() == null) {
190 LOG.error("Failed Endpoint registration -- No Endpoint-Group Id in endpoint {}", endpoint);
193 SubnetId subnetId = null;
194 if (endpoint.getNetworkContainment() != null) {
195 LOG.trace("Subnet is defined based on endpoint containment value {}", endpoint.getNetworkContainment()
197 subnetId = new SubnetId(endpoint.getNetworkContainment());
199 if (subnetId == null) {
200 LOG.error("Failed Endpoint registration -- Couldn't find a subnet for endpoint {}", endpoint.getKey());
203 LOG.debug("Using subnetId {} for endpoint {}", subnetId, endpoint.getKey());
204 policyManager.registerSubnetWithEpg(endpoint.getEndpointGroup(), endpoint.getTenant(), subnetId);
206 Optional<MappedSubnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
207 FaasIidFactory.mappedSubnetIid(endpoint.getTenant(), subnetId),
208 dataProvider.newReadWriteTransaction());
209 if (subnetOp.isPresent()) {
210 return subnetOp.get().getFaasSubnetId();
212 LOG.error("Failed Endpoint registration -- Couldn't find Mapped Subnet Id based on GBP Subnet Id {}", subnetId);
217 boolean validate(Endpoint endpoint) {
218 if (endpoint.getL2Context() == null) {
219 LOG.error("Endpoint Failed Validation -- Missing L2 Context. Endpoint {}", endpoint);
222 if (endpoint.getL3Address() == null) {
223 LOG.error("Endpoint Failed Validation -- Missing L3 Address. Endpoint {}", endpoint);
226 if (endpoint.getMacAddress() == null) {
227 LOG.error("Endpoint Failed Validation -- Missing Mac Address. Endpoint {}", endpoint);
230 if (endpoint.getTenant() == null) {
231 LOG.error("Endpoint Failed Validation -- Missing Tenant Id. Endpoint {}", endpoint);
234 if (endpoint.getEndpointGroup() == null) {
235 LOG.error("Endpoint Failed Validation -- Missing Endpoint-Group. Endpoint {}", endpoint);
238 FaasEndpointContext faasEpAug = endpoint.getAugmentation(FaasEndpointContext.class);
239 if (faasEpAug == null || faasEpAug.getFaasPortRefId() == null) {
240 LOG.error("Endpoint Failed Validation -- Missing Required Faas Info. Endpoint {}", endpoint);
246 private void removeFaasEndpointLocationIfExist(TenantId tenantId, L2BridgeDomainId l2BridgeDomainId,
247 MacAddress macAddress) {
248 synchronized (this) {
249 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(l2BridgeDomainId, macAddress);
250 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
251 Optional<MappedEndpoint> endpointOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
252 FaasIidFactory.mappedEndpointIid(tenantId, mappedEndpointKey), rwTx);
253 DataStoreHelper.submitToDs(rwTx);
254 if (endpointOp.isPresent()) {
255 UlnDatastoreApi.removeEndpointLocationFromDsIfExists(policyManager.getFaasTenantId(tenantId),
256 endpointOp.get().getEndpointLocation());
261 private MappedEndpoint getMappedEndpoint(Endpoint endpoint) {
262 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress());
263 Optional<MappedEndpoint> endpointOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
264 FaasIidFactory.mappedEndpointIid(endpoint.getTenant(), mappedEndpointKey),
265 dataProvider.newReadWriteTransaction());
266 if (endpointOp.isPresent()) {
267 return endpointOp.get();