2 * Copyright (c) 2015 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.neutron.transcriber;
11 import java.lang.reflect.Method;
12 import java.util.ArrayList;
13 import java.util.HashSet;
14 import java.util.List;
17 import java.util.concurrent.ExecutionException;
19 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
26 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
27 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
29 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
30 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yangtools.yang.binding.Augmentable;
33 import org.opendaylight.yangtools.yang.binding.ChildOf;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.common.base.Optional;
40 import com.google.common.base.Preconditions;
41 import com.google.common.util.concurrent.CheckedFuture;
43 import org.opendaylight.neutron.spi.INeutronCRUD;
44 import org.opendaylight.neutron.spi.INeutronObject;
46 public abstract class AbstractNeutronInterface<T extends DataObject, U extends ChildOf<? extends DataObject> & Augmentable<U>, S extends INeutronObject> implements AutoCloseable, INeutronCRUD<S>, TransactionChainListener {
47 private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNeutronInterface.class);
48 private static final int DEDASHED_UUID_LENGTH = 32;
49 private static final int DEDASHED_UUID_START = 0;
50 private static final int DEDASHED_UUID_DIV1 = 8;
51 private static final int DEDASHED_UUID_DIV2 = 12;
52 private static final int DEDASHED_UUID_DIV3 = 16;
53 private static final int DEDASHED_UUID_DIV4 = 20;
55 private DataBroker db;
57 AbstractNeutronInterface(ProviderContext providerContext) {
58 this.db = providerContext.getSALService(DataBroker.class);
61 public DataBroker getDataBroker() {
65 public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction, Throwable cause) {
66 LOGGER.error("Broken chain {} in TxchainDomWrite, transaction {}, cause {}",
67 chain, transaction.getIdentifier(), cause);
70 public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
71 LOGGER.debug("Chain {} closed successfully", chain);
74 protected BindingTransactionChain createTransactionChain() {
75 return getDataBroker().createTransactionChain(this);
78 protected interface Action0<U> {
79 public U action(BindingTransactionChain chain);
82 protected <U> U chainWrapper0(Action0<U> action) {
83 try (BindingTransactionChain chain = this.createTransactionChain()) {
84 return action.action(chain);
88 protected interface Action1<U, V> {
89 public U action(V input, BindingTransactionChain chain);
92 protected <U, V> U chainWrapper1(V input, Action1<U, V> action) {
93 try (BindingTransactionChain chain = this.createTransactionChain()) {
94 return action.action(input, chain);
98 protected interface Action2<U, V, W> {
99 public U action(V input0, W input1, BindingTransactionChain chain);
102 protected <U, V, W> U chainWrapper2(V input0, W input1,
103 Action2<U, V, W> action) {
104 try (BindingTransactionChain chain = this.createTransactionChain()) {
105 return action.action(input0, input1, chain);
109 protected abstract InstanceIdentifier<T> createInstanceIdentifier(T item);
111 protected abstract InstanceIdentifier<U> createInstanceIdentifier();
113 protected abstract T toMd(S neutronObject);
115 protected abstract T toMd(String uuid);
117 protected abstract S fromMd(T dataObject);
119 protected <T extends DataObject> T readMd(InstanceIdentifier<T> path, BindingTransactionChain chain) {
120 Preconditions.checkNotNull(chain);
122 final ReadOnlyTransaction transaction = chain.newReadOnlyTransaction();
123 CheckedFuture<Optional<T>, ReadFailedException> future = transaction.read(LogicalDatastoreType.CONFIGURATION, path);
124 if (future != null) {
125 Optional<T> optional;
127 optional = future.checkedGet();
128 if (optional.isPresent()) {
129 result = optional.get();
131 } catch (ReadFailedException e) {
132 LOGGER.warn("Failed to read {}", path, e);
139 protected <T extends DataObject> T readMd(InstanceIdentifier<T> path) {
140 return chainWrapper1(path,
141 new Action1<T, InstanceIdentifier<T>>() {
143 public T action(InstanceIdentifier<T> path, BindingTransactionChain chain) {
144 return readMd(path, chain);
149 protected boolean addMd(S neutronObject, BindingTransactionChain chain) {
150 // TODO think about adding existence logic
151 return updateMd(neutronObject, chain);
154 protected boolean addMd(S neutronObject) {
155 return chainWrapper1(neutronObject,
156 new Action1<Boolean, S>() {
158 public Boolean action(S path, BindingTransactionChain chain) {
159 return addMd(path, chain);
164 protected boolean updateMd(S neutronObject, BindingTransactionChain chain) {
165 Preconditions.checkNotNull(chain);
168 * retry for transaction conflict.
170 * org.opendaylight.controller.sal.restconf.impl.RestconfImpl#updateConfigurationData
174 WriteTransaction transaction = chain.newWriteOnlyTransaction();
175 T item = toMd(neutronObject);
176 InstanceIdentifier<T> iid = createInstanceIdentifier(item);
177 transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
178 CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
181 } catch (InterruptedException | ExecutionException e) {
182 if (e.getCause() instanceof OptimisticLockFailedException) {
184 LOGGER.debug("Got OptimisticLockFailedException - trying again {}", neutronObject);
187 LOGGER.warn("Got OptimisticLockFailedException on last try - failing {}", neutronObject);
189 LOGGER.warn("Transation failed ", e);
197 protected boolean updateMd(S neutronObject) {
198 return chainWrapper1(neutronObject,
199 new Action1<Boolean, S>() {
201 public Boolean action(S neutronObject, BindingTransactionChain chain) {
202 return updateMd(neutronObject, chain);
207 private boolean removeMd(T item, BindingTransactionChain chain) {
208 Preconditions.checkNotNull(chain);
209 WriteTransaction transaction = chain.newWriteOnlyTransaction();
210 InstanceIdentifier<T> iid = createInstanceIdentifier(item);
211 transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
212 CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
215 } catch (InterruptedException | ExecutionException e) {
216 LOGGER.warn("Transation failed ",e);
222 protected boolean removeMd(T item) {
223 return chainWrapper1(item,
224 new Action1<Boolean, T>() {
226 public Boolean action(T item, BindingTransactionChain chain) {
227 return removeMd(item, chain);
232 protected Uuid toUuid(String uuid) {
233 Preconditions.checkNotNull(uuid);
236 result = new Uuid(uuid);
237 } catch(IllegalArgumentException e) {
238 // OK... someone didn't follow RFC 4122... lets try this the hard way
239 String dedashed = uuid.replace("-", "");
240 if(dedashed.length() == DEDASHED_UUID_LENGTH) {
241 String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1)
243 + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2)
245 + dedashed.substring(DEDASHED_UUID_DIV2, DEDASHED_UUID_DIV3)
247 + dedashed.substring(DEDASHED_UUID_DIV3, DEDASHED_UUID_DIV4)
249 + dedashed.substring(DEDASHED_UUID_DIV4, DEDASHED_UUID_LENGTH);
250 result = new Uuid(redashed);
258 // this method uses reflection to update an object from it's delta.
260 protected boolean overwrite(Object target, Object delta) {
261 Method[] methods = target.getClass().getMethods();
263 for(Method toMethod: methods){
264 if(toMethod.getDeclaringClass().equals(target.getClass())
265 && toMethod.getName().startsWith("set")){
267 String toName = toMethod.getName();
268 String fromName = toName.replace("set", "get");
271 Method fromMethod = delta.getClass().getMethod(fromName);
272 Object value = fromMethod.invoke(delta, (Object[])null);
274 toMethod.invoke(target, value);
276 } catch (Exception e) {
277 LOGGER.error("Error in overwrite", e);
286 public void close() throws Exception {
287 // TODO Auto-generated method stub
291 protected boolean exists(String uuid, BindingTransactionChain chain) {
292 Preconditions.checkNotNull(chain);
293 T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), chain);
294 return dataObject != null;
298 public boolean exists(String uuid) {
299 return chainWrapper1(uuid,
300 new Action1<Boolean, String>() {
302 public Boolean action(String uuid, BindingTransactionChain chain) {
303 return exists(uuid, chain);
308 protected S get(String uuid, BindingTransactionChain chain) {
309 Preconditions.checkNotNull(chain);
310 T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), chain);
311 if (dataObject == null) {
314 return fromMd(dataObject);
318 public S get(String uuid) {
319 return chainWrapper1(uuid,
320 new Action1<S, String>() {
322 public S action(String uuid, BindingTransactionChain chain) {
323 return get(uuid, chain);
328 protected abstract List<T> getDataObjectList(U dataObjects);
330 protected List<S> getAll(BindingTransactionChain chain) {
331 Preconditions.checkNotNull(chain);
332 Set<S> allNeutronObjects = new HashSet<S>();
333 U dataObjects = readMd(createInstanceIdentifier(), chain);
334 if (dataObjects != null) {
335 for (T dataObject: getDataObjectList(dataObjects)) {
336 allNeutronObjects.add(fromMd(dataObject));
339 LOGGER.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
340 List<S> ans = new ArrayList<S>();
341 ans.addAll(allNeutronObjects);
346 public List<S> getAll() {
347 return chainWrapper0(new Action0<List<S>>() {
349 public List<S> action(BindingTransactionChain chain) {
350 return getAll(chain);
355 protected boolean add(S input, BindingTransactionChain chain) {
356 Preconditions.checkNotNull(chain);
357 if (exists(input.getID(), chain)) {
365 public boolean add(S input) {
366 return chainWrapper1(input,
367 new Action1<Boolean, S>() {
369 public Boolean action(S input, BindingTransactionChain chain) {
370 return add(input, chain);
375 protected boolean remove(String uuid, BindingTransactionChain chain) {
376 Preconditions.checkNotNull(chain);
377 if (!exists(uuid, chain)) {
380 return removeMd(toMd(uuid), chain);
384 public boolean remove(String uuid) {
385 return chainWrapper1(uuid,
386 new Action1<Boolean, String>() {
388 public Boolean action(String uuid, BindingTransactionChain chain) {
389 return remove(uuid, chain);
394 protected boolean update(String uuid, S delta, BindingTransactionChain chain) {
395 Preconditions.checkNotNull(chain);
396 if (!exists(uuid, chain)) {
399 updateMd(delta, chain);
404 public boolean update(String uuid, S delta) {
405 return chainWrapper2(uuid, delta,
406 new Action2<Boolean, String, S>() {
408 public Boolean action(String uuid, S delta, BindingTransactionChain chain) {
409 return update(uuid, delta, chain);
415 public boolean inUse(String uuid) {