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