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