71d60ca8647cfecc0b2288a8d57bc23c2e9b5ed4
[vtn.git] /
1 /*
2  * Copyright (c) 2015 NEC Corporation. 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.vtn.manager.internal.util.flow.cond;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Set;
15
16 import com.google.common.base.Optional;
17
18 import org.opendaylight.vtn.manager.VTNException;
19
20 import org.opendaylight.vtn.manager.internal.util.DataStoreUtils;
21 import org.opendaylight.vtn.manager.internal.util.MiscUtils;
22 import org.opendaylight.vtn.manager.internal.util.rpc.RpcErrorTag;
23 import org.opendaylight.vtn.manager.internal.util.rpc.RpcException;
24
25 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.VtnFlowConditions;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.vtn.flow.cond.config.VtnFlowMatch;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.vtn.flow.cond.config.VtnFlowMatchBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.vtn.flow.cond.config.VtnFlowMatchKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.vtn.flow.conditions.VtnFlowCondition;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.cond.rev150313.vtn.flow.conditions.VtnFlowConditionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeName;
37
38 /**
39  * {@code FlowCondUtils} class is a collection of utility class methods
40  * for flow condition.
41  */
42 public final class FlowCondUtils {
43     /**
44      * A brief description about flow condition.
45      */
46     private static final String  DESC_FLOW_COND = "Flow condition";
47
48     /**
49      * Private constructor that protects this class from instantiating.
50      */
51     private FlowCondUtils() {}
52
53     /**
54      * Return a new {@link RpcException} that indicates the specified flow
55      * condition is not present.
56      *
57      * @param name  The name of the flow condition.
58      * @return  An {@link RpcException}.
59      */
60     public static RpcException getNotFoundException(String name) {
61         return getNotFoundException(name, null);
62     }
63
64     /**
65      * Return a new {@link RpcException} that indicates the specified flow
66      * condition is not present.
67      *
68      * @param name   The name of the flow condition.
69      * @param cause  A {@link Throwable} which indicates the cause of error.
70      * @return  An {@link RpcException}.
71      */
72     public static RpcException getNotFoundException(String name,
73                                                     Throwable cause) {
74         String msg =
75             MiscUtils.joinColon(name, "Flow condition does not exist.");
76         return RpcException.getNotFoundException(msg, cause);
77     }
78
79     /**
80      * Return a new {@link RpcException} that indicates the flow match index
81      * is missing.
82      *
83      * @return  An {@link RpcException}.
84      */
85     public static RpcException getMatchIndexMissingException() {
86         return RpcException.getNullArgumentException("Match index");
87     }
88
89     /**
90      * Verify the name of the flow condition.
91      *
92      * @param name  The name of the flow condition.
93      * @return  A {@link VnodeName} instance that contains the given name.
94      * @throws RpcException  The specified name is invalid.
95      */
96     public static VnodeName checkName(String name) throws RpcException {
97         return MiscUtils.checkName(DESC_FLOW_COND, name);
98     }
99
100     /**
101      * Verify the name of the flow condition.
102      *
103      * @param vname  A {@link VnodeName} instance.
104      * @return  Return the string in {@code vname}.
105      * @throws RpcException  The specified name is invalid.
106      */
107     public static String checkName(VnodeName vname) throws RpcException {
108         return MiscUtils.checkName(DESC_FLOW_COND, vname);
109     }
110
111     /**
112      * Ensure the given vnode-name is not null.
113      *
114      * @param vname  A {@link VnodeName} instance.
115      * @throws RpcException  {@code vname} is {@code null}.
116      */
117     public static void checkPresent(VnodeName vname) throws RpcException {
118         MiscUtils.checkPresent(DESC_FLOW_COND, vname);
119     }
120
121     /**
122      * Create the instance identifier for the flow condition specified by the
123      * given name.
124      *
125      * <p>
126      *   This method is used to retrieve existing flow condition.
127      * </p>
128      *
129      * @param name  The name of the flow condition.
130      * @return  An {@link InstanceIdentifier} instance.
131      * @throws RpcException
132      *    The given flow condition name is invalid.
133      */
134     public static InstanceIdentifier<VtnFlowCondition> getIdentifier(
135         String name) throws RpcException {
136         return getIdentifier(getVnodeName(name));
137     }
138
139     /**
140      * Create the instance identifier for the flow condition specified by the
141      * given name.
142      *
143      * @param vname  A {@link VnodeName} instance that contains the name of
144      *               the flow condition.
145      * @return  An {@link InstanceIdentifier} instance.
146      */
147     public static InstanceIdentifier<VtnFlowCondition> getIdentifier(
148         VnodeName vname) {
149         return InstanceIdentifier.builder(VtnFlowConditions.class).
150             child(VtnFlowCondition.class, new VtnFlowConditionKey(vname)).
151             build();
152     }
153
154     /**
155      * Create the instance identifier for the flow match specified by the
156      * given flow condition name and match index.
157      *
158      * <p>
159      *   This method is used to retrieve flow match in existing flow condition.
160      * </p>
161      *
162      * @param name   The name of the flow condition.
163      * @param index  The index assigned to the flow match in a flow condition.
164      * @return  An {@link InstanceIdentifier} instance.
165      * @throws RpcException
166      *    The given flow condition name or match index is invalid.
167      */
168     public static InstanceIdentifier<VtnFlowMatch> getIdentifier(
169         String name, Integer index) throws RpcException {
170         return getIdentifier(getVnodeName(name), index);
171     }
172
173     /**
174      * Create the instance identifier for the flow match specified by the
175      * given flow condition name and match index.
176      *
177      * <p>
178      *   This method is used to retrieve flow match in existing flow condition.
179      * </p>
180      *
181      * @param vname  A {@link VnodeName} instance that contains the name of
182      *               the flow condition.
183      * @param index  The index assigned to the flow match in a flow condition.
184      * @return  An {@link InstanceIdentifier} instance.
185      * @throws RpcException
186      *    The given flow condition name or match index is invalid.
187      */
188     public static InstanceIdentifier<VtnFlowMatch> getIdentifier(
189         VnodeName vname, Integer index) throws RpcException {
190         if (index == null) {
191             throw getMatchIndexMissingException();
192         }
193
194         return InstanceIdentifier.builder(VtnFlowConditions.class).
195             child(VtnFlowCondition.class, new VtnFlowConditionKey(vname)).
196             child(VtnFlowMatch.class, new VtnFlowMatchKey(index)).build();
197     }
198
199     /**
200      * Return a {@link VnodeName} instance that contains the given flow
201      * condition name.
202      *
203      * <p>
204      *   This method is used to retrieve existing flow condition.
205      * </p>
206      *
207      * @param name  The name of the flow condition.
208      * @return  A {@link VnodeName} instance that contains the given name.
209      * @throws RpcException  The specified name is invalid.
210      */
211     public static VnodeName getVnodeName(String name) throws RpcException {
212         try {
213             return MiscUtils.checkName(DESC_FLOW_COND, name);
214         } catch (RpcException e) {
215             if (e.getErrorTag() == RpcErrorTag.BAD_ELEMENT) {
216                 // The specified flow condition should not be present because
217                 // the given name is invalid.
218                 throw getNotFoundException(name, e);
219             }
220             throw e;
221         }
222     }
223
224     /**
225      * Return the name of the flow condition configured in the given
226      * instance identifier.
227      *
228      * @param path  An {@link InstanceIdentifier} instance.
229      * @return  The name of the flow condition if found.
230      *          {@code null} if not found.
231      */
232     public static String getName(InstanceIdentifier<?> path) {
233         VtnFlowConditionKey key = path.firstKeyOf(VtnFlowCondition.class);
234         if (key == null) {
235             return null;
236         }
237
238         VnodeName vname = key.getName();
239         return (vname == null) ? null : vname.getValue();
240     }
241
242     /**
243      * Ensure that there is no duplicate match index in the match list.
244      *
245      * @param set    A set of match indices.
246      * @param index  An index to be tested.
247      * @throws RpcException   An error occurred.
248      */
249     public static void verifyMatchIndex(Set<Integer> set, Integer index)
250         throws RpcException {
251         if (!set.add(index)) {
252             String msg = "Duplicate match index: " + index;
253             throw RpcException.getBadArgumentException(msg);
254         }
255     }
256
257     /**
258      * Verify the given index number for a flow match in a flow condition.
259      *
260      * @param index  A match index to be verified.
261      * @throws RpcException
262      *    The given match index is invalid.
263      */
264     public static void verifyMatchIndex(Integer index) throws RpcException {
265         if (index == null) {
266             throw getMatchIndexMissingException();
267         }
268
269         try {
270             new VtnFlowMatchBuilder().setIndex(index);
271         } catch (RuntimeException e) {
272             String msg = "Invalid match index: " + index;
273             throw RpcException.getBadArgumentException(msg, e);
274         }
275     }
276
277     /**
278      * Determine whether the given flow condition container is empty or not.
279      *
280      * @param root  A {@link VtnFlowConditions} instance.
281      * @return  {@code true} only if the given flow condition container is
282      *          empty.
283      */
284     public static boolean isEmpty(VtnFlowConditions root) {
285         if (root == null) {
286             return true;
287         }
288
289         List<VtnFlowCondition> vlist = root.getVtnFlowCondition();
290         return (vlist == null || vlist.isEmpty());
291     }
292
293     /**
294      * Determine whether the specified flow condition is present or not.
295      *
296      * @param rtx    A {@link ReadTransaction} instance associated with the
297      *               read transaction for the MD-SAL datastore.
298      * @param vname  A {@link VnodeName} instance that contains the name of the
299      *               target flow condition.
300      * @throws RpcException
301      *    The specified flow condition is not present.
302      * @throws VTNException
303      *    Failed to read the MD-SAL datastore.
304      */
305     public static void checkPresent(ReadTransaction rtx, VnodeName vname)
306         throws VTNException {
307         InstanceIdentifier<VtnFlowCondition> path = getIdentifier(vname);
308         LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
309         Optional<VtnFlowCondition> opt = DataStoreUtils.read(rtx, oper, path);
310         if (!opt.isPresent()) {
311             throw getNotFoundException(vname.getValue());
312         }
313     }
314
315     /**
316      * Read all the flow conditions from the MD-SAL datastore.
317      *
318      * @param rtx  A {@link ReadTransaction} instance.
319      * @return  A list of {@link VTNFlowCondition} instances.
320      * @throws VTNException  An error occurred.
321      */
322     public static List<VTNFlowCondition> readFlowConditions(ReadTransaction rtx)
323         throws VTNException {
324         InstanceIdentifier<VtnFlowConditions> path =
325             InstanceIdentifier.create(VtnFlowConditions.class);
326         LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
327         Optional<VtnFlowConditions> opt = DataStoreUtils.read(rtx, oper, path);
328         List<VtnFlowCondition> vlist = null;
329         if (opt.isPresent()) {
330             vlist = opt.get().getVtnFlowCondition();
331         }
332         if (vlist == null || vlist.isEmpty()) {
333             return Collections.<VTNFlowCondition>emptyList();
334         }
335
336         List<VTNFlowCondition> list = new ArrayList<>(vlist.size());
337         for (VtnFlowCondition vfc: vlist) {
338             list.add(new VTNFlowCondition(vfc));
339         }
340
341         return list;
342     }
343
344     /**
345      * Read the flow condition specified by the given name from the MD-SAL
346      * datastore.
347      *
348      * @param rtx   A {@link ReadTransaction} instance.
349      * @param name  The name of the flow condition.
350      * @return  A {@link VTNFlowCondition} instance.
351      * @throws VTNException  An error occurred.
352      */
353     public static VTNFlowCondition readFlowCondition(ReadTransaction rtx,
354                                                      String name)
355         throws VTNException {
356         InstanceIdentifier<VtnFlowCondition> path = getIdentifier(name);
357         LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
358         Optional<VtnFlowCondition> opt = DataStoreUtils.read(rtx, oper, path);
359         if (opt.isPresent()) {
360             return new VTNFlowCondition(opt.get());
361         }
362
363         throw getNotFoundException(name);
364     }
365
366     /**
367      * Read the flow match specified by the given index in the given flow
368      * condition from the MD-SAL datastore.
369      *
370      * @param rtx   A {@link ReadTransaction} instance.
371      * @param name  The name of the flow condition.
372      * @param idx   The match index that specifies the flow match in the
373      *              flow condition.
374      * @return  A {@link VTNFlowMatch} instance.
375      *          {@code null} is returned if no flow match is associated
376      *          with the given match index in the flow condition.
377      * @throws VTNException  An error occurred.
378      */
379     public static VTNFlowMatch readFlowMatch(ReadTransaction rtx, String name,
380                                              int idx) throws VTNException {
381         VnodeName vname = getVnodeName(name);
382         InstanceIdentifier<VtnFlowMatch> path = getIdentifier(vname, idx);
383         LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
384         Optional<VtnFlowMatch> opt = DataStoreUtils.read(rtx, oper, path);
385         if (opt.isPresent()) {
386             return new VTNFlowMatch(opt.get());
387         }
388
389         // Check to see if the flow condition is present.
390         checkPresent(rtx, vname);
391
392         return null;
393     }
394 }