Editing network containment of endpoints
[groupbasedpolicy.git] / sxp-mapper / src / main / java / org / opendaylight / groupbasedpolicy / sxp / mapper / impl / SxpMapperReactorImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.sxp.mapper.impl;
10
11 import java.util.Collections;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
17 import org.opendaylight.groupbasedpolicy.sxp.mapper.api.SxpMapperReactor;
18 import org.opendaylight.groupbasedpolicy.sxp.mapper.impl.util.SxpListenerUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainment;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.common.RpcResult;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import com.google.common.base.Optional;
45 import com.google.common.base.Preconditions;
46 import com.google.common.util.concurrent.AsyncFunction;
47 import com.google.common.util.concurrent.CheckedFuture;
48 import com.google.common.util.concurrent.Futures;
49 import com.google.common.util.concurrent.JdkFutureAdapters;
50 import com.google.common.util.concurrent.ListenableFuture;
51
52 /**
53  * Purpose: exclusively processes sxp master database changes and EGP templates changes
54  */
55 public class SxpMapperReactorImpl implements SxpMapperReactor {
56
57     private static final Logger LOG = LoggerFactory.getLogger(SxpMapperReactorImpl.class);
58
59     private final BaseEndpointService l3EndpointService;
60     private final DataBroker dataBroker;
61
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");
65     }
66
67     @Override
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())
80             .build())
81             .build();
82         final RegisterEndpointInput epInput = new RegisterEndpointInputBuilder()
83                 .setAddressEndpointReg(Collections.singletonList(new AddressEndpointRegBuilder()
84                         .setAddressType(IpPrefixType.class)
85                         .setAddress(address.getValue())
86                         .setContextType(L3Context.class)
87                         .setContextId(epForwardingTemplate.getL3Context())
88                         .setNetworkContainment(networkContainment)
89                         .setCondition(epPolicyTemplate.getConditions())
90                         .setTenant(epPolicyTemplate.getTenant())
91                         .setEndpointGroup(epPolicyTemplate.getEndpointGroups())
92                         .build()))
93                 .build();
94                 epForwardingTemplate.getL3Context();
95
96         return chainL3EPServiceIfEpAbsent(epInput);
97     }
98
99     private CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> findExistingEndPoint(final ContextId containment,
100                                                                                           final String address) {
101         KeyedInstanceIdentifier<AddressEndpoint, AddressEndpointKey> addressEndpointPath =
102                 InstanceIdentifier.create(Endpoints.class).child(AddressEndpoints.class).child(AddressEndpoint.class,
103                         new AddressEndpointKey(address, IpPrefixType.class, containment, L3Context.class));
104         final ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
105         final CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> read = rTx.read(
106                 LogicalDatastoreType.OPERATIONAL, addressEndpointPath);
107         Futures.addCallback(read, SxpListenerUtil.createTxCloseCallback(rTx));
108         return read;
109     }
110
111     private ListenableFuture<RpcResult<Void>> chainL3EPServiceIfEpAbsent(final RegisterEndpointInput epInput) {
112         AddressEndpointReg addressEndpoint = epInput.getAddressEndpointReg().get(0);
113         CheckedFuture<Optional<AddressEndpoint>, ReadFailedException> existingEndpointFuture =
114                 findExistingEndPoint(addressEndpoint.getContextId(), addressEndpoint.getAddress());
115
116         return Futures.transform(existingEndpointFuture, new AsyncFunction<Optional<AddressEndpoint>, RpcResult<Void>>() {
117             @Override
118             public ListenableFuture<RpcResult<Void>> apply(final Optional<AddressEndpoint> input) throws Exception {
119                 final ListenableFuture<RpcResult<Void>> nextResult;
120                 if (input == null || !input.isPresent()) {
121                     // invoke service
122                     return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(epInput));
123                 } else {
124                     final String existingL3EpMsg = String.format("address-endpoint for given key already exists: %s | %s",
125                             addressEndpoint.getContextId(), addressEndpoint.getAddress() );
126                     nextResult = Futures.immediateFailedFuture(new IllegalStateException(existingL3EpMsg));
127                 }
128                 return nextResult;
129             }
130         });
131     }
132
133 }
134