b1cd010cf9472cfb937e6759afd3f9debfa9c7ed
[groupbasedpolicy.git] / renderers / ios-xe / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ios_xe_provider / impl / manager / PolicyManagerImpl.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.renderer.ios_xe_provider.impl.manager;
10
11 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
12 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
13
14 import com.google.common.base.Function;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.AsyncFunction;
17 import com.google.common.util.concurrent.CheckedFuture;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import javax.annotation.Nullable;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
30 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
31 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class PolicyManagerImpl implements PolicyManager {
48
49     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerImpl.class);
50     private static final String policyMapName = "service-chains";
51     private final DataBroker dataBroker;
52     private final NodeManager nodeManager;
53
54     public PolicyManagerImpl(final DataBroker dataBroker,
55                              final NodeManager nodeManager) {
56         this.dataBroker = Preconditions.checkNotNull(dataBroker);
57         this.nodeManager = Preconditions.checkNotNull(nodeManager);
58     }
59
60     @Override
61     public ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, final Configuration dataBefore,
62                                                 final long version) {
63         final ListenableFuture<Boolean> result;
64         if (dataBefore == null && dataAfter != null) {
65             result = syncPolicy(dataAfter, Create);
66         } else if (dataBefore != null && dataAfter == null) {
67             result = syncPolicy(dataBefore, Delete);
68         } else {
69             // TODO implement
70             result = Futures.immediateFuture(false);
71         }
72
73         reportVersion(version);
74
75         // chain version update (TODO: status)
76         return Futures.transform(result, new AsyncFunction<Boolean, Boolean>() {
77             @Override
78             public ListenableFuture<Boolean> apply(final Boolean input) throws Exception {
79                 if (input != null && input) {
80                     return Futures.transform(reportVersion(version), new Function<Void, Boolean>() {
81                         @Nullable
82                         @Override
83                         public Boolean apply(@Nullable final Void input) {
84                             return Boolean.TRUE;
85                         }
86                     });
87                 } else {
88                     return Futures.immediateFuture(input);
89                 }
90             }
91         });
92     }
93
94     private ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, DsAction action) {
95         if (dataAfter.getRendererEndpoints() == null
96                 || dataAfter.getRendererEndpoints().getRendererEndpoint() == null) {
97             LOG.debug("no configuration obtained - skipping");
98             return Futures.immediateFuture(true);
99         }
100         final Map<DataBroker, PolicyWriter> policyWriterPerDeviceCache = new HashMap<>();
101         for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
102             if (dataAfter.getEndpoints() == null || dataAfter.getEndpoints().getAddressEndpointWithLocation() == null) {
103                 LOG.debug("renderer-endpoint: missing address-endpoint-with-location");
104                 //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
105                 continue;
106             }
107
108             final List<AddressEndpointWithLocation> endpointsWithLocation = dataAfter.getEndpoints()
109                     .getAddressEndpointWithLocation();
110             final InstanceIdentifier mountpointIid = PolicyManagerUtil.getAbsoluteLocationMountpoint(rendererEndpoint, endpointsWithLocation);
111             final DataBroker mountpoint = nodeManager.getNodeMountPoint(mountpointIid);
112             if (mountpoint == null) {
113                 LOG.debug("no data-broker for mount-point [{}] available", mountpointIid);
114                 //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
115                 continue;
116             }
117
118             // Find policy writer
119             PolicyWriter policyWriter = policyWriterPerDeviceCache.get(mountpoint);
120             if (policyWriter == null) {
121                 // Initialize new policy writer
122                 final String interfaceName = PolicyManagerUtil.getInterfaceNameForPolicyMap(rendererEndpoint, endpointsWithLocation);
123                 final NodeId nodeId = nodeManager.getNodeIdByMountpointIid(mountpointIid);
124                 final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
125                 if (interfaceName == null || managementIpAddress == null) {
126                     LOG.debug("can not create policyWriter: interface={}, managementIpAddress={}",
127                             interfaceName, managementIpAddress);
128                     //TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
129                     continue;
130                 }
131                 policyWriter = new PolicyWriter(mountpoint, interfaceName, managementIpAddress, policyMapName, nodeId);
132                 policyWriterPerDeviceCache.put(mountpoint, policyWriter);
133             }
134
135             final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
136                     .getAddressEndpointWithLocation());
137             // Peer Endpoint
138             for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
139                 final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(peerEndpoint, dataAfter.getEndpoints()
140                         .getAddressEndpointWithLocation());
141                 if (sourceSgt == null || destinationSgt == null) {
142                     LOG.debug("endpoint-policy: missing sgt value(sourceSgt={}, destinationSgt={})",
143                             sourceSgt, destinationSgt);
144                     //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
145                     continue;
146                 }
147                 PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
148             }
149         }
150
151         //TODO: return real (cumulated) future
152         final List<CheckedFuture<Void, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
153         if (action.equals(Create)) {
154             policyWriterPerDeviceCache.values().forEach(pw -> allFutureResults.add(pw.commitToDatastore()));
155         } else if (action.equals(Delete)) {
156             policyWriterPerDeviceCache.values().forEach(pw -> allFutureResults.add(pw.removeFromDatastore()));
157         } else {
158             LOG.info("unsupported policy manage action: {}", action);
159
160         }
161
162         final ListenableFuture<List<Void>> cumulativeResult = Futures.allAsList(allFutureResults);
163
164         return Futures.transform(cumulativeResult, new Function<List<Void>, Boolean>() {
165             @Nullable
166             @Override
167             public Boolean apply(@Nullable final List<Void> input) {
168                 LOG.trace("considering all submits as successful - otherwise there will be exception");
169                 return Boolean.TRUE;
170             }
171         });
172     }
173
174     private CheckedFuture<Void, TransactionCommitFailedException> reportVersion(long version) {
175         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
176         InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
177                 .child(Renderer.class, new RendererKey(NodeManager.iosXeRenderer))
178                 .child(RendererPolicy.class);
179         wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, new RendererPolicyBuilder().setVersion(version).build());
180         return wtx.submit();
181     }
182
183     @Override
184     public void close() {
185         //NOOP
186     }
187
188     enum DsAction {Create, Delete}
189
190     public enum ActionCase {ALLOW, CHAIN}
191 }