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.UlnDatastoreUtil;
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;
58 private final UlnDatastoreUtil ulnDatastoreUtil;
60 public FaasEndpointManagerListener(FaasPolicyManager policyManager, DataBroker dataProvider,
62 this.policyManager = policyManager;
63 this.dataProvider = dataProvider;
65 checkNotNull(dataProvider);
66 listenerRegistrations.add(dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
67 LogicalDatastoreType.OPERATIONAL, IidFactory.endpointsIidWildcard().child(Endpoint.class)),
68 changes -> executor.execute(() -> onEndpointChanged(changes))));
70 listenerRegistrations.add(dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
71 LogicalDatastoreType.OPERATIONAL, IidFactory.endpointsIidWildcard().child(EndpointL3.class)),
72 changes -> executor.execute(() -> onEndpointL3Changed(changes))));
74 this.ulnDatastoreUtil = new UlnDatastoreUtil(dataProvider);
78 public void close() throws Exception {
79 for (ListenerRegistration<?> reg: listenerRegistrations) {
84 private void onEndpointChanged(Collection<DataTreeModification<Endpoint>> changes) {
85 for (DataTreeModification<Endpoint> change: changes) {
86 DataObjectModification<Endpoint> rootNode = change.getRootNode();
87 switch (rootNode.getModificationType()) {
88 case SUBTREE_MODIFIED:
90 Endpoint updatedEndpoint = rootNode.getDataAfter();
91 LOG.debug("Updated Endpoint {}", updatedEndpoint);
92 if (validate(updatedEndpoint)) {
93 policyManager.registerTenant(updatedEndpoint.getTenant(), updatedEndpoint.getEndpointGroup());
94 processEndpoint(updatedEndpoint);
98 Endpoint deletedEndpoint = rootNode.getDataBefore();
99 LOG.debug("Removed Endpoint {}", deletedEndpoint);
100 removeFaasEndpointLocationIfExist(deletedEndpoint.getTenant(), deletedEndpoint.getL2Context(),
101 deletedEndpoint.getMacAddress());
109 private void onEndpointL3Changed(Collection<DataTreeModification<EndpointL3>> changes) {
110 for (DataTreeModification<EndpointL3> change: changes) {
111 DataObjectModification<EndpointL3> rootNode = change.getRootNode();
112 switch (rootNode.getModificationType()) {
113 case SUBTREE_MODIFIED:
115 LOG.debug("Updated EndpointL3 {}", rootNode.getDataAfter());
118 EndpointL3 endpoint = rootNode.getDataBefore();
119 LOG.debug("Removed EndpointL3 {}", endpoint);
120 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
121 endpoint.getMacAddress());
129 protected void processEndpoint(Endpoint endpoint) {
130 Uuid tenantId = policyManager.getFaasTenantId(endpoint.getTenant());
131 if (tenantId == null) {
132 LOG.error("Failed Endpoint Registration. Couldn't find faas tenant Id. Endpoint {}", endpoint);
135 EndpointLocationBuilder epLocBuilder = new EndpointLocationBuilder();
136 epLocBuilder.setDescription(new Text("gbp-endpoint"));
137 epLocBuilder.setName(new Text(endpoint.getL2Context().getValue()));
138 epLocBuilder.setTenantId(tenantId);
139 epLocBuilder.setFaasPortRefId(endpoint.getAugmentation(FaasEndpointContext.class).getFaasPortRefId());
140 Uuid epId = getFaasEndpointId(endpoint);
142 LOG.error("Failed Endpoint registration. Couldn't Create Faas Endpoint Id");
145 epLocBuilder.setUuid(epId);
146 Uuid faasSubnetId = getFaasSubnetId(endpoint);
147 List<PrivateIps> privateIpAddresses = new ArrayList<>();
148 for (L3Address ip : endpoint.getL3Address()) {
149 PrivateIpsBuilder ipBuilder = new PrivateIpsBuilder();
150 ipBuilder.setIpAddress(IetfModelCodec.ipAddress2013(ip.getIpAddress()));
151 ipBuilder.setSubnetId(faasSubnetId);
152 privateIpAddresses.add(ipBuilder.build());
154 if (!ulnDatastoreUtil.attachEndpointToSubnet(epLocBuilder, faasSubnetId, IetfModelCodec.macAddress2013(endpoint.getMacAddress()),
155 privateIpAddresses, null)) {
156 LOG.error("Failed Endpoint Registration. Failed to Attach Endpoint to Faas Logical Network. Endpoint {}",
161 private Uuid getFaasEndpointId(Endpoint endpoint) {
162 MappedEndpoint mEndpoint1 = getMappedEndpoint(endpoint);
163 if (mEndpoint1 != null) {
164 return mEndpoint1.getEndpointLocation();
166 synchronized (this) {// must be atomic
167 MappedEndpoint mEndpoint2 = getMappedEndpoint(endpoint);
168 if (mEndpoint2 != null) {
169 return mEndpoint2.getEndpointLocation();
171 MappedEndpointBuilder mBuilder = new MappedEndpointBuilder();
172 mBuilder.setL2Context(endpoint.getL2Context());
173 mBuilder.setMacAddress(endpoint.getMacAddress());
174 mBuilder.setEndpointLocation(new Uuid(UUID.randomUUID().toString()));
175 MappedEndpoint mEndpoint = mBuilder.build();
176 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
177 wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedEndpointIid(
178 endpoint.getTenant(), new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress())),
180 if (DataStoreHelper.submitToDs(wTx)) {
181 LOG.debug("Cached in Datastore Mapped Endpoint {}", mEndpoint);
182 return mEndpoint.getEndpointLocation();
184 LOG.error("Couldn't Cache in Datastore Mapped Endpoint {}", mEndpoint);
191 Uuid getFaasSubnetId(Endpoint endpoint) {
192 if (endpoint.getEndpointGroup() == null) {
193 LOG.error("Failed Endpoint registration -- No Endpoint-Group Id in endpoint {}", endpoint);
196 SubnetId subnetId = null;
197 if (endpoint.getNetworkContainment() != null) {
198 LOG.trace("Subnet is defined based on endpoint containment value {}", endpoint.getNetworkContainment()
200 subnetId = new SubnetId(endpoint.getNetworkContainment());
202 if (subnetId == null) {
203 LOG.error("Failed Endpoint registration -- Couldn't find a subnet for endpoint {}", endpoint.getKey());
206 LOG.debug("Using subnetId {} for endpoint {}", subnetId, endpoint.getKey());
207 policyManager.registerSubnetWithEpg(endpoint.getEndpointGroup(), endpoint.getTenant(), subnetId);
209 Optional<MappedSubnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
210 FaasIidFactory.mappedSubnetIid(endpoint.getTenant(), subnetId),
211 dataProvider.newReadWriteTransaction());
212 if (subnetOp.isPresent()) {
213 return subnetOp.get().getFaasSubnetId();
215 LOG.error("Failed Endpoint registration -- Couldn't find Mapped Subnet Id based on GBP Subnet Id {}", subnetId);
220 boolean validate(Endpoint endpoint) {
221 if (endpoint.getL2Context() == null) {
222 LOG.error("Endpoint Failed Validation -- Missing L2 Context. Endpoint {}", endpoint);
225 if (endpoint.getL3Address() == null) {
226 LOG.error("Endpoint Failed Validation -- Missing L3 Address. Endpoint {}", endpoint);
229 if (endpoint.getMacAddress() == null) {
230 LOG.error("Endpoint Failed Validation -- Missing Mac Address. Endpoint {}", endpoint);
233 if (endpoint.getTenant() == null) {
234 LOG.error("Endpoint Failed Validation -- Missing Tenant Id. Endpoint {}", endpoint);
237 if (endpoint.getEndpointGroup() == null) {
238 LOG.error("Endpoint Failed Validation -- Missing Endpoint-Group. Endpoint {}", endpoint);
241 FaasEndpointContext faasEpAug = endpoint.getAugmentation(FaasEndpointContext.class);
242 if (faasEpAug == null || faasEpAug.getFaasPortRefId() == null) {
243 LOG.error("Endpoint Failed Validation -- Missing Required Faas Info. Endpoint {}", endpoint);
249 private void removeFaasEndpointLocationIfExist(TenantId tenantId, L2BridgeDomainId l2BridgeDomainId,
250 MacAddress macAddress) {
251 synchronized (this) {
252 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(l2BridgeDomainId, macAddress);
253 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
254 Optional<MappedEndpoint> endpointOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
255 FaasIidFactory.mappedEndpointIid(tenantId, mappedEndpointKey), rwTx);
256 DataStoreHelper.submitToDs(rwTx);
257 if (endpointOp.isPresent()) {
258 ulnDatastoreUtil.removeEndpointLocationFromDsIfExists(policyManager.getFaasTenantId(tenantId),
259 endpointOp.get().getEndpointLocation());
264 private MappedEndpoint getMappedEndpoint(Endpoint endpoint) {
265 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress());
266 Optional<MappedEndpoint> endpointOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
267 FaasIidFactory.mappedEndpointIid(endpoint.getTenant(), mappedEndpointKey),
268 dataProvider.newReadWriteTransaction());
269 if (endpointOp.isPresent()) {
270 return endpointOp.get();