+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for
- * flow node subDataObject (flows, groups and meters).
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public abstract class AbstractChangeListener implements DataChangeListener {
-
- private final static Logger LOG = LoggerFactory.getLogger(AbstractChangeListener.class);
-
- private final AtomicLong txNum = new AtomicLong();
- private String transactionId;
-
- @Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
- this.transactionId = this.newTransactionIdentifier().toString();
- /* All DataObjects for create */
- final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
- changeEvent.getCreatedData().entrySet();
- /* All DataObjects for updates - init HashSet */
- final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<>();
- /* Filtered DataObject for update processing only */
- Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updateConfigEntrySet =
- changeEvent.getUpdatedData().entrySet();
- updatedEntries.addAll(updateConfigEntrySet);
- updatedEntries.removeAll(createdEntries);
- /* All DataObjects for remove */
- final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
- changeEvent.getRemovedPaths();
- /* Create DataObject processing (send to device) */
- for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
- InstanceIdentifier<? extends DataObject> entryKey = createdEntry.getKey();
- DataObject entryValue = createdEntry.getValue();
- if (preconditionForChange(entryKey, entryValue, null)) {
- this.add(entryKey, entryValue);
- }
- }
-
- for (final Entry<InstanceIdentifier<?>, DataObject> updatedEntrie : updatedEntries) {
- Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
- changeEvent.getOriginalData();
-
- InstanceIdentifier<? extends Object> entryKey = updatedEntrie.getKey();
- final DataObject original = origConfigData.get(entryKey);
- final DataObject updated = updatedEntrie.getValue();
- if (preconditionForChange(entryKey, original, updated)) {
- this.update(entryKey, original, updated);
- }
- }
-
- for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
- Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
- changeEvent.getOriginalData();
-
- final DataObject removeValue = origConfigData.get(instanceId);
- if (preconditionForChange(instanceId, removeValue, null)) {
- this.remove(instanceId, removeValue);
- }
- }
- }
-
- /**
- * Method returns generated transaction ID, which is unique for
- * every transaction. ID is composite from prefix ("DOM") and unique number.
- *
- * @return String transactionID
- */
- public String getTransactionId() {
- return this.transactionId;
- }
-
- private Object newTransactionIdentifier() {
- return "DOM-" + txNum.getAndIncrement();
- }
-
- /**
- * Method check all local preconditions for apply relevant changes.
- *
- * @param InstanceIdentifier identifier - the whole path to DataObject
- * @param DataObject original - original DataObject (for update)
- * or relevant DataObject (add/delete operations)
- * @param DataObject update - changed DataObject (contain updates)
- * or should be null for (add/delete operations)
- *
- * @return boolean - applicable
- */
- protected abstract boolean preconditionForChange(
- final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update);
-
- /**
- * Method checks the node data path in DataStore/OPERATIONAL because
- * without the Node Identifier in DataStore/OPERATIONAL, device
- * is not connected and device pre-configuration is allowed only.
- *
- * @param InstanceIdentifier identifier - could be whole path to DataObject,
- * but parent Node.class InstanceIdentifier is used for a check only
- *
- * @return boolean - is the Node available in DataStore/OPERATIONAL (is connected)
- */
- protected boolean isNodeAvailable(final InstanceIdentifier<? extends DataObject> identifier,
- final ReadOnlyTransaction readTrans) {
- final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
- try {
- return readTrans.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId).get().isPresent();
- }
- catch (InterruptedException | ExecutionException e) {
- LOG.error("Unexpected exception by reading Node ".concat(nodeInstanceId.toString()), e);
- return false;
- }
- finally {
- readTrans.close();
- }
- }
-
- /**
- * Method removes DataObject which is identified by InstanceIdentifier
- * from device.
- *
- * @param InstanceIdentifier identifier - the whole path to DataObject
- * @param DataObject remove - DataObject for removing
- */
- protected abstract void remove(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject remove);
-
- /**
- * Method updates the original DataObject to the update DataObject
- * in device. Both are identified by same InstanceIdentifier
- *
- * @param InstanceIdentifier identifier - the whole path to DataObject
- * @param DataObject original - original DataObject (for update)
- * @param DataObject update - changed DataObject (contain updates)
- */
- protected abstract void update(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update);
-
- /**
- * Method adds the DataObject which is identified by InstanceIdentifier
- * to device.
- *
- * @param InstanceIdentifier identifier - the whole path to new DataObject
- * @param DataObject add - new DataObject
- */
- protected abstract void add(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject add);
-}
*/
package org.opendaylight.controller.frm;
-import org.opendaylight.controller.frm.flow.FlowProvider;
-import org.opendaylight.controller.frm.group.GroupProvider;
-import org.opendaylight.controller.frm.meter.MeterProvider;
-import org.opendaylight.controller.frm.reconil.FlowNodeReconcilProvider;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
/**
* Forwarding Rules Manager Activator
*
- * Activator manages all Providers ({@link FlowProvider}, {@link GroupProvider},
- * {@link MeterProvider} and the {@link FlowNodeReconcilProvider}).
+ * Activator {@link ForwardingRulesManager}.
* It registers all listeners (DataChangeEvent, ReconcilNotification)
* in the Session Initialization phase.
*
private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class);
- private final FlowProvider flowProvider;
- private final GroupProvider groupProvider;
- private final MeterProvider meterProvider;
- private final FlowNodeReconcilProvider flowNodeReconcilProvider;
-
- public FRMActivator() {
- this.flowProvider = new FlowProvider();
- this.groupProvider = new GroupProvider();
- this.meterProvider = new MeterProvider();
- this.flowNodeReconcilProvider = new FlowNodeReconcilProvider();
- }
+ private ForwardingRulesManager manager;
@Override
- public void onSessionInitiated(final ProviderContext session) {
+ public void onSessionInitiated(ProviderContext session) {
LOG.info("FRMActivator initialization.");
- /* Flow */
try {
- final DataBroker flowSalService = session.getSALService(DataBroker.class);
- this.flowProvider.init(flowSalService);
- this.flowProvider.start(session);
- /* Group */
- final DataBroker groupSalService = session.getSALService(DataBroker.class);
- this.groupProvider.init(groupSalService);
- this.groupProvider.start(session);
- /* Meter */
- final DataBroker meterSalService = session.getSALService(DataBroker.class);
- this.meterProvider.init(meterSalService);
- this.meterProvider.start(session);
- /* FlowNode Reconciliation */
- final DataBroker dbs = session.getSALService(DataBroker.class);
- this.flowNodeReconcilProvider.init(dbs);
- this.flowNodeReconcilProvider.start(session);
-
- LOG.info("FRMActivator started successfully");
- } catch (Exception e) {
- String errMsg = "Unexpected error by starting FRMActivator";
- LOG.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ this.manager = new ForwardingRulesManagerImpl(dataBroker, session);
+ this.manager.start();
+ LOG.info("FRMActivator initialization successfull.");
+ }
+ catch (Exception e) {
+ LOG.error("Unexpected error by FRM initialization!", e);
+ this.stopImpl(null);
}
}
@Override
protected void stopImpl(final BundleContext context) {
- try {
- this.flowProvider.close();
- this.groupProvider.close();
- this.meterProvider.close();
- this.flowNodeReconcilProvider.close();
- } catch (Exception e) {
- LOG.error("Unexpected error by stopping FRMActivator", e);
+ if (manager != null) {
+ try {
+ manager.close();
+ } catch (Exception e) {
+ LOG.error("Unexpected error by stopping FRMActivator", e);
+ }
+ manager = null;
+ LOG.info("FRMActivator stopped.");
}
}
}
\ No newline at end of file
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.frm;
-
-import java.math.BigInteger;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AtomicLongMap;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * Singleton FlowCookieProducer contains a FlowCookie generator which is generated unique
- * flowCookie identifier for every flow in same Table. That could help with quick
- * identification of flow statistic because DataStore/CONFIGURATION could contains
- * a lot of flows with same flowCookie. So we are replacing original flowCookie
- * with unique and we are building final FlowCookieMap in DataStore/OPERATIONAL
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public enum FlowCookieProducer {
-
- INSTANCE;
-
- /* Flow_Cookie_Key and Flow_Ids MapHolder */
- private static final AtomicLongMap<InstanceIdentifier<Table>> cookieKeys = AtomicLongMap.create();
-
- /**
- * Method returns the unique cookie for a node table.
- * Flow Cookie Key signs List<FlowId> for a right flow statistic identification
- * in the DataStore/operational.
- * We need a List<FlowId> because system doesn't guarantee unique mapping
- * from flow_cookie to flow_id. REST Operations doesn't used FRM yet, so
- * cookie from user input could have a user input flow ID and an alien system ID
- * which is generated by system.
- *
- * @param InstanceIdentifier<Table> tableIdentifier
- * @return unique BigInteger flowCookie for a node table
- */
- public BigInteger getNewCookie(final InstanceIdentifier<Table> tableIdentifier) {
- FlowCookieProducer.validationTableIdentifier(tableIdentifier);
- if ( cookieKeys.containsKey(tableIdentifier)) {
- /* new identifier always starts from ONE because
- * ZERO is reserved for the NO_COOKIES flows */
- return BigInteger.valueOf(cookieKeys.addAndGet(tableIdentifier, 1L));
- } else {
- return BigInteger.valueOf(cookieKeys.incrementAndGet(tableIdentifier));
- }
- }
-
- /**
- * Method cleans the node table flow_cookie_key for the disconnected Node.
- *
- * @param InstanceIdentifier<Table> tableIdentifier
- */
- public void clean(final InstanceIdentifier<Table> tableIdentifier) {
- FlowCookieProducer.validationTableIdentifier(tableIdentifier);
- cookieKeys.remove(tableIdentifier);
- }
-
- /*
- * Help the TableIdentifer input validation method
- */
- private static void validationTableIdentifier(final InstanceIdentifier<Table> tableIdent) {
- Preconditions.checkArgument(tableIdent != null, "Input validation exception: TableIdentifier can not be null !");
- }
-}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * FlowNodeReconciliation
+ * It represent Reconciliation functionality for every new device.
+ * So we have to read all possible pre-configured Flows, Meters and Groups from
+ * Config/DS and add all to new device.
+ * New device is represented by new {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode}
+ * in Operational/DS. So we have to add listener for Wildcarded path in base data change scope.
+ *
+ * WildCarded InstanceIdentifier:
+ * {@code
+ *
+ * InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class)
+ *
+ * }
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 26, 2014
+ */
+public interface FlowNodeReconciliation extends DataChangeListener, AutoCloseable {
+
+ /**
+ * Method contains Node registration to {@link ForwardingRulesManager} functionality
+ * as a prevention to use a validation check to the Operational/DS for identify
+ * pre-configure transaction and serious device commit in every transaction.
+ *
+ * Second part of functionality is own reconciliation pre-configure
+ * Flows, Meters and Groups.
+ *
+ * @param connectedNode - {@link org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier} to new Node
+ */
+ void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode);
+
+ /**
+ * Method contains functionality for registered Node {@FlowCapableNode} removing
+ * from {@Link ForwardingRulesManager}
+ *
+ * @param disconnectedNode - {@link org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier} to removed Node
+ */
+ void flowNodeDisconnected(InstanceIdentifier<FlowCapableNode> disconnectedNode);
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * ForwardingRulesCommiter
+ * It represent a contract between DataStore DataChangeEvent and relevant
+ * SalRpcService for device. Every implementation has to be registered for
+ * Configurational/DS tree path.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public interface ForwardingRulesCommiter <D extends DataObject> extends AutoCloseable, DataChangeListener {
+
+ /**
+ * Method removes DataObject which is identified by InstanceIdentifier
+ * from device.
+ *
+ * @param InstanceIdentifier identifier - the whole path to DataObject
+ * @param DataObject remove - DataObject for removing
+ * @param InstanceIdentifier<FlowCapableNode> parent Node InstanceIdentifier
+ */
+ void remove(InstanceIdentifier<D> identifier, D del,
+ InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+ /**
+ * Method updates the original DataObject to the update DataObject
+ * in device. Both are identified by same InstanceIdentifier
+ *
+ * @param InstanceIdentifier identifier - the whole path to DataObject
+ * @param DataObject original - original DataObject (for update)
+ * @param DataObject update - changed DataObject (contain updates)
+ */
+ void update(InstanceIdentifier<D> identifier, D original, D update,
+ InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+ /**
+ * Method adds the DataObject which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param InstanceIdentifier identifier - the whole path to new DataObject
+ * @param DataObject add - new DataObject
+ */
+ void add(InstanceIdentifier<D> identifier, D add,
+ InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.frm;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * ForwardingRulesManager
+ * It represent a central point for whole modul. Implementation
+ * Flow Provider registers the link FlowChangeListener} and it holds all needed
+ * services for link FlowChangeListener}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public interface ForwardingRulesManager extends AutoCloseable {
+
+ public void start();
+
+ /**
+ * Method returns information :
+ * "is Node with send InstanceIdentifier connected"?
+ *
+ * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+ * @return boolean - is device connected
+ */
+ public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident);
+
+ /**
+ * Method add new {@link FlowCapableNode} to active Node Holder.
+ * ActiveNodeHolder prevent unnecessary Operational/DS read for identify
+ * pre-configure and serious Configure/DS transactions.
+ *
+ * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+ */
+ public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident);
+
+ /**
+ * Method remove disconnected {@link FlowCapableNode} from active Node
+ * Holder. And all next flows or groups or meters will stay in Config/DS
+ * only.
+ *
+ * @param InstanceIdentifier<FlowCapableNode> ident - the key of the node
+ */
+ public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident);
+
+ /**
+ * Method returns generated transaction ID, which is unique for
+ * every transaction. ID is composite from prefix ("DOM") and unique number.
+ *
+ * @return String transactionID for RPC transaction identification
+ */
+ public String getNewTransactionId();
+
+ /**
+ * Method returns Read Transacion. It is need for Node reconciliation only.
+ *
+ * @return ReadOnlyTransaction
+ */
+ public ReadOnlyTransaction getReadTranaction();
+
+ /**
+ * Flow RPC service
+ *
+ * @return
+ */
+ public SalFlowService getSalFlowService();
+
+ /**
+ * Group RPC service
+ *
+ * @return
+ */
+ public SalGroupService getSalGroupService();
+
+ /**
+ * Meter RPC service
+ *
+ * @return
+ */
+ public SalMeterService getSalMeterService();
+
+ /**
+ * Content definition method and prevent code duplicity in Reconcil
+ * @return ForwardingRulesCommiter<Flow>
+ */
+ public ForwardingRulesCommiter<Flow> getFlowCommiter();
+
+ /**
+ * Content definition method and prevent code duplicity in Reconcil
+ * @return ForwardingRulesCommiter<Group>
+ */
+ public ForwardingRulesCommiter<Group> getGroupCommiter();
+
+ /**
+ * Content definition method and prevent code duplicity
+ * @return ForwardingRulesCommiter<Meter>
+ */
+ public ForwardingRulesCommiter<Meter> getMeterCommiter();
+
+ /**
+ * Content definition method
+ * @return FlowNodeReconciliation
+ */
+ public FlowNodeReconciliation getFlowNodeReconciliation();
+}
+
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.flow;
-
-import java.math.BigInteger;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.frm.FlowCookieProducer;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Flow Change Listener
- * add, update and remove {@link Flow} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class FlowChangeListener extends AbstractChangeListener {
-
- private static final Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
-
- private final FlowProvider provider;
-
- public FlowChangeListener (final FlowProvider provider) {
- this.provider = Preconditions.checkNotNull(provider, "FlowProvider can not be null !");
- }
-
- @Override
- protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject removeDataObj) {
-
- final Flow flow = ((Flow) removeDataObj);
- final InstanceIdentifier<Table> tableIdent = identifier.firstIdentifierOf(Table.class);
- final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
- final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow);
-
- // use empty cookie mask in order to delete flow even with generated cookie
- builder.setCookieMask(new FlowCookie(BigInteger.ZERO));
-
- builder.setFlowRef(new FlowRef(identifier));
- builder.setNode(new NodeRef(nodeIdent));
- builder.setFlowTable(new FlowTableRef(tableIdent));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalFlowService().removeFlow(builder.build());
- LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, removeDataObj});
- }
-
- @Override
- protected void update(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update) {
-
- final Flow originalFlow = ((Flow) original);
- final Flow updatedFlow = ((Flow) update);
- final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
- final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
-
- builder.setNode(new NodeRef(nodeIdent));
- builder.setFlowRef(new FlowRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
-
- builder.setUpdatedFlow((new UpdatedFlowBuilder(updatedFlow)).build());
- builder.setOriginalFlow((new OriginalFlowBuilder(originalFlow)).build());
-
- this.provider.getSalFlowService().updateFlow(builder.build());
- LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update});
- }
-
- @Override
- protected void add(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject addDataObj) {
-
- final Flow flow = ((Flow) addDataObj);
- final InstanceIdentifier<Table> tableIdent = identifier.firstIdentifierOf(Table.class);
- final NodeRef nodeRef = new NodeRef(identifier.firstIdentifierOf(Node.class));
- final FlowCookie flowCookie = new FlowCookie(FlowCookieProducer.INSTANCE.getNewCookie(tableIdent));
- final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
-
- builder.setNode(nodeRef);
- builder.setFlowRef(new FlowRef(identifier));
- builder.setFlowTable(new FlowTableRef(tableIdent));
- builder.setCookie( flowCookie );
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalFlowService().addFlow(builder.build());
- LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj});
- }
-
- @Override
- protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject dataObj, final DataObject update) {
-
- final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
- return update != null
- ? (dataObj instanceof Flow && update instanceof Flow && isNodeAvailable(identifier, trans))
- : (dataObj instanceof Flow && isNodeAvailable(identifier, trans));
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.flow;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Flow Provider registers the {@link FlowChangeListener} and it holds all needed
- * services for {@link FlowChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class FlowProvider implements AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
-
- private SalFlowService salFlowService;
- private DataBroker dataService;
-
- /* DataChangeListener */
- private DataChangeListener flowDataChangeListener;
- private ListenerRegistration<DataChangeListener> flowDataChangeListenerRegistration;
-
- /**
- * Provider Initialization Phase.
- *
- * @param DataProviderService dataService
- */
- public void init (final DataBroker dataService) {
- LOG.info("FRM Flow Config Provider initialization.");
- this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
- }
-
- /**
- * Listener Registration Phase
- *
- * @param RpcConsumerRegistry rpcRegistry
- */
- public void start(final RpcConsumerRegistry rpcRegistry) {
- Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-
- this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
- "RPC SalFlowService not found.");
-
- /* Build Path */
- InstanceIdentifier<Flow> flowIdentifier = InstanceIdentifier.create(Nodes.class)
- .child(Node.class).augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
-
- /* DataChangeListener registration */
- this.flowDataChangeListener = new FlowChangeListener(FlowProvider.this);
- this.flowDataChangeListenerRegistration =
- this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- flowIdentifier, flowDataChangeListener, DataChangeScope.SUBTREE);
-
- LOG.info("FRM Flow Config Provider started.");
- }
-
- @Override
- public void close() {
- LOG.info("FRM Flow Config Provider stopped.");
- if (flowDataChangeListenerRegistration != null) {
- try {
- flowDataChangeListenerRegistration.close();
- } catch (Exception e) {
- String errMsg = "Error by stop FRM Flow Config Provider.";
- LOG.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
- } finally {
- flowDataChangeListenerRegistration = null;
- }
- }
- }
-
- public DataChangeListener getFlowDataChangeListener() {
- return flowDataChangeListener;
- }
-
- public SalFlowService getSalFlowService() {
- return salFlowService;
- }
-
- public DataBroker getDataService() {
- return dataService;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.group;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Group Change Listener
- * add, update and remove {@link Group} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class GroupChangeListener extends AbstractChangeListener {
-
- private static final Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
-
- private final GroupProvider provider;
-
- public GroupChangeListener(final GroupProvider provider) {
- this.provider = Preconditions.checkNotNull(provider, "GroupProvider can not be null !");
- }
-
- @Override
- protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject removeDataObj) {
-
- final Group group = ((Group) removeDataObj);
- final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
- final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
-
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalGroupService().removeGroup(builder.build());
- LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj});
- }
-
- @Override
- protected void update(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update) {
-
- final Group originalGroup = ((Group) original);
- final Group updatedGroup = ((Group) update);
- final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
- final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
-
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
-
- builder.setUpdatedGroup((new UpdatedGroupBuilder(updatedGroup)).build());
- builder.setOriginalGroup((new OriginalGroupBuilder(originalGroup)).build());
-
- this.provider.getSalGroupService().updateGroup(builder.build());
- LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
- }
-
- @Override
- protected void add(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject addDataObj) {
-
- final Group group = ((Group) addDataObj);
- final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
- final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
-
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalGroupService().addGroup(builder.build());
- LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj});
- }
-
- @Override
- protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject dataObj, final DataObject update) {
-
- final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
- return update != null
- ? (dataObj instanceof Group && update instanceof Group && isNodeAvailable(identifier, trans))
- : (dataObj instanceof Group && isNodeAvailable(identifier, trans));
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.group;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Group Provider registers the {@link GroupChangeListener} and it holds all needed
- * services for {@link GroupChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class GroupProvider implements AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
-
- private SalGroupService salGroupService;
- private DataBroker dataService;
-
- /* DataChangeListener */
- private DataChangeListener groupDataChangeListener;
- private ListenerRegistration<DataChangeListener> groupDataChangeListenerRegistration;
-
- /**
- * Provider Initialization Phase.
- *
- * @param DataProviderService dataService
- */
- public void init (final DataBroker dataService) {
- LOG.info("FRM Group Config Provider initialization.");
- this.dataService = Preconditions.checkNotNull(dataService, "DataService can not be null !");
- }
-
- /**
- * Listener Registration Phase
- *
- * @param RpcConsumerRegistry rpcRegistry
- */
- public void start(final RpcConsumerRegistry rpcRegistry) {
- Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
-
- this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
- "RPC SalGroupService not found.");
-
- /* Build Path */
- InstanceIdentifier<Group> groupIdentifier = InstanceIdentifier.create(Nodes.class)
- .child(Node.class).augmentation(FlowCapableNode.class).child(Group.class);
-
- /* DataChangeListener registration */
- this.groupDataChangeListener = new GroupChangeListener(GroupProvider.this);
- this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(
- LogicalDatastoreType.CONFIGURATION, groupIdentifier, groupDataChangeListener, DataChangeScope.SUBTREE);
-
- LOG.info("FRM Group Config Provider started.");
- }
-
- @Override
- public void close() {
- LOG.info("FRM Group Config Provider stopped.");
- if (groupDataChangeListenerRegistration != null) {
- try {
- groupDataChangeListenerRegistration.close();
- } catch (Exception e) {
- String errMsg = "Error by stop FRM Group Config Provider.";
- LOG.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
- } finally {
- groupDataChangeListenerRegistration = null;
- }
- }
- }
-
- public DataChangeListener getGroupDataChangeListener() {
- return groupDataChangeListener;
- }
-
- public SalGroupService getSalGroupService() {
- return salGroupService;
- }
-
- public DataBroker getDataService() {
- return dataService;
- }
-}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.frm.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesCommiter;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for
+ * flow node subDataObject (flows, groups and meters).
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public abstract class AbstractListeningCommiter <T extends DataObject> implements ForwardingRulesCommiter<T> {
+
+ protected ForwardingRulesManager provider;
+
+ protected final Class<T> clazz;
+
+ public AbstractListeningCommiter (ForwardingRulesManager provider, Class<T> clazz) {
+ this.provider = Preconditions.checkNotNull(provider, "ForwardingRulesManager can not be null!");
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+
+ this.createData(createdData);
+ this.updateData(updateData, originalData);
+ this.removeData(removeData, originalData);
+ }
+
+ /**
+ * Method return wildCardPath for Listener registration
+ * and for identify the correct KeyInstanceIdentifier from data;
+ */
+ protected abstract InstanceIdentifier<T> getWildCardPath();
+
+
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent =
+ key.firstIdentifierOf(FlowCapableNode.class);
+ if (preConfigurationCheck(nodeIdent)) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get(), nodeIdent);
+ }
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent =
+ key.firstIdentifierOf(FlowCapableNode.class);
+ if (preConfigurationCheck(nodeIdent)) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T)original.get(), (T)value.get(), nodeIdent);
+ }
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent =
+ key.firstIdentifierOf(FlowCapableNode.class);
+ if (preConfigurationCheck(nodeIdent)) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue, nodeIdent);
+ }
+ }
+ }
+ }
+
+ private boolean preConfigurationCheck(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!");
+ return provider.isNodeActive(nodeIdent);
+ }
+}
+
--- /dev/null
+/**ab
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GroupForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Flow} and ForwardingRulesCommiter interface for methods:
+ * add, update and remove {@link Flow} processing for
+ * {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class FlowForwarder extends AbstractListeningCommiter<Flow> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowForwarder.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ public FlowForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+ super(manager, Flow.class);
+ Preconditions.checkNotNull(db, "DataBroker can not be null!");
+ this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), FlowForwarder.this, DataChangeScope.BASE);
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (Exception e) {
+ LOG.error("Error by stop FRM FlowChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ }
+
+ @Override
+ public void remove(final InstanceIdentifier<Flow> identifier,
+ final Flow removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, removeDataObj)) {
+ final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(removeDataObj);
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalFlowService().removeFlow(builder.build());
+ }
+ }
+
+ @Override
+ public void update(final InstanceIdentifier<Flow> identifier,
+ final Flow original, final Flow update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, update)) {
+ final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ builder.setUpdatedFlow((new UpdatedFlowBuilder(update)).build());
+ builder.setOriginalFlow((new OriginalFlowBuilder(original)).build());
+
+ this.provider.getSalFlowService().updateFlow(builder.build());
+ }
+ }
+
+ @Override
+ public void add(final InstanceIdentifier<Flow> identifier,
+ final Flow addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, addDataObj)) {
+ final AddFlowInputBuilder builder = new AddFlowInputBuilder(addDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalFlowService().addFlow(builder.build());
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<Flow> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class)
+ .augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+ }
+
+ private boolean tableIdValidationPrecondition (final TableKey tableKey, final Flow flow) {
+ Preconditions.checkNotNull(tableKey, "TableKey can not be null or empty!");
+ Preconditions.checkNotNull(flow, "Flow can not be null or empty!");
+ if (flow.getTableId() != tableKey.getId()) {
+ LOG.error("TableID in URI tableId={} and in palyload tableId={} is not same.",
+ flow.getTableId(), tableKey.getId());
+ return false;
+ }
+ return true;
+ }
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.frm.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.frm.FlowNodeReconciliation;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm
+ *
+ * FlowNode Reconciliation Listener
+ * Reconciliation for a new FlowNode
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Jun 13, 2014
+ */
+public class FlowNodeReconciliationImpl implements FlowNodeReconciliation {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconciliationImpl.class);
+
+ private final ForwardingRulesManager provider;
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ public FlowNodeReconciliationImpl (final ForwardingRulesManager manager, final DataBroker db) {
+ this.provider = Preconditions.checkNotNull(manager, "ForwardingRulesManager can not be null!");
+ Preconditions.checkNotNull(db, "DataBroker can not be null!");
+ /* Build Path */
+ InstanceIdentifier<FlowCapableNode> flowNodeWildCardIdentifier = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class).augmentation(FlowCapableNode.class);
+ this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ flowNodeWildCardIdentifier, FlowNodeReconciliationImpl.this, DataChangeScope.BASE);
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (Exception e) {
+ LOG.error("Error by stop FRM FlowNodeReconilListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+ /* All DataObjects for create */
+ final Set<InstanceIdentifier<?>> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData().keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+
+ for (InstanceIdentifier<?> entryKey : removeData) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
+ .firstIdentifierOf(FlowCapableNode.class);
+ if ( ! nodeIdent.isWildcarded()) {
+ flowNodeDisconnected(nodeIdent);
+ }
+ }
+ for (InstanceIdentifier<?> entryKey : createdData) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
+ .firstIdentifierOf(FlowCapableNode.class);
+ if ( ! nodeIdent.isWildcarded()) {
+ flowNodeConnected(nodeIdent);
+ }
+ }
+ }
+
+ @Override
+ public void flowNodeDisconnected(InstanceIdentifier<FlowCapableNode> disconnectedNode) {
+ provider.unregistrateNode(disconnectedNode);
+ }
+
+ @Override
+ public void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode) {
+ if ( ! provider.isNodeActive(connectedNode)) {
+ provider.registrateNewNode(connectedNode);
+ reconciliation(connectedNode);
+ }
+ }
+
+ private void reconciliation(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ ReadOnlyTransaction trans = provider.getReadTranaction();
+ Optional<FlowCapableNode> flowNode = Optional.absent();
+
+ try {
+ flowNode = trans.read(LogicalDatastoreType.CONFIGURATION, nodeIdent).get();
+ }
+ catch (Exception e) {
+ LOG.error("Fail with read Config/DS for Node {} !", nodeIdent, e);
+ }
+
+ if (flowNode.isPresent()) {
+ /* Groups - have to be first */
+ List<Group> groups = flowNode.get().getGroup() != null
+ ? flowNode.get().getGroup() : Collections.<Group> emptyList();
+ for (Group group : groups) {
+ final KeyedInstanceIdentifier<Group, GroupKey> groupIdent =
+ nodeIdent.child(Group.class, group.getKey());
+ this.provider.getGroupCommiter().add(groupIdent, group, nodeIdent);
+ }
+ /* Meters */
+ List<Meter> meters = flowNode.get().getMeter() != null
+ ? flowNode.get().getMeter() : Collections.<Meter> emptyList();
+ for (Meter meter : meters) {
+ final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent =
+ nodeIdent.child(Meter.class, meter.getKey());
+ this.provider.getMeterCommiter().add(meterIdent, meter, nodeIdent);
+ }
+ /* Flows */
+ List<Table> tables = flowNode.get().getTable() != null
+ ? flowNode.get().getTable() : Collections.<Table> emptyList();
+ for (Table table : tables) {
+ final KeyedInstanceIdentifier<Table, TableKey> tableIdent =
+ nodeIdent.child(Table.class, table.getKey());
+ List<Flow> flows = table.getFlow() != null ? table.getFlow() : Collections.<Flow> emptyList();
+ for (Flow flow : flows) {
+ final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent =
+ tableIdent.child(Flow.class, flow.getKey());
+ this.provider.getFlowCommiter().add(flowIdent, flow, nodeIdent);
+ }
+ }
+ }
+ /* clean transaction */
+ trans.close();
+ }
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.frm.impl;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.frm.FlowNodeReconciliation;
+import org.opendaylight.controller.frm.ForwardingRulesCommiter;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
+/**
+ * forwardingrules-manager
+ * org.opendaylight.controller.frm.impl
+ *
+ * Manager and middle point for whole module.
+ * It contains ActiveNodeHolder and provide all RPC services.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Aug 25, 2014
+ */
+public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
+
+ private final AtomicLong txNum = new AtomicLong();
+ private final Object lockObj = new Object();
+ private Set<InstanceIdentifier<FlowCapableNode>> activeNodes = Collections.emptySet();
+
+ private final DataBroker dataService;
+ private final SalFlowService salFlowService;
+ private final SalGroupService salGroupService;
+ private final SalMeterService salMeterService;
+
+ private ForwardingRulesCommiter<Flow> flowListener;
+ private ForwardingRulesCommiter<Group> groupListener;
+ private ForwardingRulesCommiter<Meter> meterListener;
+ private FlowNodeReconciliation nodeListener;
+
+ public ForwardingRulesManagerImpl(final DataBroker dataBroker,
+ final RpcConsumerRegistry rpcRegistry) {
+ this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
+
+ Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
+
+ this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
+ "RPC SalFlowService not found.");
+ this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
+ "RPC SalGroupService not found.");
+ this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
+ "RPC SalMeterService not found.");
+ }
+
+ @Override
+ public void start() {
+ this.flowListener = new FlowForwarder(this, dataService);
+ this.groupListener = new GroupForwarder(this, dataService);
+ this.meterListener = new MeterForwarder(this, dataService);
+ this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
+ LOG.info("ForwardingRulesManager has started successfull.");
+ }
+
+ @Override
+ public void close() throws Exception {
+ if(this.flowListener != null) {
+ this.flowListener.close();
+ this.flowListener = null;
+ }
+ if (this.groupListener != null) {
+ this.groupListener.close();
+ this.groupListener = null;
+ }
+ if (this.meterListener != null) {
+ this.meterListener.close();
+ this.meterListener = null;
+ }
+ if (this.nodeListener != null) {
+ this.nodeListener.close();
+ this.nodeListener = null;
+ }
+ }
+
+ @Override
+ public ReadOnlyTransaction getReadTranaction() {
+ return dataService.newReadOnlyTransaction();
+ }
+
+ @Override
+ public String getNewTransactionId() {
+ return "DOM-" + txNum.getAndIncrement();
+ }
+
+ @Override
+ public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident) {
+ return activeNodes.contains(ident);
+ }
+
+ @Override
+ public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident) {
+ if ( ! activeNodes.contains(ident)) {
+ synchronized (lockObj) {
+ if ( ! activeNodes.contains(ident)) {
+ Set<InstanceIdentifier<FlowCapableNode>> set =
+ Sets.newHashSet(activeNodes);
+ set.add(ident);
+ activeNodes = Collections.unmodifiableSet(set);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident) {
+ if (activeNodes.contains(ident)) {
+ synchronized (lockObj) {
+ if (activeNodes.contains(ident)) {
+ Set<InstanceIdentifier<FlowCapableNode>> set =
+ Sets.newHashSet(activeNodes);
+ set.remove(ident);
+ activeNodes = Collections.unmodifiableSet(set);
+ }
+ }
+ }
+ }
+
+ @Override
+ public SalFlowService getSalFlowService() {
+ return salFlowService;
+ }
+
+ @Override
+ public SalGroupService getSalGroupService() {
+ return salGroupService;
+ }
+
+ @Override
+ public SalMeterService getSalMeterService() {
+ return salMeterService;
+ }
+
+ @Override
+ public ForwardingRulesCommiter<Flow> getFlowCommiter() {
+ return flowListener;
+ }
+
+ @Override
+ public ForwardingRulesCommiter<Group> getGroupCommiter() {
+ return groupListener;
+ }
+
+ @Override
+ public ForwardingRulesCommiter<Meter> getMeterCommiter() {
+ return meterListener;
+ }
+
+ @Override
+ public FlowNodeReconciliation getFlowNodeReconciliation() {
+ return nodeListener;
+ }
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GroupForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Group} and ForwardingRulesCommiter interface for methods:
+ * add, update and remove {@link Group} processing for
+ * {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class GroupForwarder extends AbstractListeningCommiter<Group> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GroupForwarder.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ public GroupForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+ super(manager, Group.class);
+ Preconditions.checkNotNull(db, "DataBroker can not be null!");
+ this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), GroupForwarder.this, DataChangeScope.BASE);
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (Exception e) {
+ LOG.error("Error by stop FRM GroupChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<Group> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class)
+ .augmentation(FlowCapableNode.class).child(Group.class);
+ }
+
+ @Override
+ public void remove(final InstanceIdentifier<Group> identifier, final Group removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final Group group = (removeDataObj);
+ final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setGroupRef(new GroupRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalGroupService().removeGroup(builder.build());
+ }
+
+ @Override
+ public void update(final InstanceIdentifier<Group> identifier,
+ final Group original, final Group update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final Group originalGroup = (original);
+ final Group updatedGroup = (update);
+ final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setGroupRef(new GroupRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ builder.setUpdatedGroup((new UpdatedGroupBuilder(updatedGroup)).build());
+ builder.setOriginalGroup((new OriginalGroupBuilder(originalGroup)).build());
+
+ this.provider.getSalGroupService().updateGroup(builder.build());
+ }
+
+ @Override
+ public void add(final InstanceIdentifier<Group> identifier, final Group addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final Group group = (addDataObj);
+ final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setGroupRef(new GroupRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalGroupService().addGroup(builder.build());
+ }
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.frm.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.frm.ForwardingRulesManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MeterForwarder
+ * It implements {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}}
+ * for WildCardedPath to {@link Meter} and ForwardingRulesCommiter interface for methods:
+ * add, update and remove {@link Meter} processing for
+ * {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class MeterForwarder extends AbstractListeningCommiter<Meter> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MeterForwarder.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ public MeterForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+ super(manager, Meter.class);
+ Preconditions.checkNotNull(db, "DataBroker can not be null!");
+ this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), MeterForwarder.this, DataChangeScope.BASE);
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (Exception e) {
+ LOG.error("Error by stop FRM MeterChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<Meter> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class)
+ .augmentation(FlowCapableNode.class).child(Meter.class);
+ }
+
+ @Override
+ public void remove(final InstanceIdentifier<Meter> identifier, final Meter removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(removeDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setMeterRef(new MeterRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalMeterService().removeMeter(builder.build());
+ }
+
+ @Override
+ public void update(final InstanceIdentifier<Meter> identifier,
+ final Meter original, final Meter update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setMeterRef(new MeterRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ builder.setUpdatedMeter((new UpdatedMeterBuilder(update)).build());
+ builder.setOriginalMeter((new OriginalMeterBuilder(original)).build());
+
+ this.provider.getSalMeterService().updateMeter(builder.build());
+ }
+
+ @Override
+ public void add(final InstanceIdentifier<Meter> identifier, final Meter addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ final AddMeterInputBuilder builder = new AddMeterInputBuilder(addDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent));
+ builder.setMeterRef(new MeterRef(identifier));
+ builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+ this.provider.getSalMeterService().addMeter(builder.build());
+ }
+}
+
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.meter;
-
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Meter Change Listener
- * add, update and remove {@link Meter} processing from {@link org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class MeterChangeListener extends AbstractChangeListener {
-
- private static final Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
-
- private final MeterProvider provider;
-
- public MeterChangeListener (final MeterProvider provider) {
- this.provider = Preconditions.checkNotNull(provider, "MeterProvider can not be null !");
- }
-
- @Override
- protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject removeDataObj) {
-
- final Meter meter = ((Meter) removeDataObj);
- final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
- final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
-
- builder.setNode(new NodeRef(nodeIdent));
- builder.setMeterRef(new MeterRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalMeterService().removeMeter(builder.build());
- LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj});
- }
-
- @Override
- protected void update(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update) {
-
- final Meter originalMeter = ((Meter) original);
- final Meter updatedMeter = ((Meter) update);
- final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
- final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
-
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
-
- builder.setUpdatedMeter((new UpdatedMeterBuilder(updatedMeter)).build());
- builder.setOriginalMeter((new OriginalMeterBuilder(originalMeter)).build());
-
- this.provider.getSalMeterService().updateMeter(builder.build());
- LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update});
-
- }
-
- @Override
- protected void add(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject addDataObj) {
-
- final Meter meter = ((Meter) addDataObj);
- final InstanceIdentifier<Node> nodeInstanceId = identifier.firstIdentifierOf(Node.class);
- final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
-
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(identifier));
-
- Uri uri = new Uri(this.getTransactionId());
- builder.setTransactionUri(uri);
- this.provider.getSalMeterService().addMeter(builder.build());
- LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj});
- }
-
- @Override
- protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject dataObj, final DataObject update) {
-
- final ReadOnlyTransaction trans = this.provider.getDataService().newReadOnlyTransaction();
- return update != null
- ? (dataObj instanceof Meter && update instanceof Meter && isNodeAvailable(identifier, trans))
- : (dataObj instanceof Meter && isNodeAvailable(identifier, trans));
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.frm.meter;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Meter Provider registers the {@link MeterChangeListener} and it holds all needed
- * services for {@link MeterChangeListener}.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- */
-public class MeterProvider implements AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
-
- private SalMeterService salMeterService;
- private DataBroker dataService;
-
- /* DataChangeListener */
- private DataChangeListener meterDataChangeListener;
- private ListenerRegistration<DataChangeListener> meterDataChangeListenerRegistration;
-
- /**
- * Provider Initialization Phase.
- *
- * @param DataProviderService dataService
- */
- public void init(final DataBroker dataService) {
- LOG.info("FRM Meter Config Provider initialization.");
- this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
- }
-
- /**
- * Listener Registration Phase
- *
- * @param RpcConsumerRegistry rpcRegistry
- */
- public void start(final RpcConsumerRegistry rpcRegistry) {
- Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
- this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
- "RPC SalMeterService not found.");
-
- /* Build Path */
- InstanceIdentifier<Meter> meterIdentifier = InstanceIdentifier.create(Nodes.class)
- .child(Node.class).augmentation(FlowCapableNode.class).child(Meter.class);
-
- /* DataChangeListener registration */
- this.meterDataChangeListener = new MeterChangeListener(MeterProvider.this);
- this.meterDataChangeListenerRegistration =
- this.dataService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- meterIdentifier, meterDataChangeListener, DataChangeScope.SUBTREE);
-
- LOG.info("FRM Meter Config Provider started.");
- }
-
- @Override
- public void close() {
- LOG.info("FRM Meter Config Provider stopped.");
- if (meterDataChangeListenerRegistration != null) {
- try {
- meterDataChangeListenerRegistration.close();
- } catch (Exception e) {
- String errMsg = "Error by stop FRM Meter Config Provider.";
- LOG.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
- } finally {
- meterDataChangeListenerRegistration = null;
- }
- }
- }
-
- public DataChangeListener getMeterDataChangeListener() {
- return meterDataChangeListener;
- }
-
- public DataBroker getDataService() {
- return dataService;
- }
-
- public SalMeterService getSalMeterService() {
- return salMeterService;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.frm.reconil;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import org.opendaylight.controller.frm.AbstractChangeListener;
-import org.opendaylight.controller.frm.FlowCookieProducer;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * FlowNode Reconciliation Listener
- * Reconciliation for a new FlowNode
- * Remove CookieMapKey for removed FlowNode
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public class FlowNodeReconcilListener extends AbstractChangeListener {
-
- private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconcilListener.class);
-
- private final FlowNodeReconcilProvider provider;
-
- public FlowNodeReconcilListener(final FlowNodeReconcilProvider provider) {
- this.provider = Preconditions.checkNotNull(provider, "Flow Node Reconcil Provider can not be null!");
- }
-
- @Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
- /* FlowCapableNode DataObjects for reconciliation */
- final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
- changeEvent.getCreatedData().entrySet();
- /* FlowCapableNode DataObjects for clean FlowCookieHolder */
- final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
- changeEvent.getRemovedPaths();
- for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
- InstanceIdentifier<? extends DataObject> entryKey = createdEntry.getKey();
- DataObject entryValue = createdEntry.getValue();
- if (preconditionForChange(entryKey, entryValue, null)) {
- this.add(entryKey, entryValue);
- }
- }
- for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
- Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
- changeEvent.getOriginalData();
- final DataObject removeValue = origConfigData.get(instanceId);
- if (preconditionForChange(instanceId, removeValue, null)) {
- this.remove(instanceId, removeValue);
- }
- }
- }
-
- @Override
- /* Cleaning FlowCookieManager holder for all node tables */
- protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject removeDataObj) {
-
- final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
- identifier.firstIdentifierOf(FlowCapableNode.class);
- final FlowCapableNode flowNode = ((FlowCapableNode) removeDataObj);
-
- for (Table flowTable : flowNode.getTable()) {
- final InstanceIdentifier<Table> tableIdent =
- flowNodeIdent.child(Table.class, flowTable.getKey());
- FlowCookieProducer.INSTANCE.clean(tableIdent);
- }
- }
-
- @Override
- /* Reconciliation by connect new FlowCapableNode */
- protected void add(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject addDataObj) {
-
- final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
- identifier.firstIdentifierOf(FlowCapableNode.class);
- final Optional<FlowCapableNode> flowCapNode = this.readFlowCapableNode(flowNodeIdent);
-
- if (flowCapNode.isPresent()) {
- final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
- final NodeRef nodeRef = new NodeRef(nodeIdent);
- /* Groups - have to be first */
- List<Group> groups = flowCapNode.get().getGroup();
- if(groups != null) {
- for (Group group : groups) {
- final GroupRef groupRef = new GroupRef(flowNodeIdent.child(Group.class, group.getKey()));
- final AddGroupInputBuilder groupBuilder = new AddGroupInputBuilder(group);
- groupBuilder.setGroupRef(groupRef);
- groupBuilder.setNode(nodeRef);
- this.provider.getSalGroupService().addGroup(groupBuilder.build());
- }
- }
- /* Meters */
- List<Meter> meters = flowCapNode.get().getMeter();
- if(meters != null) {
- for (Meter meter : meters) {
- final MeterRef meterRef = new MeterRef(flowNodeIdent.child(Meter.class, meter.getKey()));
- final AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder(meter);
- meterBuilder.setMeterRef(meterRef);
- meterBuilder.setNode(nodeRef);
- this.provider.getSalMeterService().addMeter(meterBuilder.build());
- }
- }
- /* Flows */
- List<Table> tables = flowCapNode.get().getTable();
- if(tables != null) {
- for (Table flowTable : tables) {
- final InstanceIdentifier<Table> tableIdent = flowNodeIdent.child(Table.class, flowTable.getKey());
- List<Flow> flows = flowTable.getFlow();
- if(flows != null) {
- for (Flow flow : flows) {
- final FlowCookie flowCookie = new FlowCookie(FlowCookieProducer.INSTANCE.getNewCookie(tableIdent));
- final FlowRef flowRef = new FlowRef(tableIdent.child(Flow.class, flow.getKey()));
- final FlowTableRef flowTableRef = new FlowTableRef(tableIdent);
- final AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder(flow);
- flowBuilder.setCookie(flowCookie);
- flowBuilder.setNode(nodeRef);
- flowBuilder.setFlowTable(flowTableRef);
- flowBuilder.setFlowRef(flowRef);
- this.provider.getSalFlowService().addFlow(flowBuilder.build());
- }
- }
- }
- }
- }
- }
-
- @Override
- protected void update(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject original, final DataObject update) {
- // NOOP - Listener is registered for DataChangeScope.BASE only
- }
-
- @Override
- protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
- final DataObject dataObj, final DataObject update) {
- return (dataObj instanceof FlowCapableNode);
- }
-
- private Optional<FlowCapableNode> readFlowCapableNode(final InstanceIdentifier<FlowCapableNode> flowNodeIdent) {
- ReadOnlyTransaction readTrans = this.provider.getDataService().newReadOnlyTransaction();
- try {
- ListenableFuture<Optional<FlowCapableNode>> confFlowNode =
- readTrans.read(LogicalDatastoreType.CONFIGURATION, flowNodeIdent);
- if (confFlowNode.get().isPresent()) {
- return Optional.<FlowCapableNode> of(confFlowNode.get().get());
- } else {
- return Optional.absent();
- }
- }
- catch (InterruptedException | ExecutionException e) {
- LOG.error("Unexpected exception by reading flow ".concat(flowNodeIdent.toString()), e);
- return Optional.absent();
- }
- finally {
- readTrans.close();
- }
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.frm.reconil;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * forwardingrules-manager
- * org.opendaylight.controller.frm
- *
- * FlowNode Reconciliation Provider registers the FlowNodeReconilListener
- * and it holds all needed services for FlowNodeReconcilListener.
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Jun 13, 2014
- */
-public class FlowNodeReconcilProvider implements AutoCloseable {
-
- private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconcilProvider.class);
-
- private SalFlowService salFlowService;
- private SalMeterService salMeterService;
- private SalGroupService salGroupService;
- private DataBroker dataService;
-
- /* DataChangeListener */
- private DataChangeListener flowNodeReconcilListener;
- private ListenerRegistration<DataChangeListener> flowNodeReconcilListenerRegistration;
-
- public void init (final DataBroker dataService) {
- LOG.info("FRM Flow Node Config Reconcil Provider initialization.");
-
- this.dataService = Preconditions.checkNotNull(dataService, "DataProviderService can not be null !");
- }
-
- public void start( final RpcConsumerRegistry rpcRegistry ) {
- Preconditions.checkArgument(rpcRegistry != null, "RpcConcumerRegistry can not be null !");
-
- this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
- "RPC SalFlowService not found.");
- this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
- "RPC SalMeterService not found.");
- this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
- "RPC SalGroupService not found.");
-
- /* Build Path */
- InstanceIdentifier<FlowCapableNode> flowCapableNodeIdent =
- InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
-
- /* ReconcilNotificationListener registration */
- this.flowNodeReconcilListener = new FlowNodeReconcilListener(FlowNodeReconcilProvider.this);
- this.flowNodeReconcilListenerRegistration = this.dataService.registerDataChangeListener(
- LogicalDatastoreType.OPERATIONAL, flowCapableNodeIdent, flowNodeReconcilListener, DataChangeScope.BASE);
- LOG.info("FRM Flow Node Config Reconcil Provider started.");
- }
-
- @Override
- public void close() {
- LOG.info("FRM Flow Node Config Reconcil Provider stopped.");
- if (flowNodeReconcilListenerRegistration != null) {
- try {
- flowNodeReconcilListenerRegistration.close();
- } catch (Exception e) {
- String errMsg = "Error by stop FRM Flow Node Config Reconcil Provider.";
- LOG.error(errMsg, e);
- throw new IllegalStateException(errMsg, e);
- } finally {
- flowNodeReconcilListenerRegistration = null;
- }
- }
- }
-
- public DataChangeListener getFlowNodeReconcilListener() {
- return flowNodeReconcilListener;
- }
-
- public DataBroker getDataService() {
- return dataService;
- }
-
- public SalFlowService getSalFlowService() {
- return salFlowService;
- }
-
- public SalMeterService getSalMeterService() {
- return salMeterService;
- }
-
- public SalGroupService getSalGroupService() {
- return salGroupService;
- }
-}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalFlowServiceMock;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class FlowListenerTest extends FRMTest {
+ RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+ NodeKey s1Key = new NodeKey(new NodeId("S1"));
+ TableKey tableKey = new TableKey((short) 2);
+
+ @Test
+ public void addTwoFlowsTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+ InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+ InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+ Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+ assertEquals(1, addFlowCalls.size());
+ assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+ flowKey = new FlowKey(new FlowId("test_Flow2"));
+ flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ addFlowCalls = salFlowService.getAddFlowCalls();
+ assertEquals(2, addFlowCalls.size());
+ assertEquals("DOM-1", addFlowCalls.get(1).getTransactionUri().getValue());
+ assertEquals(2, addFlowCalls.get(1).getTableId().intValue());
+ assertEquals(flowII, addFlowCalls.get(1).getFlowRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void updateFlowTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+ InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+ InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+ Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+ assertEquals(1, addFlowCalls.size());
+ assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+ flowKey = new FlowKey(new FlowId("test_Flow"));
+ flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).setOutGroup((long) 5).build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
+ assertEquals(1, updateFlowCalls.size());
+ assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
+ assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void updateFlowScopeTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+ InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+ InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+ IpMatch ipMatch = new IpMatchBuilder().setIpDscp(new Dscp((short)4)).build();
+ Match match = new MatchBuilder().setIpMatch(ipMatch).build();
+ Flow flow = new FlowBuilder().setMatch(match).setKey(flowKey).setTableId((short) 2).build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+ assertEquals(1, addFlowCalls.size());
+ assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+ flowKey = new FlowKey(new FlowId("test_Flow"));
+ flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ ipMatch = new IpMatchBuilder().setIpDscp(new Dscp((short)5)).build();
+ match = new MatchBuilder().setIpMatch(ipMatch).build();
+ flow = new FlowBuilder().setMatch(match).setKey(flowKey).setTableId((short) 2).build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
+ assertEquals(1, updateFlowCalls.size());
+ assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
+ assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
+ assertEquals(ipMatch, updateFlowCalls.get(0).getUpdatedFlow().getMatch().getIpMatch());
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void deleteFlowTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ FlowKey flowKey = new FlowKey(new FlowId("test_Flow"));
+ InstanceIdentifier<Table> tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey);
+ InstanceIdentifier<Flow> flowII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Table.class, tableKey).child(Flow.class, flowKey);
+ Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.<Flow>emptyList()).build();
+ Flow flow = new FlowBuilder().setKey(flowKey).setTableId((short) 2).build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, tableII, table);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowII, flow);
+ assertCommit(writeTx.submit());
+ SalFlowServiceMock salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<AddFlowInput> addFlowCalls = salFlowService.getAddFlowCalls();
+ assertEquals(1, addFlowCalls.size());
+ assertEquals("DOM-0", addFlowCalls.get(0).getTransactionUri().getValue());
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.CONFIGURATION, flowII);
+ assertCommit(writeTx.submit());
+ salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
+ List<RemoveFlowInput> removeFlowCalls = salFlowService.getRemoveFlowCalls();
+ assertEquals(1, removeFlowCalls.size());
+ assertEquals("DOM-1", removeFlowCalls.get(0).getTransactionUri().getValue());
+ assertEquals(flowII, removeFlowCalls.get(0).getFlowRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalGroupServiceMock;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class GroupListenerTest extends FRMTest {
+ RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+ NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+ @Test
+ public void addTwoGroupsTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+ InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+ Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+ assertCommit(writeTx.submit());
+ SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+ assertEquals(1, addGroupCalls.size());
+ assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+ groupKey = new GroupKey(new GroupId((long) 256));
+ groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+ group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+ assertCommit(writeTx.submit());
+ salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ addGroupCalls = salGroupService.getAddGroupCalls();
+ assertEquals(2, addGroupCalls.size());
+ assertEquals("DOM-1", addGroupCalls.get(1).getTransactionUri().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void updateGroupTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+ InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+ Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+ assertCommit(writeTx.submit());
+ SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+ assertEquals(1, addGroupCalls.size());
+ assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+ group = new GroupBuilder().setKey(groupKey).setGroupName("Group2").build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+ assertCommit(writeTx.submit());
+ salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ List<UpdateGroupInput> updateGroupCalls = salGroupService.getUpdateGroupCalls();
+ assertEquals(1, updateGroupCalls.size());
+ assertEquals("DOM-1", updateGroupCalls.get(0).getTransactionUri().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void removeGroupTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ GroupKey groupKey = new GroupKey(new GroupId((long) 255));
+ InstanceIdentifier<Group> groupII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Group.class, groupKey);
+ Group group = new GroupBuilder().setKey(groupKey).setGroupName("Group1").build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, groupII, group);
+ assertCommit(writeTx.submit());
+ SalGroupServiceMock salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ List<AddGroupInput> addGroupCalls = salGroupService.getAddGroupCalls();
+ assertEquals(1, addGroupCalls.size());
+ assertEquals("DOM-0", addGroupCalls.get(0).getTransactionUri().getValue());
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.CONFIGURATION, groupII);
+ assertCommit(writeTx.submit());
+ salGroupService = (SalGroupServiceMock) forwardingRulesManager.getSalGroupService();
+ List<RemoveGroupInput> removeGroupCalls = salGroupService.getRemoveGroupCalls();
+ assertEquals(1, removeGroupCalls.size());
+ assertEquals("DOM-1", removeGroupCalls.get(0).getTransactionUri().getValue());
+
+ forwardingRulesManager.close();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+import test.mock.util.SalMeterServiceMock;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class MeterListenerTest extends FRMTest {
+ RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+ NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+ @Test
+ public void addTwoMetersTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+ InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+ Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+ assertCommit(writeTx.submit());
+ SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+ assertEquals(1, addMeterCalls.size());
+ assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+ meterKey = new MeterKey(new MeterId((long) 2001));
+ meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+ meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_two").setBarrier(true).build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+ assertCommit(writeTx.submit());
+ salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ addMeterCalls = salMeterService.getAddMeterCalls();
+ assertEquals(2, addMeterCalls.size());
+ assertEquals("DOM-1", addMeterCalls.get(1).getTransactionUri().getValue());
+ assertEquals(meterII, addMeterCalls.get(1).getMeterRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void updateMeterTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+ InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+ Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").setBarrier(false).build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+ assertCommit(writeTx.submit());
+ SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+ assertEquals(1, addMeterCalls.size());
+ assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+ meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_two").setBarrier(true).build();
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+ assertCommit(writeTx.submit());
+ salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ List<UpdateMeterInput> updateMeterCalls = salMeterService.getUpdateMeterCalls();
+ assertEquals(1, updateMeterCalls.size());
+ assertEquals("DOM-1", updateMeterCalls.get(0).getTransactionUri().getValue());
+ assertEquals(meterII, updateMeterCalls.get(0).getMeterRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+ @Test
+ public void removeMeterTest() throws Exception {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ MeterKey meterKey = new MeterKey(new MeterId((long) 2000));
+ InstanceIdentifier<Meter> meterII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class).child(Meter.class, meterKey);
+ Meter meter = new MeterBuilder().setKey(meterKey).setMeterName("meter_one").build();
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, meterII, meter);
+ assertCommit(writeTx.submit());
+ SalMeterServiceMock salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ List<AddMeterInput> addMeterCalls = salMeterService.getAddMeterCalls();
+ assertEquals(1, addMeterCalls.size());
+ assertEquals("DOM-0", addMeterCalls.get(0).getTransactionUri().getValue());
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.CONFIGURATION, meterII);
+ assertCommit(writeTx.submit());
+ salMeterService = (SalMeterServiceMock) forwardingRulesManager.getSalMeterService();
+ List<RemoveMeterInput> removeMeterCalls = salMeterService.getRemoveMeterCalls();
+ assertEquals(1, removeMeterCalls.size());
+ assertEquals("DOM-1", removeMeterCalls.get(0).getTransactionUri().getValue());
+ assertEquals(meterII, removeMeterCalls.get(0).getMeterRef().getValue());
+
+ forwardingRulesManager.close();
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock;
+
+import org.junit.Test;
+import org.opendaylight.controller.frm.impl.ForwardingRulesManagerImpl;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import test.mock.util.FRMTest;
+import test.mock.util.RpcProviderRegistryMock;
+
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class NodeListenerTest extends FRMTest {
+
+ RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
+ NodeKey s1Key = new NodeKey(new NodeId("S1"));
+
+ @Test
+ public void addRemoveNodeTest() throws ExecutionException, InterruptedException {
+ ForwardingRulesManagerImpl forwardingRulesManager = new ForwardingRulesManagerImpl(getDataBroker(), rpcProviderRegistryMock);
+ forwardingRulesManager.start();
+
+ addFlowCapableNode(s1Key);
+
+ InstanceIdentifier<FlowCapableNode> nodeII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key)
+ .augmentation(FlowCapableNode.class);
+
+ boolean nodeActive = forwardingRulesManager.isNodeActive(nodeII);
+ assertTrue(nodeActive);
+
+ removeNode(s1Key);
+
+ nodeActive = forwardingRulesManager.isNodeActive(nodeII);
+ assertFalse(nodeActive);
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock.util;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class AbstractDataBrokerTest extends AbstractSchemaAwareTest {
+
+ private DataBrokerTestCustomizer testCustomizer;
+ private DataBroker dataBroker;
+ private DOMDataBroker domBroker;
+
+
+ @Override
+ protected void setupWithSchema(final SchemaContext context) {
+ testCustomizer = createDataBrokerTestCustomizer();
+ dataBroker = testCustomizer.createDataBroker();
+ domBroker = testCustomizer.createDOMDataBroker();
+ testCustomizer.updateSchema(context);
+ setupWithDataBroker(dataBroker);
+ }
+
+ protected void setupWithDataBroker(final DataBroker dataBroker) {
+ // Intentionally left No-op, subclasses may customize it
+ }
+
+ protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() {
+ return new DataBrokerTestCustomizer();
+ }
+
+ public DataBroker getDataBroker() {
+ return dataBroker;
+ }
+
+ public DOMDataBroker getDomBroker() {
+ return domBroker;
+ }
+
+ protected static final void assertCommit(final ListenableFuture<Void> commit) {
+ try {
+ commit.get(500, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock.util;
+
+import org.junit.Before;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public abstract class AbstractSchemaAwareTest {
+
+ private Iterable<YangModuleInfo> moduleInfos;
+ private SchemaContext schemaContext;
+
+
+ protected Iterable<YangModuleInfo> getModuleInfos() {
+ return BindingReflections.loadModuleInfos();
+ }
+
+
+ @Before
+ public final void setup() {
+ moduleInfos = getModuleInfos();
+ ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+ moduleContext.addModuleInfos(moduleInfos);
+ schemaContext = moduleContext.tryToCreateSchemaContext().get();
+ setupWithSchema(schemaContext);
+ }
+
+ /**
+ * Setups test with Schema context.
+ * This method is called before {@link #setupWithSchemaService(SchemaService)}
+ *
+ * @param context
+ */
+ protected abstract void setupWithSchema(SchemaContext context);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock.util;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import javassist.ClassPool;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class DataBrokerTestCustomizer {
+
+ private DOMDataBroker domDataBroker;
+ private final RuntimeGeneratedMappingServiceImpl mappingService;
+ private final MockSchemaService schemaService;
+ private ImmutableMap<LogicalDatastoreType, DOMStore> datastores;
+ private final BindingToNormalizedNodeCodec bindingToNormalized ;
+
+ public ImmutableMap<LogicalDatastoreType, DOMStore> createDatastores() {
+ return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
+ .put(LogicalDatastoreType.OPERATIONAL, createOperationalDatastore())
+ .put(LogicalDatastoreType.CONFIGURATION,createConfigurationDatastore())
+ .build();
+ }
+
+ public DataBrokerTestCustomizer() {
+ schemaService = new MockSchemaService();
+ ClassPool pool = ClassPool.getDefault();
+ mappingService = new RuntimeGeneratedMappingServiceImpl(pool);
+ DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool));
+ BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
+ GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
+ bindingToNormalized = new BindingToNormalizedNodeCodec(loading, mappingService, codecRegistry);
+ schemaService.registerSchemaContextListener(bindingToNormalized);
+ }
+
+ public DOMStore createConfigurationDatastore() {
+ InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG",
+ MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor());
+ schemaService.registerSchemaContextListener(store);
+ return store;
+ }
+
+ public DOMStore createOperationalDatastore() {
+ InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER",
+ MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor());
+ schemaService.registerSchemaContextListener(store);
+ return store;
+ }
+
+ public DOMDataBroker createDOMDataBroker() {
+ return new DOMDataBrokerImpl(getDatastores(), getCommitCoordinatorExecutor());
+ }
+
+ public ListeningExecutorService getCommitCoordinatorExecutor() {
+ return MoreExecutors.sameThreadExecutor();
+ }
+
+ public DataBroker createDataBroker() {
+ return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService );
+ }
+
+ public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
+ return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor());
+ }
+
+ private SchemaService getSchemaService() {
+ return schemaService;
+ }
+
+ private DOMDataBroker getDOMDataBroker() {
+ if(domDataBroker == null) {
+ domDataBroker = createDOMDataBroker();
+ }
+ return domDataBroker;
+ }
+
+ private synchronized ImmutableMap<LogicalDatastoreType, DOMStore> getDatastores() {
+ if (datastores == null) {
+ datastores = createDatastores();
+ }
+ return datastores;
+ }
+
+ public void updateSchema(final SchemaContext ctx) {
+ schemaService.changeSchema(ctx);
+ mappingService.onGlobalContextUpdated(ctx);
+ }
+
+}
--- /dev/null
+package test.mock.util;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+
+public abstract class FRMTest extends AbstractDataBrokerTest{
+
+ public void addFlowCapableNode(NodeKey nodeKey) throws ExecutionException, InterruptedException {
+ Nodes nodes = new NodesBuilder().setNode(Collections.<Node>emptyList()).build();
+ InstanceIdentifier<Node> flowNodeIdentifier = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, nodeKey);
+
+ FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder();
+ NodeBuilder nodeBuilder = new NodeBuilder();
+ nodeBuilder.setKey(nodeKey);
+ nodeBuilder.addAugmentation(FlowCapableNode.class, fcnBuilder.build());
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes);
+ writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, nodeBuilder.build());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, nodeBuilder.build());
+ assertCommit(writeTx.submit());
+ }
+
+ public void removeNode(NodeKey nodeKey) throws ExecutionException, InterruptedException {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class).child(Node.class, nodeKey));
+ writeTx.submit().get();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package test.mock.util;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+
+@SuppressWarnings("deprecation")
+public final class MockSchemaService implements SchemaService, SchemaContextProvider {
+
+ private SchemaContext schemaContext;
+
+ ListenerRegistry<SchemaContextListener> listeners = ListenerRegistry.create();
+
+ @Override
+ public void addModule(final Module module) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized SchemaContext getGlobalContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public synchronized SchemaContext getSessionContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+ final SchemaContextListener listener) {
+ return listeners.register(listener);
+ }
+
+ @Override
+ public void removeModule(final Module module) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public synchronized void changeSchema(final SchemaContext newContext) {
+ schemaContext = newContext;
+ for (ListenerRegistration<SchemaContextListener> listener : listeners) {
+ listener.getInstance().onGlobalContextUpdated(schemaContext);
+ }
+ }
+}
--- /dev/null
+package test.mock.util;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public class RpcProviderRegistryMock implements RpcProviderRegistry {
+ @Override
+ public <T extends RpcService> BindingAwareBroker.RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
+ return null;
+ }
+
+ @Override
+ public <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
+ return null;
+ }
+
+ @Override
+ public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
+ return null;
+ }
+
+ @Override
+ public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
+ if (serviceInterface.equals(SalFlowService.class)) {
+ return (T) new SalFlowServiceMock();
+ } else if (serviceInterface.equals(SalGroupService.class)) {
+ return (T) new SalGroupServiceMock();
+ } else if (serviceInterface.equals(SalMeterService.class)) {
+ return (T) new SalMeterServiceMock();
+ } else {
+ return null;
+ }
+ }
+}
--- /dev/null
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalFlowServiceMock implements SalFlowService{
+ private List<AddFlowInput> addFlowCalls = new ArrayList<>();
+ private List<RemoveFlowInput> removeFlowCalls = new ArrayList<>();
+ private List<UpdateFlowInput> updateFlowCalls = new ArrayList<>();
+
+ @Override
+ public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
+ addFlowCalls.add(input);
+ return null;
+ }
+
+
+ @Override
+ public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
+ removeFlowCalls.add(input);
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
+ updateFlowCalls.add(input);
+ return null;
+ }
+
+ public List<AddFlowInput> getAddFlowCalls() {
+ return addFlowCalls;
+ }
+
+ public List<RemoveFlowInput> getRemoveFlowCalls() {
+ return removeFlowCalls;
+ }
+
+ public List<UpdateFlowInput> getUpdateFlowCalls() {
+ return updateFlowCalls;
+ }
+}
--- /dev/null
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalGroupServiceMock implements SalGroupService {
+ private List<AddGroupInput> addGroupCalls = new ArrayList<>();
+ private List<RemoveGroupInput> removeGroupCalls = new ArrayList<>();
+ private List<UpdateGroupInput> updateGroupCalls = new ArrayList<>();
+
+ @Override
+ public Future<RpcResult<AddGroupOutput>> addGroup(AddGroupInput input) {
+ addGroupCalls.add(input);
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<RemoveGroupOutput>> removeGroup(RemoveGroupInput input) {
+ removeGroupCalls.add(input);
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<UpdateGroupOutput>> updateGroup(UpdateGroupInput input) {
+ updateGroupCalls.add(input);
+ return null;
+ }
+
+ public List<AddGroupInput> getAddGroupCalls() {
+ return addGroupCalls;
+ }
+
+ public List<RemoveGroupInput> getRemoveGroupCalls() {
+ return removeGroupCalls;
+ }
+
+ public List<UpdateGroupInput> getUpdateGroupCalls() {
+ return updateGroupCalls;
+ }
+}
--- /dev/null
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalMeterServiceMock implements SalMeterService {
+ private List<AddMeterInput> addMeterCalls = new ArrayList<>();
+ private List<RemoveMeterInput> removeMeterCalls = new ArrayList<>();
+ private List<UpdateMeterInput> updateMeterCalls = new ArrayList<>();
+
+ @Override
+ public Future<RpcResult<AddMeterOutput>> addMeter(AddMeterInput input) {
+ addMeterCalls.add(input);
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<RemoveMeterOutput>> removeMeter(RemoveMeterInput input) {
+ removeMeterCalls.add(input);
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<UpdateMeterOutput>> updateMeter(UpdateMeterInput input) {
+ updateMeterCalls.add(input);
+ return null;
+ }
+
+ public List<AddMeterInput> getAddMeterCalls() {
+ return addMeterCalls;
+ }
+
+ public List<RemoveMeterInput> getRemoveMeterCalls() {
+ return removeMeterCalls;
+ }
+
+ public List<UpdateMeterInput> getUpdateMeterCalls() {
+ return updateMeterCalls;
+ }
+}
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.opendaylight.controller.sal.rest.impl.RestconfApplication</param-value>
</init-param>
+ <!-- AAA Auth Filter -->
+ <init-param>
+ <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
+ <param-value> org.opendaylight.aaa.sts.TokenAuthFilter</param-value>
+ </init-param>
<load-on-startup>1</load-on-startup>
</servlet>