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