2 * Copyright (c) 2016 Cisco Systems, Inc. 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.sxp.ep.provider.impl;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.CheckedFuture;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
20 import java.util.Collections;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SxpListenerUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
48 import org.opendaylight.yangtools.yang.common.RpcResult;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * Purpose: exclusively processes sxp master database changes and EGP templates changes
55 public class SxpMapperReactorImpl implements SxpMapperReactor {
57 private static final Logger LOG = LoggerFactory.getLogger(SxpMapperReactorImpl.class);
59 private final BaseEndpointService l3EndpointService;
60 private final DataBroker dataBroker;
62 public SxpMapperReactorImpl(final BaseEndpointService l3EndpointService, final DataBroker dataBroker) {
63 this.l3EndpointService = Preconditions.checkNotNull(l3EndpointService, "l3Endpoint service missing");
64 this.dataBroker = Preconditions.checkNotNull(dataBroker, "dataBroker missing");
68 public ListenableFuture<RpcResult<Void>> processTemplatesAndSxpMasterDB(
69 final EndpointPolicyTemplateBySgt epPolicyTemplate,
70 final EndpointForwardingTemplateBySubnet epForwardingTemplate,
71 final MasterDatabaseBinding masterDBBinding) {
72 LOG.debug("processing ep-templates + sxpMasterDB entry: {} - {}",
73 masterDBBinding.getSecurityGroupTag(), masterDBBinding.getIpPrefix());
74 // apply sxpMasterDB to policy template
75 final Ipv4Prefix address = new Ipv4Prefix(epForwardingTemplate.getIpPrefix().getIpv4Prefix().getValue());
76 final NetworkContainment networkContainment = new NetworkContainmentBuilder()
77 .setContainment(new NetworkDomainContainmentBuilder()
78 .setNetworkDomainType(epForwardingTemplate.getNetworkContainment().getNetworkDomainType())
79 .setNetworkDomainId(epForwardingTemplate.getNetworkContainment().getNetworkDomainId())
82 final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(
83 Collections.singletonList(new AddressEndpointRegBuilder().setAddressType(IpPrefixType.class)
84 .setAddress(address.getValue())
85 .setContextType(L3Context.class)
86 .setContextId(epForwardingTemplate.getL3Context())
87 .setNetworkContainment(networkContainment)
88 .setCondition(epPolicyTemplate.getConditions())
89 .setTenant(epPolicyTemplate.getTenant())
90 .setEndpointGroup(epPolicyTemplate.getEndpointGroups())
93 epForwardingTemplate.getL3Context();
95 return chainL3EPServiceIfEpAbsent(epInput);
98 private CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> findExistingEndPoint(final ContextId containment,
99 final String address) {
100 KeyedInstanceIdentifier<AddressEndpoint, AddressEndpointKey> addressEndpointPath =
101 InstanceIdentifier.create(Endpoints.class).child(AddressEndpoints.class).child(AddressEndpoint.class,
102 new AddressEndpointKey(address, IpPrefixType.class, containment, L3Context.class));
103 final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
104 final CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> read = rTx.read(
105 LogicalDatastoreType.OPERATIONAL, addressEndpointPath);
106 Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx), MoreExecutors.directExecutor());
110 private ListenableFuture<RpcResult<Void>> chainL3EPServiceIfEpAbsent(final RegisterEndpointInput epInput) {
111 AddressEndpointReg addressEndpoint = epInput.getAddressEndpointReg().get(0);
112 CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> existingEndpointFuture =
113 findExistingEndPoint(addressEndpoint.getContextId(), addressEndpoint.getAddress());
115 return Futures.transformAsync(existingEndpointFuture, new AsyncFunction<Optional<AddressEndpoint>, RpcResult<Void>>() {
117 public ListenableFuture<RpcResult<Void>> apply(final Optional<AddressEndpoint> input) throws Exception {
118 final ListenableFuture<RpcResult<Void>> nextResult;
119 if (input == null || !input.isPresent() || !isSameEpg(epInput, input.get())) {
121 return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(epInput));
123 final String existingL3EpMsg = String.format("address-endpoint for given key already exists: %s | %s",
124 addressEndpoint.getContextId(), addressEndpoint.getAddress() );
125 nextResult = Futures.immediateFailedFuture(new IllegalStateException(existingL3EpMsg));
129 }, MoreExecutors.directExecutor());
132 private boolean isSameEpg(RegisterEndpointInput epInput, AddressEndpoint input) {
133 if (epInput == null || epInput.getAddressEndpointReg() == null || epInput.getAddressEndpointReg().isEmpty()) {
136 final AddressEndpointReg epInputAddressEndpoint = epInput.getAddressEndpointReg().get(0);
137 if (epInputAddressEndpoint.getEndpointGroup() == null || epInputAddressEndpoint.getEndpointGroup().isEmpty()) {
140 if (input == null || input.getEndpointGroup() == null || input.getEndpointGroup().isEmpty()) {
143 final EndpointGroupId addressEndpointGroupId = epInputAddressEndpoint.getEndpointGroup().get(0);
144 final EndpointGroupId existingEndpointGroupId = input.getEndpointGroup().get(0);
145 return addressEndpointGroupId.equals(existingEndpointGroupId);