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 com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
15 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
19 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
20 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
21 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
22 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
23 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
24 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
25 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
26 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
27 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
28 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
29 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
30 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
31 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
32 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
33 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
34 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
35 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder;
36 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
37 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
38 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
40 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
42 import org.opendaylight.yangtools.yang.binding.DataObject;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 import java.util.List;
50 * Purpose: Util class for every policy writer
52 class PolicyWriterUtil {
54 private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
56 static boolean writeClassMaps(final List<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
57 if (classMapEntries == null || classMapEntries.isEmpty()) {
60 for (ClassMap entry : classMapEntries) {
61 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
62 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
63 if (!optionalWriteTransaction.isPresent()) {
64 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
67 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
68 final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
69 writeMergeTransaction(writeTransaction, classMapIid, entry);
71 final java.util.Optional<ReadOnlyTransaction> optionalTransaction =
72 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
73 if (!optionalTransaction.isPresent()) {
74 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
77 final ReadOnlyTransaction readTransaction = optionalTransaction.get();
78 if (checkWritten(readTransaction, classMapIid) == null) {
81 LOG.info("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
86 static boolean removeClassMaps(final List<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
87 boolean result = true;
88 if (classMapEntries == null || classMapEntries.isEmpty()) {
91 for (ClassMap entry : classMapEntries) {
92 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
93 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
94 if (!optionalWriteTransaction.isPresent()) {
95 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
98 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
99 final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
100 deleteTransaction(writeTransaction, classMapIid);
102 final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
103 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
104 if (!optionalReadTransaction.isPresent()) {
105 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
108 final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
109 result = checkRemoved(readTransaction, classMapIid);
110 LOG.info("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
115 static boolean writePolicyMap(final String policyMapName, final List<Class> policyMapEntries, NodeId nodeId,
116 final DataBroker mountpoint) {
117 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
118 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
119 if (!optionalWriteTransaction.isPresent()) {
120 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
123 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
124 final PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
125 final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
126 writeMergeTransaction(writeTransaction, policyMapIid, policyMap);
128 final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
129 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
130 if (!optionalReadTransaction.isPresent()) {
131 LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
134 final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
135 if (checkWritten(readTransaction, policyMapIid) == null) {
138 LOG.info("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
142 static boolean removePolicyMapEntries(final String policyMapName, final List<Class> policyMapEntries,
143 final NodeId nodeId, final DataBroker mountpoint) {
144 if (policyMapEntries == null || policyMapEntries.isEmpty()) {
147 for (Class entry : policyMapEntries) {
148 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
149 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
150 if (!optionalWriteTransaction.isPresent()) {
151 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
154 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
155 final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entry.getName());
156 if (deleteTransaction(writeTransaction, policyMapEntryIid)) {
157 LOG.info("Policy map entry {} removed from node {}", entry.getName(), nodeId.getValue());
163 static boolean writeInterface(final String policyMapName, final String interfaceName, final NodeId nodeId,
164 final DataBroker mountpoint) {
165 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
166 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
167 if (!optionalWriteTransaction.isPresent()) {
168 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
171 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
172 final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
173 final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
174 writeMergeTransaction(writeTransaction, servicePolicyIid, servicePolicy);
175 LOG.info("Service-policy interface {}, bound to policy-map {} created on node {}",
176 interfaceName, policyMapName, nodeId.getValue());
180 static boolean writeLocal(final Local localForwarder, final NodeId nodeId, final DataBroker mountpoint) {
181 if (localForwarder == null) {
184 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
185 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
186 if (!optionalWriteTransaction.isPresent()) {
187 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
190 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
191 final InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
192 writeMergeTransaction(writeTransaction, localIid, localForwarder);
193 LOG.info("Local forwarder created on node {}", nodeId.getValue());
197 static boolean removeLocal(final NodeId nodeId, final DataBroker mountpoint) {
198 // Remove local forwarder only when there are no more service-paths
199 if (ServiceChainingUtil.checkServicePathPresence(mountpoint)) {
200 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
201 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
202 if (!optionalWriteTransaction.isPresent()) {
203 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
206 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
207 final InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
208 deleteTransaction(writeTransaction, localIid);
209 LOG.info("Local forwarder removed from node {}", nodeId.getValue());
214 static boolean writeRemote(final List<ServiceFfName> remoteForwarders, final NodeId nodeId,
215 final DataBroker mountpoint) {
216 if (remoteForwarders == null || remoteForwarders.isEmpty()) {
219 for (ServiceFfName forwarder : remoteForwarders) {
220 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
221 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
222 if (!optionalWriteTransaction.isPresent()) {
223 LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
226 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
227 final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
228 writeMergeTransaction(writeTransaction, forwarderIid, forwarder);
229 LOG.info("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
234 static boolean writeServicePaths(final List<ServiceChain> serviceChains, final NodeId nodeId,
235 final DataBroker mountpoint) {
236 for (org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain serviceChain : serviceChains) {
237 for (ServicePath entry : serviceChain.getServicePath()) {
238 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
239 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
240 if (!optionalWriteTransaction.isPresent()) {
241 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
244 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
245 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
246 writeMergeTransaction(writeTransaction, servicePathIid, entry);
247 LOG.info("Service path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
253 static boolean removeServicePaths(final List<ServiceChain> serviceChains, final NodeId nodeId,
254 final DataBroker mountpoint) {
255 if (serviceChains == null || serviceChains.isEmpty()) {
258 for (ServiceChain chain : serviceChains) {
259 List<ServicePath> servicePaths = chain.getServicePath();
260 if (servicePaths == null || servicePaths.isEmpty()) {
263 for (ServicePath servicePath : servicePaths) {
264 final java.util.Optional<WriteTransaction> optionalWriteTransaction =
265 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
266 if (!optionalWriteTransaction.isPresent()) {
267 LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
270 final WriteTransaction writeTransaction = optionalWriteTransaction.get();
271 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
272 if (deleteTransaction(writeTransaction, servicePathIid)) {
273 LOG.info("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
281 private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
282 return InstanceIdentifier.builder(Native.class)
283 .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
286 private static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
287 return InstanceIdentifier.builder(Native.class)
288 .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
291 private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
292 final ClassNameType classNameType) {
293 return InstanceIdentifier.builder(Native.class)
294 .child(PolicyMap.class, new PolicyMapKey(policyMapName))
295 .child(Class.class, new ClassKey(classNameType)).build();
298 private static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
299 return InstanceIdentifier.builder(Native.class)
300 .child(Interface.class)
301 .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
302 .child(ServicePolicy.class)
306 private static InstanceIdentifier<Local> localSffInstanceIdentifier() {
307 return InstanceIdentifier.builder(Native.class)
308 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
309 .child(ServiceFunctionForwarder.class)
310 .child(Local.class).build();
313 private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
314 return InstanceIdentifier.builder(Native.class)
315 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
316 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
317 .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
320 private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
321 return InstanceIdentifier.builder(Native.class)
322 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
323 .child(ServicePath.class, key).build();
326 private static <U extends DataObject> void writeMergeTransaction(final WriteTransaction transaction,
327 final InstanceIdentifier<U> addIID,
330 transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
331 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
332 submitFuture.checkedGet();
333 } catch (TransactionCommitFailedException e) {
334 LOG.error("Write transaction failed to {}", e.getMessage());
335 } catch (Exception e) {
336 LOG.error("Failed to .. {}", e.getMessage());
340 private static <U extends DataObject> boolean deleteTransaction(final WriteTransaction transaction,
341 final InstanceIdentifier<U> addIID) {
343 transaction.delete(LogicalDatastoreType.CONFIGURATION, addIID);
344 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
345 submitFuture.checkedGet();
347 } catch (TransactionCommitFailedException e) {
348 LOG.error("Write transaction failed to {}", e.getMessage());
350 } catch (Exception e) {
351 LOG.error("Failed to .. {}", e.getMessage());
356 private static <U extends DataObject> U checkWritten(final ReadOnlyTransaction transaction,
357 final InstanceIdentifier<U> readIID) {
358 for (int attempt = 1; attempt <= 5; attempt++) {
360 final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
361 transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
362 final Optional<U> optional = submitFuture.checkedGet();
363 if (optional != null && optional.isPresent()) {
364 transaction.close(); // Release lock
365 return optional.get();
367 // Could take some time until specific configuration appears on device, try to read a few times
370 } catch (InterruptedException i) {
371 LOG.error("Thread interrupted while waiting ... {} ", i);
372 } catch (ReadFailedException e) {
373 LOG.warn("Read transaction failed to {} ", e);
374 } catch (Exception e) {
375 LOG.error("Failed to .. {}", e.getMessage());
381 private static <U extends DataObject> boolean checkRemoved(final ReadOnlyTransaction transaction,
382 final InstanceIdentifier<U> readIID) {
383 for (int attempt = 1; attempt <= 5; attempt++) {
385 final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
386 transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
387 final Optional<U> optional = submitFuture.checkedGet();
388 if (optional != null && optional.isPresent()) {
389 // Could take some time until specific configuration is removed from the device
392 transaction.close(); // Release lock
395 } catch (InterruptedException i) {
396 LOG.error("Thread interrupted while waiting ... {} ", i);
397 } catch (ReadFailedException e) {
398 LOG.warn("Read transaction failed to {} ", e);
399 } catch (Exception e) {
400 LOG.error("Failed to .. {}", e.getMessage());