[ios-xe-renderer] Increases coverage for PolicyWriterUtil
[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 javax.annotation.Nonnull;
12 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.manager.PolicyManagerImpl;
22 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
23 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
24 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
25 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
26 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
27 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
28 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
29 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
30 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
31 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
32 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
33 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
34 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
35 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
36 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
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.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;
46
47 /**
48  * Purpose: Util class for every policy writer
49  */
50 public class PolicyWriterUtil {
51
52     private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
53
54     private PolicyWriterUtil() {
55         throw new IllegalAccessError("instance of util class not supported");
56     }
57
58     public static boolean writeClassMap(@Nonnull final ClassMap classMap,
59                                         final PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
60         boolean result = true;
61         final DataBroker mountpoint = policyMapLocation.getMountpoint();
62         final NodeId nodeId = policyMapLocation.getNodeId();
63         final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
64         netconfWrite(mountpoint, classMapIid, classMap);
65         // Check
66         final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
67         if (checkCreated.isPresent()) {
68             LOG.trace("Created class-map {} on node {}", classMap.getName(), nodeId.getValue());
69         } else {
70             LOG.warn("Failed to create class-map {} on node {}", classMap.getName(), nodeId.getValue());
71             result = false;
72
73         }
74         return result;
75     }
76
77     public static boolean removeClassMap(final ClassMap classMap, final PolicyManagerImpl.PolicyMapLocation location) {
78         final DataBroker mountpoint = location.getMountpoint();
79         final NodeId nodeId = location.getNodeId();
80         boolean result = true;
81         if (classMap == null) {
82             return true;
83         }
84         final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(classMap);
85         netconfDeleteIfPresent(mountpoint, classMapIid);
86         // Check
87         final java.util.Optional<ClassMap> checkCreated = java.util.Optional.ofNullable(netconfRead(mountpoint, classMapIid));
88         if (checkCreated.isPresent()) {
89             LOG.warn("Failed to remove class-map {} on node {}", classMap.getName(), nodeId.getValue());
90             result = false;
91         } else {
92             LOG.trace("Class-map {} removed from node {}", classMap.getName(), nodeId.getValue());
93         }
94         return result;
95     }
96
97     public static boolean writePolicyMap(final PolicyMap policyMap, final PolicyManagerImpl.PolicyMapLocation location) {
98         final DataBroker mountpoint = location.getMountpoint();
99         final NodeId nodeId = location.getNodeId();
100         final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMap.getName());
101         netconfWrite(mountpoint, policyMapIid, policyMap);
102         // Check
103         if (netconfRead(mountpoint, policyMapIid) == null) {
104             LOG.warn("Failed to create policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
105             return false;
106         }
107         LOG.trace("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
108         return true;
109     }
110
111     public static boolean removePolicyMap(final PolicyManagerImpl.PolicyMapLocation location) {
112         final String policyMapName = location.getPolicyMapName();
113         final DataBroker mountpoint = location.getMountpoint();
114         final NodeId nodeId = location.getNodeId();
115         final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
116         netconfDeleteIfPresent(mountpoint, policyMapIid);
117         // Check
118         if (netconfRead(mountpoint, policyMapIid) != null) {
119             LOG.warn("Failed to remove policy-map {} from node {}", policyMapName, nodeId.getValue());
120             return false;
121         }
122         LOG.trace("Policy-map {} removed from node {}", policyMapName, nodeId.getValue());
123         return true;
124     }
125
126     public static boolean writePolicyMapEntry(final Class policyMapEntry,
127                                               final PolicyManagerImpl.PolicyMapLocation location) {
128         final String policyMapName = location.getPolicyMapName();
129         final NodeId nodeId = location.getNodeId();
130         final DataBroker mountpoint = location.getMountpoint();
131         final ClassNameType entryName = policyMapEntry.getName();
132         final InstanceIdentifier<Class> policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entryName);
133         netconfWrite(mountpoint, policyMapEntryIid, policyMapEntry);
134         // Check
135         if (netconfRead(mountpoint, policyMapEntryIid) == null) {
136             LOG.warn("Failed to create entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(),
137                     policyMapEntry);
138             return false;
139         }
140         LOG.trace("Created entry in policy-map {} on node {}. Entry: {}", policyMapName, nodeId.getValue(), policyMapEntry);
141         return true;
142     }
143
144     public static boolean removePolicyMapEntry(final Class policyMapEntry, final PolicyManagerImpl.PolicyMapLocation location) {
145         final String policyMapName = location.getPolicyMapName();
146         final DataBroker mountpoint = location.getMountpoint();
147         final NodeId nodeId = location.getNodeId();
148         if (policyMapEntry == null) {
149             return true;
150         }
151         boolean result = true;
152         final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, policyMapEntry.getName());
153         if (netconfDeleteIfPresent(mountpoint, policyMapEntryIid)) {
154             LOG.trace("Policy-map entry {} removed from node {}", policyMapEntry.getName(), nodeId.getValue());
155         } else {
156             LOG.warn("Failed to remove policy-map entry {} from node {}", policyMapEntry.getName(), nodeId.getValue());
157             result = false;
158         }
159         return result;
160     }
161
162     public static boolean writeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
163         final String policyMapName = location.getPolicyMapName();
164         final String interfaceName = location.getInterfaceName();
165         final NodeId nodeId = location.getNodeId();
166         final DataBroker mountpoint = location.getMountpoint();
167         final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
168         final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
169         if (netconfWrite(mountpoint, servicePolicyIid, servicePolicy)) {
170             LOG.trace("Service-policy interface {}, bound to policy-map {} created on  node {}",
171                     interfaceName, policyMapName, nodeId.getValue());
172             return true;
173         } else {
174             LOG.warn("Failed to write service-policy interface {} to policy-map {} on  node {}",
175                     interfaceName, policyMapName, nodeId.getValue());
176             return false;
177         }
178     }
179
180     public static boolean removeInterface(final PolicyManagerImpl.PolicyMapLocation location) {
181         final String policyMapName = location.getPolicyMapName();
182         final String interfaceName = location.getInterfaceName();
183         final DataBroker mountpoint = location.getMountpoint();
184         final NodeId nodeId = location.getNodeId();
185         final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
186         if (netconfDeleteIfPresent(mountpoint, servicePolicyIid)) {
187             LOG.trace("Service-policy interface {}, removed from node {}",
188                     interfaceName, policyMapName, nodeId.getValue());
189             return true;
190         } else {
191             LOG.warn("Failed to remove service-policy interface {} from  node {}",
192                     interfaceName, policyMapName, nodeId.getValue());
193             return false;
194         }
195     }
196
197     public static boolean writeRemote(final ServiceFfName remoteForwarder,
198                                       final PolicyManagerImpl.PolicyMapLocation location) {
199         // TODO writeNE
200         final DataBroker mountpoint = location.getMountpoint();
201         final NodeId nodeId = location.getNodeId();
202         if (remoteForwarder == null) {
203             return true;
204         }
205         boolean result = true;
206         final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
207         if (netconfWrite(mountpoint, forwarderIid, remoteForwarder)) {
208             LOG.trace("Remote forwarder {} created on node {}", remoteForwarder.getName(), nodeId.getValue());
209         } else {
210             LOG.warn("Failed to create remote forwarder {} on node {}", remoteForwarder.getName(), nodeId.getValue());
211             result = false;
212         }
213         return result;
214     }
215
216     public static boolean removeRemote(final ServiceFfName remoteForwarder, final PolicyManagerImpl.PolicyMapLocation location) {
217         final DataBroker mountpoint = location.getMountpoint();
218         final NodeId nodeId = location.getNodeId();
219         if (remoteForwarder == null) {
220             return true;
221         }
222         boolean result = true;
223         final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(remoteForwarder);
224         if (netconfDeleteIfPresent(mountpoint, forwarderIid)) {
225             LOG.trace("Remote forwarder {} removed from node {}", remoteForwarder.getName(), nodeId.getValue());
226         } else {
227             LOG.warn("Failed to remove forwarder {} from node {}", remoteForwarder.getName(), nodeId.getValue());
228             result = false;
229         }
230         return result;
231     }
232
233     public static boolean writeServicePath(final ServiceChain serviceChain,
234                                            final PolicyManagerImpl.PolicyMapLocation location) {
235         final DataBroker mountpoint = location.getMountpoint();
236         final NodeId nodeId = location.getNodeId();
237         boolean result = true;
238         for (ServicePath entry : serviceChain.getServicePath()) {
239             final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
240             if (netconfWrite(mountpoint, servicePathIid, entry)) {
241                 LOG.trace("Service-path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
242             } else {
243                 LOG.warn("Failed to create service-path with ID: {} on node {}", entry.getServicePathId(), nodeId.getValue());
244                 result = false;
245             }
246         }
247         return result;
248     }
249
250     public static boolean removeServicePath(final ServiceChain serviceChain, final PolicyManagerImpl.PolicyMapLocation location) {
251         final DataBroker mountpoint = location.getMountpoint();
252         final NodeId nodeId = location.getNodeId();
253         if (serviceChain == null) {
254             return true;
255         }
256         boolean result = true;
257         List<ServicePath> servicePaths = serviceChain.getServicePath();
258         if (servicePaths == null || servicePaths.isEmpty()) {
259             return true;
260         }
261         for (ServicePath servicePath : servicePaths) {
262             final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
263             if (netconfDeleteIfPresent(mountpoint, servicePathIid)) {
264                 LOG.trace("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
265                         nodeId.getValue());
266             } else {
267                 LOG.warn("Failed to remove service-path with ID: {} from node {}", servicePath.getServicePathId(),
268                         nodeId.getValue());
269                 result = false;
270             }
271         }
272         return result;
273     }
274
275
276     private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
277         return InstanceIdentifier.builder(Native.class)
278                 .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
279     }
280
281     public static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
282         return InstanceIdentifier.builder(Native.class)
283                 .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
284     }
285
286     private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
287                                                                               final ClassNameType classNameType) {
288         return InstanceIdentifier.builder(Native.class)
289                 .child(PolicyMap.class, new PolicyMapKey(policyMapName))
290                 .child(Class.class, new ClassKey(classNameType)).build();
291     }
292
293     public static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
294         return InstanceIdentifier.builder(Native.class)
295                 .child(Interface.class)
296                 .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
297                 .child(ServicePolicy.class)
298                 .build();
299     }
300
301     private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
302         return InstanceIdentifier.builder(Native.class)
303                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
304                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
305                 .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
306     }
307
308     private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
309         return InstanceIdentifier.builder(Native.class)
310                 .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
311                 .child(ServicePath.class, key).build();
312     }
313
314     private static <U extends DataObject> boolean netconfWrite(final DataBroker mountpoint,
315                                                                final InstanceIdentifier<U> addIID,
316                                                                final U data) {
317         // TODO consider to move netconfWrite, netconfDeleteIfPresent and netconfRead methods (+ methods in NetconfTransactionCreator) to gbp base
318         final java.util.Optional<WriteTransaction> optionalWriteTransaction =
319                 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
320         if (!optionalWriteTransaction.isPresent()) {
321             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
322             return false;
323         }
324         final WriteTransaction transaction = optionalWriteTransaction.get();
325         try {
326             transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
327             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
328             submitFuture.checkedGet();
329             return true;
330         } catch (TransactionCommitFailedException e) {
331             LOG.error("Write transaction failed to {}", e.getMessage());
332         } catch (Exception e) {
333             LOG.error("Failed to .. {}", e.getMessage());
334         }
335         return false;
336     }
337
338     private static <U extends DataObject> boolean netconfDeleteIfPresent(final DataBroker mountpoint,
339                                                                          final InstanceIdentifier<U> deleteIID) {
340         if (netconfRead(mountpoint, deleteIID) == null) {
341             LOG.trace("Remove action called on non-existing element, skipping. Iid was: {}, data provider: {} ",
342                     deleteIID, mountpoint);
343             return true;
344         }
345         final java.util.Optional<WriteTransaction> optionalWriteTransaction =
346                 NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
347         if (!optionalWriteTransaction.isPresent()) {
348             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
349             return false;
350         }
351         final WriteTransaction transaction = optionalWriteTransaction.get();
352         try {
353             transaction.delete(LogicalDatastoreType.CONFIGURATION, deleteIID);
354             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
355             submitFuture.checkedGet();
356             return true;
357         } catch (TransactionCommitFailedException e) {
358             LOG.error("Write transaction failed to {}", e.getMessage());
359         } catch (Exception e) {
360             LOG.error("Failed to .. {}", e.getMessage());
361         }
362         return false;
363     }
364
365     public static <U extends DataObject> U netconfRead(final DataBroker mountpoint,
366                                                        final InstanceIdentifier<U> readIID) {
367         final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
368                 NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
369         if (!optionalReadTransaction.isPresent()) {
370             LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
371             return null;
372         }
373         final ReadOnlyTransaction transaction = optionalReadTransaction.get();
374         try {
375             final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
376                     transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
377             final Optional<U> optional = submitFuture.checkedGet();
378             if (optional != null && optional.isPresent()) {
379                 transaction.close(); // Release lock
380                 return optional.get();
381             }
382         } catch (ReadFailedException e) {
383             LOG.warn("Read transaction failed to {} ", e);
384         } catch (Exception e) {
385             LOG.error("Failed to .. {}", e.getMessage());
386         }
387
388         return null;
389     }
390 }