ios-xe - check existence of element before removing it
[groupbasedpolicy.git] / renderers / ios-xe / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ios_xe_provider / impl / writer / PolicyWriterUtil.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.writer;
10
11 import java.util.List;
12 import java.util.Set;
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.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.ServiceFfName;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * Purpose: Util class for every policy writer
48  */
49 class PolicyWriterUtil {
50
51     private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
52
53     static boolean writeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
54         boolean result = true;
55         if (classMapEntries == null || classMapEntries.isEmpty()) {
56             return true;
57         }
58         for (ClassMap entry : classMapEntries) {
59             final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
60             netconfWrite(mountpoint, classMapIid, entry);
61             // Check
62             final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
63             if (checkCreated.isPresent()) {
64                 LOG.trace("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
65             }
66             else {
67                 LOG.warn("Failed to create class-map {} on node {}", entry.getName(), nodeId.getValue());
68                 result = false;
69             }
70         }
71         return result;
72     }
73
74     static boolean removeClassMaps(final Set<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
75         boolean result = true;
76         if (classMapEntries == null || classMapEntries.isEmpty()) {
77             return true;
78         }
79         for (ClassMap entry : classMapEntries) {
80             final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
81             netconfDeleteIfPresent(mountpoint, classMapIid);
82             // Check
83             final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
84             if (checkCreated.isPresent()) {
85                 LOG.warn("Failed to remove class-map {} on node {}", entry.getName(), nodeId.getValue());
86                 result = false;
87             }
88             else {
89                 LOG.trace("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
90             }
91         }
92         return result;
93     }
94
95     static boolean writePolicyMap(final String policyMapName, final Set<Class> policyMapEntries, NodeId nodeId,
96                                   final DataBroker mountpoint) {
97         final PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
98         final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
99         netconfWrite(mountpoint, policyMapIid, policyMap);
100         // Check
101         if (netconfRead(mountpoint, policyMapIid) == null) {
102             LOG.warn("Failed to create policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
103             return false;
104         }
105         LOG.trace("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
106         return true;
107     }
108
109     static boolean removePolicyMapEntries(final String policyMapName, final Set<Class> policyMapEntries,
110                                           final NodeId nodeId, final DataBroker mountpoint) {
111         if (policyMapEntries == null || policyMapEntries.isEmpty()) {
112             return true;
113         }
114         boolean result = true;
115         for (Class entry : policyMapEntries) {
116             final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entry.getName());
117             if (netconfDeleteIfPresent(mountpoint, policyMapEntryIid)) {
118                 LOG.trace("Policy-map entry {} removed from node {}", entry.getName(), nodeId.getValue());
119             }
120             else {
121                 LOG.warn("Failed to remove policy-map entry {} from node {}", entry.getName(), nodeId.getValue());
122                 result = false;
123             }
124         }
125         return result;
126     }
127
128     static boolean writeInterface(final String policyMapName, final String interfaceName, final NodeId nodeId,
129                                   final DataBroker mountpoint) {
130         final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
131         final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
132         if (netconfWrite(mountpoint, servicePolicyIid, servicePolicy)) {
133             LOG.trace("Service-policy interface {}, bound to policy-map {} created on  node {}",
134                     interfaceName, policyMapName, nodeId.getValue());
135             return true;
136         }
137         else {
138             LOG.warn("Failed to write service-policy interface {} to policy-map {} on  node {}",
139                     interfaceName, policyMapName, nodeId.getValue());
140             return false;
141         }
142     }
143
144     static boolean writeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
145                                final DataBroker mountpoint) {
146         if (remoteForwarders == null || remoteForwarders.isEmpty()) {
147             return true;
148         }
149         boolean result = true;
150         for (ServiceFfName forwarder : remoteForwarders) {
151             final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
152             if (netconfWrite(mountpoint, forwarderIid, forwarder)) {
153                 LOG.trace("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
154             }
155             else {
156                 LOG.warn("Failed to create remote forwarder {} on node {}", forwarder.getName(), nodeId.getValue());
157                 result = false;
158             }
159         }
160         return result;
161     }
162
163     static boolean removeRemote(final Set<ServiceFfName> remoteForwarders, final NodeId nodeId,
164                                 final DataBroker mountpoint) {
165         if (remoteForwarders == null || remoteForwarders.isEmpty()) {
166             return true;
167         }
168         boolean result = true;
169         for (ServiceFfName forwarder : remoteForwarders) {
170             final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
171             if (netconfDeleteIfPresent(mountpoint, forwarderIid)) {
172                 LOG.trace("Remote forwarder {} removed from node {}", forwarder.getName(), nodeId.getValue());
173             }
174             else {
175                 LOG.warn("Failed to remove forwarder {} from node {}", forwarder.getName(), nodeId.getValue());
176                 result = false;
177             }
178         }
179         return result;
180     }
181
182     static boolean writeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
183                                      final DataBroker mountpoint) {
184         boolean result = true;
185         for (org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain serviceChain : serviceChains) {
186             for (ServicePath entry : serviceChain.getServicePath()) {
187                 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
188                 if (netconfWrite(mountpoint, servicePathIid, entry)) {
189                     LOG.trace("Service-path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
190                 }
191                 else {
192                     LOG.warn("Failed to create service-path with ID: {} on node {}", entry.getServicePathId(), nodeId.getValue());
193                     result = false;
194                 }
195             }
196         }
197         return result;
198     }
199
200     static boolean removeServicePaths(final Set<ServiceChain> serviceChains, final NodeId nodeId,
201                                       final DataBroker mountpoint) {
202         if (serviceChains == null || serviceChains.isEmpty()) {
203             return true;
204         }
205         boolean result = true;
206         for (ServiceChain chain : serviceChains) {
207             List<ServicePath> servicePaths = chain.getServicePath();
208             if (servicePaths == null || servicePaths.isEmpty()) {
209                 continue;
210             }
211             for (ServicePath servicePath : servicePaths) {
212                 final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
213                 if (netconfDeleteIfPresent(mountpoint, servicePathIid)) {
214                     LOG.trace("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
215                             nodeId.getValue());
216                 }
217                 else {
218                     LOG.warn("Failed to remove service-path with ID: {} from node {}", servicePath.getServicePathId(),
219                             nodeId.getValue());
220                     result = false;
221                 }
222             }
223         }
224         return result;
225     }
226
227     private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
228         return InstanceIdentifier.builder(Native.class)
229                 .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
230     }
231
232     private static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
233         return InstanceIdentifier.builder(Native.class)
234                 .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
235     }
236
237     private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
238                                                                               final ClassNameType classNameType) {
239         return InstanceIdentifier.builder(Native.class)
240                 .child(PolicyMap.class, new PolicyMapKey(policyMapName))
241                 .child(Class.class, new ClassKey(classNameType)).build();
242     }
243
244     private static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
245         return InstanceIdentifier.builder(Native.class)
246                 .child(Interface.class)
247                 .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
248                 .child(ServicePolicy.class)
249                 .build();
250     }
251
252     private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
253         return InstanceIdentifier.builder(Native.class)
254                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
255                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
256                 .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
257     }
258
259     private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
260         return InstanceIdentifier.builder(Native.class)
261                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
262                 .child(ServicePath.class, key).build();
263     }
264
265     private static <U extends DataObject> boolean netconfWrite(final DataBroker mountpoint,
266                                                             final InstanceIdentifier<U> addIID,
267                                                             final U data) {
268         final java.util.Optional<WriteTransaction> optionalWriteTransaction =
269                 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
270         if (!optionalWriteTransaction.isPresent()) {
271             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
272             return false;
273         }
274         final WriteTransaction transaction = optionalWriteTransaction.get();
275         try {
276             transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
277             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
278             submitFuture.checkedGet();
279             return true;
280         } catch (TransactionCommitFailedException e) {
281             LOG.error("Write transaction failed to {}", e.getMessage());
282         } catch (Exception e) {
283             LOG.error("Failed to .. {}", e.getMessage());
284         }
285         return false;
286     }
287
288     private static <U extends DataObject> boolean netconfDeleteIfPresent(final DataBroker mountpoint,
289                                                                          final InstanceIdentifier<U> deleteIID) {
290         if (netconfRead(mountpoint, deleteIID) == null) {
291             LOG.trace("Remove action called on non-existing element, skipping. Iid was: {}, data provider: {} ",
292                     deleteIID, mountpoint);
293             return true;
294         }
295         final java.util.Optional<WriteTransaction> optionalWriteTransaction =
296                 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
297         if (!optionalWriteTransaction.isPresent()) {
298             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
299             return false;
300         }
301         final WriteTransaction transaction = optionalWriteTransaction.get();
302         try {
303             transaction.delete(LogicalDatastoreType.CONFIGURATION, deleteIID);
304             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
305             submitFuture.checkedGet();
306             return true;
307         } catch (TransactionCommitFailedException e) {
308             LOG.error("Write transaction failed to {}", e.getMessage());
309         } catch (Exception e) {
310             LOG.error("Failed to .. {}", e.getMessage());
311         }
312         return false;
313     }
314
315     private static <U extends DataObject> U netconfRead(final DataBroker mountpoint,
316                                                         final InstanceIdentifier<U> readIID) {
317         final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
318                 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
319         if (!optionalReadTransaction.isPresent()) {
320             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
321             return null;
322         }
323         final ReadOnlyTransaction transaction = optionalReadTransaction.get();
324         try {
325             final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
326                     transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
327             final Optional<U> optional = submitFuture.checkedGet();
328             if (optional != null && optional.isPresent()) {
329                 transaction.close(); // Release lock
330                 return optional.get();
331             }
332         } catch (ReadFailedException e) {
333             LOG.warn("Read transaction failed to {} ", e);
334         } catch (Exception e) {
335             LOG.error("Failed to .. {}", e.getMessage());
336         }
337
338         return null;
339     }
340 }