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.writer;
11 import java.util.List;
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.CheckedFuture;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
22 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
23 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
24 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
25 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
26 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
27 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
28 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
29 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
30 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
31 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
32 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
33 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
34 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
35 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
36 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder;
37 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
38 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
40 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
41 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * Purpose: Util class for every policy writer
51 class PolicyWriterUtil {
53 private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
55 static boolean writeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
56 if (classMapEntries == null || classMapEntries.isEmpty()) {
59 for (ClassMap entry : classMapEntries) {
60 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
61 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
62 if (!optionalWriteTransaction.isPresent()) {
63 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
66 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
67 final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
68 writeMergeTransaction(writeTransaction, classMapIid, entry);
70 final java.util.Optional<ReadOnlyTransaction> optionalTransaction =
71 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
72 if (!optionalTransaction.isPresent()) {
73 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
76 final ReadOnlyTransaction readTransaction = optionalTransaction.get();
77 if (checkWritten(readTransaction, classMapIid) == null) {
80 LOG.info("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
85 static boolean removeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
86 boolean result = true;
87 if (classMapEntries == null || classMapEntries.isEmpty()) {
90 for (ClassMap entry : classMapEntries) {
91 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
92 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
93 if (!optionalWriteTransaction.isPresent()) {
94 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
97 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
98 final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
99 deleteTransaction(writeTransaction, classMapIid);
101 final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
102 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
103 if (!optionalReadTransaction.isPresent()) {
104 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
107 final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
108 result = checkRemoved(readTransaction, classMapIid);
109 LOG.info("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
114 static boolean writePolicyMap(final String policyMapName, final Set<Class> policyMapEntries, NodeId nodeId,
115 final DataBroker mountpoint) {
116 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
117 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
118 if (!optionalWriteTransaction.isPresent()) {
119 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
122 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
123 final PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
124 final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
125 writeMergeTransaction(writeTransaction, policyMapIid, policyMap);
127 final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
128 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
129 if (!optionalReadTransaction.isPresent()) {
130 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
133 final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
134 if (checkWritten(readTransaction, policyMapIid) == null) {
137 LOG.info("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
141 static boolean removePolicyMapEntries(final String policyMapName, final Set<Class> policyMapEntries,
142 final NodeId nodeId, final DataBroker mountpoint) {
143 if (policyMapEntries == null || policyMapEntries.isEmpty()) {
146 for (Class entry : policyMapEntries) {
147 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
148 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
149 if (!optionalWriteTransaction.isPresent()) {
150 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
153 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
154 final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entry.getName());
155 if (deleteTransaction(writeTransaction, policyMapEntryIid)) {
156 LOG.info("Policy map entry {} removed from node {}", entry.getName(), nodeId.getValue());
162 static boolean writeInterface(final String policyMapName, final String interfaceName, final NodeId nodeId,
163 final DataBroker mountpoint) {
164 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
165 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
166 if (!optionalWriteTransaction.isPresent()) {
167 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
170 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
171 final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
172 final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
173 writeMergeTransaction(writeTransaction, servicePolicyIid, servicePolicy);
174 LOG.info("Service-policy interface {}, bound to policy-map {} created on node {}",
175 interfaceName, policyMapName, nodeId.getValue());
179 static boolean writeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
180 final DataBroker mountpoint) {
181 if (remoteForwarders == null || remoteForwarders.isEmpty()) {
184 for (ServiceFfName forwarder : remoteForwarders) {
185 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
186 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
187 if (!optionalWriteTransaction.isPresent()) {
188 LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
191 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
192 final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
193 writeMergeTransaction(writeTransaction, forwarderIid, forwarder);
194 LOG.info("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
199 static boolean removeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
200 final DataBroker mountpoint) {
201 if (remoteForwarders == null || remoteForwarders.isEmpty()) {
204 for (ServiceFfName forwarder : remoteForwarders) {
205 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
206 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
207 if (!optionalWriteTransaction.isPresent()) {
208 LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
211 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
212 final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
213 deleteTransaction(writeTransaction, forwarderIid);
214 LOG.info("Remote forwarder {} removed from node {}", forwarder.getName(), nodeId.getValue());
219 static boolean writeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
220 final DataBroker mountpoint) {
221 for (org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain serviceChain : serviceChains) {
222 for (ServicePath entry : serviceChain.getServicePath()) {
223 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
224 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
225 if (!optionalWriteTransaction.isPresent()) {
226 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
229 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
230 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
231 writeMergeTransaction(writeTransaction, servicePathIid, entry);
232 LOG.info("Service path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
238 static boolean removeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
239 final DataBroker mountpoint) {
240 if (serviceChains == null || serviceChains.isEmpty()) {
243 for (ServiceChain chain : serviceChains) {
244 List<ServicePath> servicePaths = chain.getServicePath();
245 if (servicePaths == null || servicePaths.isEmpty()) {
248 for (ServicePath servicePath : servicePaths) {
249 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
250 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
251 if (!optionalWriteTransaction.isPresent()) {
252 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
255 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
256 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
257 if (deleteTransaction(writeTransaction, servicePathIid)) {
258 LOG.info("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
266 private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
267 return InstanceIdentifier.builder(Native.class)
268 .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
271 private static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
272 return InstanceIdentifier.builder(Native.class)
273 .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
276 private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
277 final ClassNameType classNameType) {
278 return InstanceIdentifier.builder(Native.class)
279 .child(PolicyMap.class, new PolicyMapKey(policyMapName))
280 .child(Class.class, new ClassKey(classNameType)).build();
283 private static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
284 return InstanceIdentifier.builder(Native.class)
285 .child(Interface.class)
286 .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
287 .child(ServicePolicy.class)
291 private static InstanceIdentifier<Local> localSffInstanceIdentifier() {
292 return InstanceIdentifier.builder(Native.class)
293 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
294 .child(ServiceFunctionForwarder.class)
295 .child(Local.class).build();
298 private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
299 return InstanceIdentifier.builder(Native.class)
300 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
301 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
302 .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
305 private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
306 return InstanceIdentifier.builder(Native.class)
307 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
308 .child(ServicePath.class, key).build();
311 private static <U extends DataObject> void writeMergeTransaction(final WriteTransaction transaction,
312 final InstanceIdentifier<U> addIID,
315 transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
316 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
317 submitFuture.checkedGet();
318 } catch (TransactionCommitFailedException e) {
319 LOG.error("Write transaction failed to {}", e.getMessage());
320 } catch (Exception e) {
321 LOG.error("Failed to .. {}", e.getMessage());
325 private static <U extends DataObject> boolean deleteTransaction(final WriteTransaction transaction,
326 final InstanceIdentifier<U> addIID) {
328 transaction.delete(LogicalDatastoreType.CONFIGURATION, addIID);
329 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
330 submitFuture.checkedGet();
332 } catch (TransactionCommitFailedException e) {
333 LOG.error("Write transaction failed to {}", e.getMessage());
335 } catch (Exception e) {
336 LOG.error("Failed to .. {}", e.getMessage());
341 private static <U extends DataObject> U checkWritten(final ReadOnlyTransaction transaction,
342 final InstanceIdentifier<U> readIID) {
343 for (int attempt = 1; attempt <= 5; attempt++) {
345 final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
346 transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
347 final Optional<U> optional = submitFuture.checkedGet();
348 if (optional != null && optional.isPresent()) {
349 transaction.close(); // Release lock
350 return optional.get();
352 // Could take some time until specific configuration appears on device, try to read a few times
355 } catch (InterruptedException i) {
356 LOG.error("Thread interrupted while waiting ... {} ", i);
357 } catch (ReadFailedException e) {
358 LOG.warn("Read transaction failed to {} ", e);
359 } catch (Exception e) {
360 LOG.error("Failed to .. {}", e.getMessage());
366 private static <U extends DataObject> boolean checkRemoved(final ReadOnlyTransaction transaction,
367 final InstanceIdentifier<U> readIID) {
368 for (int attempt = 1; attempt <= 5; attempt++) {
370 final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
371 transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
372 final Optional<U> optional = submitFuture.checkedGet();
373 if (optional != null && optional.isPresent()) {
374 // Could take some time until specific configuration is removed from the device
377 transaction.close(); // Release lock
380 } catch (InterruptedException i) {
381 LOG.error("Thread interrupted while waiting ... {} ", i);
382 } catch (ReadFailedException e) {
383 LOG.warn("Read transaction failed to {} ", e);
384 } catch (Exception e) {
385 LOG.error("Failed to .. {}", e.getMessage());