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 java.util.ArrayList;
14 import java.util.List;
16 import java.util.UUID;
17 import java.util.concurrent.ScheduledExecutorService;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
27 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
28 import org.opendaylight.groupbasedpolicy.util.IidFactory;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.faas.endpoint.rev151009.FaasEndpointContext;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.endpoints.locations.rev151013.endpoints.locations.container.endpoints.locations.EndpointLocationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIps;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.ports.rev151013.ports.container.ports.port.PrivateIpsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpoint;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedEndpointKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedSubnet;
47 import org.opendaylight.yangtools.concepts.ListenerRegistration;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import com.google.common.base.Optional;
55 public class FaasEndpointManagerListener implements DataChangeListener, AutoCloseable {
57 private static final Logger LOG = LoggerFactory.getLogger(FaasEndpointManagerListener.class);
58 private final ScheduledExecutorService executor;
59 private final ListenerRegistration<DataChangeListener> registerListener;
60 private final FaasPolicyManager policyManager;
61 private final DataBroker dataProvider;
63 public FaasEndpointManagerListener(FaasPolicyManager policyManager, DataBroker dataProvider,
64 ScheduledExecutorService executor) {
65 this.executor = executor;
66 this.policyManager = policyManager;
67 this.dataProvider = dataProvider;
68 this.registerListener = checkNotNull(dataProvider).registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
69 IidFactory.endpointsIidWildcard(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
73 public void close() throws Exception {
74 if (registerListener != null)
75 registerListener.close();
79 public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
80 executor.execute(new Runnable() {
88 private void executeEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
91 for (DataObject dao : change.getCreatedData().values()) {
92 if (dao instanceof Endpoint) {
93 Endpoint endpoint = (Endpoint) dao;
94 LOG.debug("Created Endpoint {}", endpoint);
95 if (validate(endpoint)) {
96 policyManager.registerTenant(endpoint.getTenant(), endpoint.getEndpointGroup());
97 processEndpoint(endpoint);
99 } else if (dao instanceof EndpointL3) {
100 LOG.debug("Created EndpointL3 {}", (EndpointL3) dao);
101 } else if (dao instanceof EndpointL3Prefix) {
102 LOG.warn("Not Handled Event Yet by Faas Renderer. Created EndpointL3Prefix {}", (EndpointL3Prefix) dao);
106 Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
107 for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
108 if (entry.getValue() instanceof Endpoint) {
109 Endpoint endpoint = (Endpoint) dao;
110 LOG.debug("Updated Endpoint {}", endpoint);
111 if (validate(endpoint)) {
112 policyManager.registerTenant(endpoint.getTenant(), endpoint.getEndpointGroup());
113 processEndpoint(endpoint);
115 } else if (entry.getValue() instanceof EndpointL3) {
116 LOG.debug("Updated EndpointL3 {}", (EndpointL3) dao);
117 } else if (entry.getValue() instanceof EndpointL3Prefix) {
118 LOG.warn("Not Handled Event Yet by Faas Renderer. Updated EndpointL3Prefix {}", (EndpointL3Prefix) dao);
122 for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
123 DataObject old = change.getOriginalData().get(iid);
127 if (old instanceof Endpoint) {
128 Endpoint endpoint = (Endpoint) dao;
129 LOG.debug("Removed Endpoint {}", endpoint);
130 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
131 endpoint.getMacAddress());
132 } else if (old instanceof EndpointL3) {
133 EndpointL3 endpoint = (EndpointL3) dao;
134 LOG.debug("Removed EndpointL3 {}", endpoint);
135 removeFaasEndpointLocationIfExist(endpoint.getTenant(), endpoint.getL2Context(),
136 endpoint.getMacAddress());
137 } else if (old instanceof EndpointL3Prefix) {
138 LOG.warn("Not Handled Event Yet by Faas Renderer. Removed EndpointL3Prefix {}", (EndpointL3Prefix) old);
143 private void processEndpoint(Endpoint endpoint) {
144 Uuid tenantId = policyManager.getFaasTenantId(endpoint.getTenant());
145 if (tenantId == null) {
146 LOG.error("Failed Endpoint Registration. Couldn't find faas tenant Id. Endpoint {}", endpoint);
149 EndpointLocationBuilder epLocBuilder = new EndpointLocationBuilder();
150 epLocBuilder.setDescription(new Text("gbp-endpoint"));
151 epLocBuilder.setName(new Text(endpoint.getL2Context().getValue()));
152 epLocBuilder.setTenantId(tenantId);
153 epLocBuilder.setFaasPortRefId(endpoint.getAugmentation(FaasEndpointContext.class).getFaasPortRefId());
154 Uuid epId = getFaasEndpointId(endpoint);
156 LOG.error("Failed Endpoint registration. Couldn't Create Faas Endpoint Id");
159 epLocBuilder.setUuid(epId);
160 Uuid faasSubnetId = getFaasSubnetId(endpoint);
161 List<PrivateIps> privateIpAddresses = new ArrayList<PrivateIps>();
162 for (L3Address ip : endpoint.getL3Address()) {
163 PrivateIpsBuilder ipBuilder = new PrivateIpsBuilder();
164 ipBuilder.setIpAddress(ip.getIpAddress());
165 ipBuilder.setSubnetId(faasSubnetId);
166 privateIpAddresses.add(ipBuilder.build());
168 if (!UlnDatastoreApi.attachEndpointToSubnet(epLocBuilder, faasSubnetId, endpoint.getMacAddress(),
169 privateIpAddresses, null)) {
170 LOG.error("Failed Endpoint Registration. Failed to Attach Endpoint to Faas Logical Network. Endpoint {}",
175 private Uuid getFaasEndpointId(Endpoint endpoint) {
176 MappedEndpoint mEndpoint1 = getMappedEndpoint(endpoint);
177 if (mEndpoint1 != null) {
178 return mEndpoint1.getEndpointLocation();
180 synchronized (this) {// must be atomic
181 MappedEndpoint mEndpoint2 = getMappedEndpoint(endpoint);
182 if (mEndpoint2 != null) {
183 return mEndpoint2.getEndpointLocation();
185 MappedEndpointBuilder mBuilder = new MappedEndpointBuilder();
186 mBuilder.setL2Context(endpoint.getL2Context());
187 mBuilder.setMacAddress(endpoint.getMacAddress());
188 mBuilder.setEndpointLocation(new Uuid(UUID.randomUUID().toString()));
189 MappedEndpoint mEndpoint = mBuilder.build();
190 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
191 wTx.put(LogicalDatastoreType.OPERATIONAL, FaasIidFactory.mappedEndpointIid(
192 endpoint.getTenant(), new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress())),
194 if (DataStoreHelper.submitToDs(wTx)) {
195 LOG.debug("Cached in Datastore Mapped Endpoint {}", mEndpoint);
196 return mEndpoint.getEndpointLocation();
198 LOG.error("Couldn't Cache in Datastore Mapped Endpoint {}", mEndpoint);
204 private Uuid getFaasSubnetId(Endpoint endpoint) {
205 if (endpoint.getEndpointGroup() == null) {
206 LOG.error("Failed Endpoint registration -- No Endpoint-Group Id in endpoint {}", endpoint);
209 SubnetId subnetId = null;
210 if (endpoint.getNetworkContainment() != null) {
211 LOG.trace("Subnet is defined based on endpoint containment value {}", endpoint.getNetworkContainment()
213 subnetId = new SubnetId(endpoint.getNetworkContainment());
215 if (subnetId == null) {
216 LOG.error("Failed Endpoint registration -- Couldn't find a subnet for endpoint {}", endpoint.getKey());
219 LOG.debug("Using subnetId {} for endpoint {}", subnetId, endpoint.getKey());
220 policyManager.registerSubnetWithEpg(endpoint.getEndpointGroup(), endpoint.getTenant(), subnetId);
222 Optional<MappedSubnet> subnetOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
223 FaasIidFactory.mappedSubnetIid(endpoint.getTenant(), subnetId),
224 dataProvider.newReadWriteTransaction());
225 if (subnetOp.isPresent()) {
226 return subnetOp.get().getFaasSubnetId();
228 LOG.error("Failed Endpoint registration -- Couldn't find Mapped Subnet Id based on GBP Subnet Id {}", subnetId);
232 private boolean validate(Endpoint endpoint) {
233 if (endpoint.getL2Context() == null) {
234 LOG.error("Endpoint Failed Validation -- Missing L2 Context. Endpoint {}", endpoint);
237 if (endpoint.getL3Address() == null) {
238 LOG.error("Endpoint Failed Validation -- Missing L3 Address. Endpoint {}", endpoint);
241 if (endpoint.getMacAddress() == null) {
242 LOG.error("Endpoint Failed Validation -- Missing Mac Address. Endpoint {}", endpoint);
245 if (endpoint.getTenant() == null) {
246 LOG.error("Endpoint Failed Validation -- Missing Tenant Id. Endpoint {}", endpoint);
249 if (endpoint.getEndpointGroup() == null) {
250 LOG.error("Endpoint Failed Validation -- Missing Endpoint-Group. Endpoint {}", endpoint);
253 FaasEndpointContext faasEpAug = endpoint.getAugmentation(FaasEndpointContext.class);
254 if (faasEpAug == null || faasEpAug.getFaasPortRefId() == null) {
255 LOG.error("Endpoint Failed Validation -- Missing Required Faas Info. Endpoint {}", endpoint);
261 private void removeFaasEndpointLocationIfExist(TenantId tenantId, L2BridgeDomainId l2BridgeDomainId,
262 MacAddress macAddress) {
263 synchronized (this) {
264 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(l2BridgeDomainId, macAddress);
265 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
266 Optional<MappedEndpoint> endpointOp = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
267 FaasIidFactory.mappedEndpointIid(tenantId, mappedEndpointKey), rwTx);
268 DataStoreHelper.submitToDs(rwTx);
269 if (endpointOp.isPresent()) {
270 UlnDatastoreApi.removeEndpointLocationFromDsIfExists(policyManager.getFaasTenantId(tenantId),
271 endpointOp.get().getEndpointLocation());
276 private MappedEndpoint getMappedEndpoint(Endpoint endpoint) {
277 MappedEndpointKey mappedEndpointKey = new MappedEndpointKey(endpoint.getL2Context(), endpoint.getMacAddress());
278 Optional<MappedEndpoint> endpointOp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
279 FaasIidFactory.mappedEndpointIid(endpoint.getTenant(), mappedEndpointKey),
280 dataProvider.newReadWriteTransaction());
281 if (endpointOp.isPresent()) {
282 return endpointOp.get();