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 public BindingTransactionChain createTransactionChain() {
75 return getDataBroker().createTransactionChain(this);
78 protected interface Action0<U> {
79 public U action(BindingTransactionChain chain);
82 protected <U> U chainWrapper0(BindingTransactionChain chain,
85 return action.action(chain);
87 try (BindingTransactionChain newChain = this.createTransactionChain()) {
88 return action.action(newChain);
92 protected interface Action1<U, V> {
93 public U action(V input, BindingTransactionChain chain);
96 protected <U, V> U chainWrapper1(V input, BindingTransactionChain chain,
97 Action1<U, V> action) {
99 return action.action(input, chain);
101 try (BindingTransactionChain newChain = this.createTransactionChain()) {
102 return action.action(input, newChain);
106 protected interface Action2<U, V, W> {
107 public U action(V input0, W input1, BindingTransactionChain chain);
110 protected <U, V, W> U chainWrapper2(V input0, W input1,
111 BindingTransactionChain chain,
112 Action2<U, V, W> action) {
114 return action.action(input0, input1, chain);
116 try (BindingTransactionChain newChain = this.createTransactionChain()) {
117 return action.action(input0, input1, newChain);
121 protected abstract InstanceIdentifier<T> createInstanceIdentifier(T item);
123 protected abstract InstanceIdentifier<U> createInstanceIdentifier();
125 protected abstract T toMd(S neutronObject);
127 protected abstract T toMd(String uuid);
129 protected abstract S fromMd(T dataObject);
131 private <T extends DataObject> T _readMd(InstanceIdentifier<T> path, BindingTransactionChain chain) {
132 Preconditions.checkNotNull(chain);
134 final ReadOnlyTransaction transaction = chain.newReadOnlyTransaction();
135 CheckedFuture<Optional<T>, ReadFailedException> future = transaction.read(LogicalDatastoreType.CONFIGURATION, path);
136 if (future != null) {
137 Optional<T> optional;
139 optional = future.checkedGet();
140 if (optional.isPresent()) {
141 result = optional.get();
143 } catch (ReadFailedException e) {
144 LOGGER.warn("Failed to read {}", path, e);
151 protected <T extends DataObject> T readMd(InstanceIdentifier<T> path, BindingTransactionChain chain) {
152 return chainWrapper1(path, chain,
153 new Action1<T, InstanceIdentifier<T>>() {
155 public T action(InstanceIdentifier<T> path, BindingTransactionChain chain) {
156 return _readMd(path, chain);
161 protected <T extends DataObject> T readMd(InstanceIdentifier<T> path) {
162 return readMd(path, null);
165 protected boolean addMd(S neutronObject, BindingTransactionChain chain) {
166 // TODO think about adding existence logic
167 return updateMd(neutronObject, chain);
170 protected boolean addMd(S neutronObject) {
171 return addMd(neutronObject, null);
174 protected boolean _updateMd(S neutronObject, BindingTransactionChain chain) {
175 Preconditions.checkNotNull(chain);
178 * retry for transaction conflict.
180 * org.opendaylight.controller.sal.restconf.impl.RestconfImpl#updateConfigurationData
184 WriteTransaction transaction = chain.newWriteOnlyTransaction();
185 T item = toMd(neutronObject);
186 InstanceIdentifier<T> iid = createInstanceIdentifier(item);
187 transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
188 CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
191 } catch (InterruptedException | ExecutionException e) {
192 if (e.getCause() instanceof OptimisticLockFailedException) {
194 LOGGER.debug("Got OptimisticLockFailedException - trying again {}", neutronObject);
197 LOGGER.warn("Got OptimisticLockFailedException on last try - failing {}", neutronObject);
199 LOGGER.warn("Transation failed ", e);
207 protected boolean updateMd(S neutronObject, BindingTransactionChain chain) {
208 return chainWrapper1(neutronObject, chain,
209 new Action1<Boolean, S>() {
211 public Boolean action(S neutronObject, BindingTransactionChain chain) {
212 return _updateMd(neutronObject, chain);
217 protected boolean updateMd(S neutronObject) {
218 return updateMd(neutronObject, null);
221 private boolean _removeMd(T item, BindingTransactionChain chain) {
222 Preconditions.checkNotNull(chain);
223 WriteTransaction transaction = chain.newWriteOnlyTransaction();
224 InstanceIdentifier<T> iid = createInstanceIdentifier(item);
225 transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
226 CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
229 } catch (InterruptedException | ExecutionException e) {
230 LOGGER.warn("Transation failed ",e);
236 protected boolean removeMd(T item, BindingTransactionChain chain) {
237 return chainWrapper1(item, chain,
238 new Action1<Boolean, T>() {
240 public Boolean action(T item, BindingTransactionChain chain) {
241 return _removeMd(item, chain);
246 protected boolean removeMd(T item) {
247 return removeMd(item, null);
250 protected Uuid toUuid(String uuid) {
251 Preconditions.checkNotNull(uuid);
254 result = new Uuid(uuid);
255 } catch(IllegalArgumentException e) {
256 // OK... someone didn't follow RFC 4122... lets try this the hard way
257 String dedashed = uuid.replace("-", "");
258 if(dedashed.length() == DEDASHED_UUID_LENGTH) {
259 String redashed = dedashed.substring(DEDASHED_UUID_START, DEDASHED_UUID_DIV1)
261 + dedashed.substring(DEDASHED_UUID_DIV1, DEDASHED_UUID_DIV2)
263 + dedashed.substring(DEDASHED_UUID_DIV2, DEDASHED_UUID_DIV3)
265 + dedashed.substring(DEDASHED_UUID_DIV3, DEDASHED_UUID_DIV4)
267 + dedashed.substring(DEDASHED_UUID_DIV4, DEDASHED_UUID_LENGTH);
268 result = new Uuid(redashed);
276 // this method uses reflection to update an object from it's delta.
278 protected boolean overwrite(Object target, Object delta) {
279 Method[] methods = target.getClass().getMethods();
281 for(Method toMethod: methods){
282 if(toMethod.getDeclaringClass().equals(target.getClass())
283 && toMethod.getName().startsWith("set")){
285 String toName = toMethod.getName();
286 String fromName = toName.replace("set", "get");
289 Method fromMethod = delta.getClass().getMethod(fromName);
290 Object value = fromMethod.invoke(delta, (Object[])null);
292 toMethod.invoke(target, value);
294 } catch (Exception e) {
295 LOGGER.error("Error in overwrite", e);
304 public void close() throws Exception {
305 // TODO Auto-generated method stub
309 protected boolean _exists(String uuid, BindingTransactionChain chain) {
310 Preconditions.checkNotNull(chain);
311 T dataObject = readMd(createInstanceIdentifier(toMd(uuid)), chain);
312 return dataObject != null;
315 public boolean exists(String uuid, BindingTransactionChain chain) {
316 return chainWrapper1(uuid, chain,
317 new Action1<Boolean, String>() {
319 public Boolean action(String uuid, BindingTransactionChain chain) {
320 return _exists(uuid, chain);
325 public boolean exists(String uuid) {
326 return exists(uuid, null);
329 public S get(String uuid) {
330 T dataObject = readMd(createInstanceIdentifier(toMd(uuid)));
331 if (dataObject == null) {
334 return fromMd(dataObject);
337 protected abstract List<T> getDataObjectList(U dataObjects);
339 public List<S> getAll() {
340 Set<S> allNeutronObjects = new HashSet<S>();
341 U dataObjects = readMd(createInstanceIdentifier());
342 if (dataObjects != null) {
343 for (T dataObject: getDataObjectList(dataObjects)) {
344 allNeutronObjects.add(fromMd(dataObject));
347 LOGGER.debug("Exiting _getAll, Found {} OpenStackFirewall", allNeutronObjects.size());
348 List<S> ans = new ArrayList<S>();
349 ans.addAll(allNeutronObjects);
353 public boolean add(S input) {
354 if (exists(input.getID())) {
361 public boolean remove(String uuid) {
365 return removeMd(toMd(uuid));
368 public boolean update(String uuid, S delta) {
376 public boolean inUse(String uuid) {