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.renderer.ios_xe_provider.impl.manager;
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;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
18 import java.util.Optional;
20 import javax.annotation.Nonnull;
21 import javax.annotation.Nullable;
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;
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 {
58 private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerImpl.class);
59 private static final String BASE_POLICY_MAP_NAME = "service-chains-";
60 private final DataBroker dataBroker;
61 private final NodeManager nodeManager;
63 public PolicyManagerImpl(final DataBroker dataBroker,
64 final NodeManager nodeManager) {
65 this.dataBroker = Preconditions.checkNotNull(dataBroker);
66 this.nodeManager = Preconditions.checkNotNull(nodeManager);
71 public ListenableFuture<Boolean> syncPolicy(@Nullable final Configuration dataAfter, @Nullable final Configuration dataBefore,
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);
79 syncPolicy(dataBefore, Delete);
80 syncPolicy(dataAfter, Create);
81 result = Futures.immediateFuture(Optional.empty());
84 return Futures.transform(result, new AsyncFunction<Optional<Status>, Boolean>() {
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>() {
90 public Boolean apply(@Nullable final Void input) {
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());
105 final PolicyConfigurationContext context = new PolicyConfigurationContext();
106 final Map<String, PolicyWriter> policyWriterPerDeviceCache = new HashMap<>();
107 for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
108 // Store the endpoint currently being configured
109 context.setCurrentRendererEP(rendererEndpoint);
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));
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));
125 // Generate policy writer key - policy map name, composed from base value, interface name and node id
126 final String interfaceName = PolicyManagerUtil.getInterfaceNameForPolicyMap(rendererEndpoint, endpointsWithLocation);
127 final NodeId nodeId = nodeManager.getNodeIdByMountpointIid(mountpointIid);
128 if (interfaceName == null || nodeId == null) {
129 LOG.warn("Cannot compose policy-map, missing value. Interface: {}, NodeId: {}", interfaceName, nodeId);
132 final String policyMapName = BASE_POLICY_MAP_NAME.concat(interfaceName);
133 final String policyWriterKey = policyMapName.concat(nodeId.getValue());
134 // Find appropriate writer
135 PolicyWriter policyWriter = policyWriterPerDeviceCache.get(policyWriterKey);
136 if (policyWriter == null) {
137 // Initialize new policy writer
138 final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
139 if (managementIpAddress == null) {
140 final String info = String.format("can not create policyWriter, managementIpAddress for mountpoint %s is null",
142 context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
145 policyWriter = new PolicyWriter(mountpoint, interfaceName, managementIpAddress, policyMapName, nodeId);
146 policyWriterPerDeviceCache.put(policyWriterKey, policyWriter);
149 // Assign policyWriter for current policy-map
150 context.setPolicyWriter(policyWriter);
152 final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
153 .getAddressEndpointWithLocation());
155 for (PeerEndpoint peerEndpoint : rendererEndpoint.getPeerEndpoint()) {
156 final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(peerEndpoint, dataAfter.getEndpoints()
157 .getAddressEndpointWithLocation());
158 if (sourceSgt == null || destinationSgt == null) {
159 final String info = String.format("endpoint-policy: missing sgt value(sourceSgt=%s, destinationSgt=%s)",
160 sourceSgt, destinationSgt);
161 context.appendUnconfiguredRendererEP(
162 StatusUtil.assembleNotConfigurableRendererEPForPeer(context, peerEndpoint, info));
165 PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, context, dataAfter, peerEndpoint,
170 final List<CheckedFuture<Boolean, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
171 if (action.equals(Create)) {
172 // TODO ensure that last transaction is done before the next one starts
173 policyWriterPerDeviceCache.values().forEach((pw) -> allFutureResults.add(pw.commitToDatastore()));
174 } else if (action.equals(Delete)) {
175 policyWriterPerDeviceCache.values().forEach((pw) -> allFutureResults.add(pw.removeFromDatastore()));
177 LOG.info("unsupported policy manage action: {}", action);
179 final ListenableFuture<List<Boolean>> cumulativeResult = Futures.allAsList(allFutureResults);
181 return Futures.transform(cumulativeResult, new Function<List<Boolean>, Optional<Status>>() {
184 public Optional<Status> apply(@Nullable final List<Boolean> input) {
185 //TODO: inspect if all booleans are true
187 LOG.trace("considering all submits as successful - otherwise there will be exception");
188 final Status status = new StatusBuilder()
189 .setUnconfiguredEndpoints(new UnconfiguredEndpointsBuilder()
190 .setUnconfiguredRendererEndpoint(context.getUnconfiguredRendererEPBag())
194 return Optional.of(status);
199 private CheckedFuture<Void, TransactionCommitFailedException> reportPolicy(long version, @Nonnull final Optional<Status> statusValue) {
200 final Optional<ReadWriteTransaction> optionalReadWriteTransaction =
201 NetconfTransactionCreator.netconfReadWriteTransaction(dataBroker);
202 if (!optionalReadWriteTransaction.isPresent()) {
203 LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
204 return Futures.immediateCheckedFuture(null);
206 final ReadWriteTransaction readWriteTransaction = optionalReadWriteTransaction.get();
207 final InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
208 .child(Renderer.class, new RendererKey(NodeManager.iosXeRenderer))
209 .child(RendererPolicy.class);
210 final RendererPolicy rendererPolicy = new RendererPolicyBuilder()
212 .setStatus(statusValue.orElse(null))
214 readWriteTransaction.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererPolicy);
215 return readWriteTransaction.submit();
219 public void close() {
223 public enum DsAction {Create, Delete}
225 public enum ActionCase {ALLOW, CHAIN}