From 3ed53ef05d371492040ca3e67b98a8cfebdcc76d Mon Sep 17 00:00:00 2001 From: Vaclav Demcak Date: Thu, 28 Aug 2014 17:22:42 +0200 Subject: [PATCH 1/1] FRM performance refactoring: * Interface definitions for FRM functionality * ForwardingRulesManager (old provider) * ForwardingRulesCommiter (DS changeListener/sender for SalServices) * FlowNodeReconciliation (reconcil contract definition) * Centralization Provider/Manager bundle functionality * fix possibility not unique transaction ID * implement active NodeHolder (remove unnecessary Operation/DS check) * Listeners * identify correct data by wildCarded InstanceIdentifier * move registration functionality to listener class * remove all unnecessary functionality * functionality fragmented * Cleaning * move FlowCookie to StatistManager (performance killer, fixing update Flow functionality, possibly speed up delete functionality) * cleaning unnecessary object creation * Added MockTests tests PASS: https://jenkins.opendaylight.org/integration/job/integration-master-csit-base-of13/ (Base-OF13/AD_SAL_NSF/TopologyManager/getTopology sometimes fail) Change-Id: If5ec9920e4574bd170192b14ca978fb628fd051b Signed-off-by: Vaclav Demcak Signed-off-by: Jan Hajnar Signed-off-by: Vaclav Demcak --- .../frm/AbstractChangeListener.java | 173 --------------- .../controller/frm/FRMActivator.java | 67 ++---- .../controller/frm/FlowCookieProducer.java | 79 ------- .../frm/FlowNodeReconciliation.java | 59 +++++ .../frm/ForwardingRulesCommiter.java | 64 ++++++ .../frm/ForwardingRulesManager.java | 125 +++++++++++ .../frm/flow/FlowChangeListener.java | 126 ----------- .../controller/frm/flow/FlowProvider.java | 107 --------- .../frm/group/GroupChangeListener.java | 111 --------- .../controller/frm/group/GroupProvider.java | 105 --------- .../frm/impl/AbstractListeningCommiter.java | 134 +++++++++++ .../controller/frm/impl/FlowForwarder.java | 140 ++++++++++++ .../frm/impl/FlowNodeReconciliationImpl.java | 171 ++++++++++++++ .../frm/impl/ForwardingRulesManagerImpl.java | 185 +++++++++++++++ .../controller/frm/impl/GroupForwarder.java | 118 ++++++++++ .../controller/frm/impl/MeterForwarder.java | 114 ++++++++++ .../frm/meter/MeterChangeListener.java | 112 ---------- .../controller/frm/meter/MeterProvider.java | 105 --------- .../frm/reconil/FlowNodeReconcilListener.java | 196 ---------------- .../frm/reconil/FlowNodeReconcilProvider.java | 115 ---------- .../test/java/test/mock/FlowListenerTest.java | 210 ++++++++++++++++++ .../java/test/mock/GroupListenerTest.java | 137 ++++++++++++ .../java/test/mock/MeterListenerTest.java | 141 ++++++++++++ .../test/java/test/mock/NodeListenerTest.java | 52 +++++ .../mock/util/AbstractDataBrokerTest.java | 60 +++++ .../mock/util/AbstractSchemaAwareTest.java | 44 ++++ .../mock/util/DataBrokerTestCustomizer.java | 111 +++++++++ .../src/test/java/test/mock/util/FRMTest.java | 42 ++++ .../test/mock/util/MockSchemaService.java | 62 ++++++ .../mock/util/RpcProviderRegistryMock.java | 42 ++++ .../test/mock/util/SalFlowServiceMock.java | 51 +++++ .../test/mock/util/SalGroupServiceMock.java | 50 +++++ .../test/mock/util/SalMeterServiceMock.java | 50 +++++ 33 files changed, 2182 insertions(+), 1276 deletions(-) delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java delete mode 100644 opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java create mode 100644 opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java deleted file mode 100644 index 130c096deb..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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, DataObject> changeEvent) { - this.transactionId = this.newTransactionIdentifier().toString(); - /* All DataObjects for create */ - final Set, DataObject>> createdEntries = - changeEvent.getCreatedData().entrySet(); - /* All DataObjects for updates - init HashSet */ - final Set, DataObject>> updatedEntries = new HashSet<>(); - /* Filtered DataObject for update processing only */ - Set, DataObject>> updateConfigEntrySet = - changeEvent.getUpdatedData().entrySet(); - updatedEntries.addAll(updateConfigEntrySet); - updatedEntries.removeAll(createdEntries); - /* All DataObjects for remove */ - final Set> removeEntriesInstanceIdentifiers = - changeEvent.getRemovedPaths(); - /* Create DataObject processing (send to device) */ - for (final Entry, DataObject> createdEntry : createdEntries) { - InstanceIdentifier entryKey = createdEntry.getKey(); - DataObject entryValue = createdEntry.getValue(); - if (preconditionForChange(entryKey, entryValue, null)) { - this.add(entryKey, entryValue); - } - } - - for (final Entry, DataObject> updatedEntrie : updatedEntries) { - Map, DataObject> origConfigData = - changeEvent.getOriginalData(); - - InstanceIdentifier 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, 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 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 identifier, - final ReadOnlyTransaction readTrans) { - final InstanceIdentifier 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 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 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 identifier, - final DataObject add); -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java index c75c644c00..9878d16e57 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java @@ -7,10 +7,7 @@ */ 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; @@ -21,8 +18,7 @@ import org.slf4j.LoggerFactory; /** * 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. * @@ -33,56 +29,33 @@ public class FRMActivator extends AbstractBindingAwareProvider { 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 diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java deleted file mode 100644 index d7b54e8380..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowCookieProducer.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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 Vaclav Demcak - * - * Created: Jun 13, 2014 - */ -public enum FlowCookieProducer { - - INSTANCE; - - /* Flow_Cookie_Key and Flow_Ids MapHolder */ - private static final AtomicLongMap> cookieKeys = AtomicLongMap.create(); - - /** - * Method returns the unique cookie for a node table. - * Flow Cookie Key signs List for a right flow statistic identification - * in the DataStore/operational. - * We need a List 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 tableIdentifier - * @return unique BigInteger flowCookie for a node table - */ - public BigInteger getNewCookie(final InstanceIdentifier
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
tableIdentifier - */ - public void clean(final InstanceIdentifier
tableIdentifier) { - FlowCookieProducer.validationTableIdentifier(tableIdentifier); - cookieKeys.remove(tableIdentifier); - } - - /* - * Help the TableIdentifer input validation method - */ - private static void validationTableIdentifier(final InstanceIdentifier
tableIdent) { - Preconditions.checkArgument(tableIdent != null, "Input validation exception: TableIdentifier can not be null !"); - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java new file mode 100644 index 0000000000..fb3178de00 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FlowNodeReconciliation.java @@ -0,0 +1,59 @@ +/** + * 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 Vaclav Demcak + * + * 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 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 disconnectedNode); +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java new file mode 100644 index 0000000000..2228785e95 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesCommiter.java @@ -0,0 +1,64 @@ +/** + * 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 Vaclav Demcak + * + * Created: Aug 25, 2014 + */ +public interface ForwardingRulesCommiter 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 parent Node InstanceIdentifier + */ + void remove(InstanceIdentifier identifier, D del, + InstanceIdentifier 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 identifier, D original, D update, + InstanceIdentifier 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 identifier, D add, + InstanceIdentifier nodeIdent); + +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java new file mode 100644 index 0000000000..504c108d81 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/ForwardingRulesManager.java @@ -0,0 +1,125 @@ +/** + * 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 Vaclav Demcak + * + * Created: Aug 25, 2014 + */ +public interface ForwardingRulesManager extends AutoCloseable { + + public void start(); + + /** + * Method returns information : + * "is Node with send InstanceIdentifier connected"? + * + * @param InstanceIdentifier ident - the key of the node + * @return boolean - is device connected + */ + public boolean isNodeActive(InstanceIdentifier 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 ident - the key of the node + */ + public void registrateNewNode(InstanceIdentifier 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 ident - the key of the node + */ + public void unregistrateNode(InstanceIdentifier 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 + */ + public ForwardingRulesCommiter getFlowCommiter(); + + /** + * Content definition method and prevent code duplicity in Reconcil + * @return ForwardingRulesCommiter + */ + public ForwardingRulesCommiter getGroupCommiter(); + + /** + * Content definition method and prevent code duplicity + * @return ForwardingRulesCommiter + */ + public ForwardingRulesCommiter getMeterCommiter(); + + /** + * Content definition method + * @return FlowNodeReconciliation + */ + public FlowNodeReconciliation getFlowNodeReconciliation(); +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java deleted file mode 100644 index c10b0da2ba..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java +++ /dev/null @@ -1,126 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 identifier, - final DataObject removeDataObj) { - - final Flow flow = ((Flow) removeDataObj); - final InstanceIdentifier
tableIdent = identifier.firstIdentifierOf(Table.class); - final InstanceIdentifier 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 identifier, - final DataObject original, final DataObject update) { - - final Flow originalFlow = ((Flow) original); - final Flow updatedFlow = ((Flow) update); - final InstanceIdentifier 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 identifier, - final DataObject addDataObj) { - - final Flow flow = ((Flow) addDataObj); - final InstanceIdentifier
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 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)); - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java deleted file mode 100644 index 8c248fa264..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 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 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; - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java deleted file mode 100644 index 9b03eaad8c..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 identifier, - final DataObject removeDataObj) { - - final Group group = ((Group) removeDataObj); - final InstanceIdentifier nodeInstanceId = identifier. 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 identifier, - final DataObject original, final DataObject update) { - - final Group originalGroup = ((Group) original); - final Group updatedGroup = ((Group) update); - final InstanceIdentifier nodeInstanceId = identifier. 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 identifier, - final DataObject addDataObj) { - - final Group group = ((Group) addDataObj); - final InstanceIdentifier nodeInstanceId = identifier. 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 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)); - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java deleted file mode 100644 index a999242bc0..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 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 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; - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java new file mode 100644 index 0000000000..ec49e61834 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/AbstractListeningCommiter.java @@ -0,0 +1,134 @@ +/** + * 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 Vaclav Demcak + * + */ +public abstract class AbstractListeningCommiter implements ForwardingRulesCommiter { + + protected ForwardingRulesManager provider; + + protected final Class clazz; + + public AbstractListeningCommiter (ForwardingRulesManager provider, Class 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, DataObject> changeEvent) { + Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!"); + + /* All DataObjects for create */ + final Map, DataObject> createdData = changeEvent.getCreatedData() != null + ? changeEvent.getCreatedData() : Collections., DataObject> emptyMap(); + /* All DataObjects for remove */ + final Set> removeData = changeEvent.getRemovedPaths() != null + ? changeEvent.getRemovedPaths() : Collections.> emptySet(); + /* All DataObjects for updates */ + final Map, DataObject> updateData = changeEvent.getUpdatedData() != null + ? changeEvent.getUpdatedData() : Collections., DataObject> emptyMap(); + /* All Original DataObjects */ + final Map, DataObject> originalData = changeEvent.getOriginalData() != null + ? changeEvent.getOriginalData() : Collections., 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 getWildCardPath(); + + + + @SuppressWarnings("unchecked") + private void createData(final Map, DataObject> createdData) { + final Set> keys = createdData.keySet() != null + ? createdData.keySet() : Collections.> emptySet(); + for (InstanceIdentifier key : keys) { + if (clazz.equals(key.getTargetType())) { + final InstanceIdentifier nodeIdent = + key.firstIdentifierOf(FlowCapableNode.class); + if (preConfigurationCheck(nodeIdent)) { + InstanceIdentifier createKeyIdent = key.firstIdentifierOf(clazz); + final Optional value = Optional.of(createdData.get(key)); + if (value.isPresent()) { + this.add(createKeyIdent, (T)value.get(), nodeIdent); + } + } + } + } + } + + @SuppressWarnings("unchecked") + private void updateData(final Map, DataObject> updateData, + final Map, DataObject> originalData) { + + final Set> keys = updateData.keySet() != null + ? updateData.keySet() : Collections.> emptySet(); + for (InstanceIdentifier key : keys) { + if (clazz.equals(key.getTargetType())) { + final InstanceIdentifier nodeIdent = + key.firstIdentifierOf(FlowCapableNode.class); + if (preConfigurationCheck(nodeIdent)) { + InstanceIdentifier updateKeyIdent = key.firstIdentifierOf(clazz); + final Optional value = Optional.of(updateData.get(key)); + final Optional 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> removeData, + final Map, DataObject> originalData) { + + for (InstanceIdentifier key : removeData) { + if (clazz.equals(key.getTargetType())) { + final InstanceIdentifier nodeIdent = + key.firstIdentifierOf(FlowCapableNode.class); + if (preConfigurationCheck(nodeIdent)) { + final InstanceIdentifier ident = key.firstIdentifierOf(clazz); + final DataObject removeValue = originalData.get(key); + this.remove(ident, (T)removeValue, nodeIdent); + } + } + } + } + + private boolean preConfigurationCheck(final InstanceIdentifier nodeIdent) { + Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!"); + return provider.isNodeActive(nodeIdent); + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java new file mode 100644 index 0000000000..fd0ddecd1c --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowForwarder.java @@ -0,0 +1,140 @@ +/**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 Vaclav Demcak + * + */ +public class FlowForwarder extends AbstractListeningCommiter { + + private static final Logger LOG = LoggerFactory.getLogger(FlowForwarder.class); + + private ListenerRegistration 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 identifier, + final Flow removeDataObj, + final InstanceIdentifier 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 identifier, + final Flow original, final Flow update, + final InstanceIdentifier 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 identifier, + final Flow addDataObj, + final InstanceIdentifier 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 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; + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java new file mode 100644 index 0000000000..f1e8dfe070 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/FlowNodeReconciliationImpl.java @@ -0,0 +1,171 @@ +/** + * 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 Vaclav Demcak + * + * Created: Jun 13, 2014 + */ +public class FlowNodeReconciliationImpl implements FlowNodeReconciliation { + + private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconciliationImpl.class); + + private final ForwardingRulesManager provider; + + private ListenerRegistration 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 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, DataObject> changeEvent) { + Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!"); + /* All DataObjects for create */ + final Set> createdData = changeEvent.getCreatedData() != null + ? changeEvent.getCreatedData().keySet() : Collections.> emptySet(); + /* All DataObjects for remove */ + final Set> removeData = changeEvent.getRemovedPaths() != null + ? changeEvent.getRemovedPaths() : Collections.> emptySet(); + + for (InstanceIdentifier entryKey : removeData) { + final InstanceIdentifier nodeIdent = entryKey + .firstIdentifierOf(FlowCapableNode.class); + if ( ! nodeIdent.isWildcarded()) { + flowNodeDisconnected(nodeIdent); + } + } + for (InstanceIdentifier entryKey : createdData) { + final InstanceIdentifier nodeIdent = entryKey + .firstIdentifierOf(FlowCapableNode.class); + if ( ! nodeIdent.isWildcarded()) { + flowNodeConnected(nodeIdent); + } + } + } + + @Override + public void flowNodeDisconnected(InstanceIdentifier disconnectedNode) { + provider.unregistrateNode(disconnectedNode); + } + + @Override + public void flowNodeConnected(InstanceIdentifier connectedNode) { + if ( ! provider.isNodeActive(connectedNode)) { + provider.registrateNewNode(connectedNode); + reconciliation(connectedNode); + } + } + + private void reconciliation(final InstanceIdentifier nodeIdent) { + + ReadOnlyTransaction trans = provider.getReadTranaction(); + Optional 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 groups = flowNode.get().getGroup() != null + ? flowNode.get().getGroup() : Collections. emptyList(); + for (Group group : groups) { + final KeyedInstanceIdentifier groupIdent = + nodeIdent.child(Group.class, group.getKey()); + this.provider.getGroupCommiter().add(groupIdent, group, nodeIdent); + } + /* Meters */ + List meters = flowNode.get().getMeter() != null + ? flowNode.get().getMeter() : Collections. emptyList(); + for (Meter meter : meters) { + final KeyedInstanceIdentifier meterIdent = + nodeIdent.child(Meter.class, meter.getKey()); + this.provider.getMeterCommiter().add(meterIdent, meter, nodeIdent); + } + /* Flows */ + List
tables = flowNode.get().getTable() != null + ? flowNode.get().getTable() : Collections.
emptyList(); + for (Table table : tables) { + final KeyedInstanceIdentifier tableIdent = + nodeIdent.child(Table.class, table.getKey()); + List flows = table.getFlow() != null ? table.getFlow() : Collections. emptyList(); + for (Flow flow : flows) { + final KeyedInstanceIdentifier flowIdent = + tableIdent.child(Flow.class, flow.getKey()); + this.provider.getFlowCommiter().add(flowIdent, flow, nodeIdent); + } + } + } + /* clean transaction */ + trans.close(); + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java new file mode 100644 index 0000000000..7cb7acf9a0 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/ForwardingRulesManagerImpl.java @@ -0,0 +1,185 @@ +/** + * 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 Vaclav Demcak + * + * 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> activeNodes = Collections.emptySet(); + + private final DataBroker dataService; + private final SalFlowService salFlowService; + private final SalGroupService salGroupService; + private final SalMeterService salMeterService; + + private ForwardingRulesCommiter flowListener; + private ForwardingRulesCommiter groupListener; + private ForwardingRulesCommiter 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 ident) { + return activeNodes.contains(ident); + } + + @Override + public void registrateNewNode(InstanceIdentifier ident) { + if ( ! activeNodes.contains(ident)) { + synchronized (lockObj) { + if ( ! activeNodes.contains(ident)) { + Set> set = + Sets.newHashSet(activeNodes); + set.add(ident); + activeNodes = Collections.unmodifiableSet(set); + } + } + } + } + + @Override + public void unregistrateNode(InstanceIdentifier ident) { + if (activeNodes.contains(ident)) { + synchronized (lockObj) { + if (activeNodes.contains(ident)) { + Set> 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 getFlowCommiter() { + return flowListener; + } + + @Override + public ForwardingRulesCommiter getGroupCommiter() { + return groupListener; + } + + @Override + public ForwardingRulesCommiter getMeterCommiter() { + return meterListener; + } + + @Override + public FlowNodeReconciliation getFlowNodeReconciliation() { + return nodeListener; + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java new file mode 100644 index 0000000000..77ef162204 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/GroupForwarder.java @@ -0,0 +1,118 @@ +/** + * 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 Vaclav Demcak + * + */ +public class GroupForwarder extends AbstractListeningCommiter { + + private static final Logger LOG = LoggerFactory.getLogger(GroupForwarder.class); + + private ListenerRegistration 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 getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Group.class); + } + + @Override + public void remove(final InstanceIdentifier identifier, final Group removeDataObj, + final InstanceIdentifier 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 identifier, + final Group original, final Group update, + final InstanceIdentifier 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 identifier, final Group addDataObj, + final InstanceIdentifier 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()); + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java new file mode 100644 index 0000000000..9511fb8775 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/impl/MeterForwarder.java @@ -0,0 +1,114 @@ +/** + * 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 Vaclav Demcak + * + */ +public class MeterForwarder extends AbstractListeningCommiter { + + private static final Logger LOG = LoggerFactory.getLogger(MeterForwarder.class); + + private ListenerRegistration 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 getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Meter.class); + } + + @Override + public void remove(final InstanceIdentifier identifier, final Meter removeDataObj, + final InstanceIdentifier 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 identifier, + final Meter original, final Meter update, + final InstanceIdentifier 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 identifier, final Meter addDataObj, + final InstanceIdentifier 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()); + } +} + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java deleted file mode 100644 index a2def8490f..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 identifier, - final DataObject removeDataObj) { - - final Meter meter = ((Meter) removeDataObj); - final InstanceIdentifier 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 identifier, - final DataObject original, final DataObject update) { - - final Meter originalMeter = ((Meter) original); - final Meter updatedMeter = ((Meter) update); - final InstanceIdentifier 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 identifier, - final DataObject addDataObj) { - - final Meter meter = ((Meter) addDataObj); - final InstanceIdentifier 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 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)); - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java deleted file mode 100644 index 44de7af495..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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 Vaclav Demcak - * - */ -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 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 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; - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java deleted file mode 100644 index 6308f2a9b0..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilListener.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * 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 Vaclav Demcak - * - * 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, DataObject> changeEvent) { - /* FlowCapableNode DataObjects for reconciliation */ - final Set, DataObject>> createdEntries = - changeEvent.getCreatedData().entrySet(); - /* FlowCapableNode DataObjects for clean FlowCookieHolder */ - final Set> removeEntriesInstanceIdentifiers = - changeEvent.getRemovedPaths(); - for (final Entry, DataObject> createdEntry : createdEntries) { - InstanceIdentifier entryKey = createdEntry.getKey(); - DataObject entryValue = createdEntry.getValue(); - if (preconditionForChange(entryKey, entryValue, null)) { - this.add(entryKey, entryValue); - } - } - for (final InstanceIdentifier instanceId : removeEntriesInstanceIdentifiers) { - Map, 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 identifier, - final DataObject removeDataObj) { - - final InstanceIdentifier flowNodeIdent = - identifier.firstIdentifierOf(FlowCapableNode.class); - final FlowCapableNode flowNode = ((FlowCapableNode) removeDataObj); - - for (Table flowTable : flowNode.getTable()) { - final InstanceIdentifier
tableIdent = - flowNodeIdent.child(Table.class, flowTable.getKey()); - FlowCookieProducer.INSTANCE.clean(tableIdent); - } - } - - @Override - /* Reconciliation by connect new FlowCapableNode */ - protected void add(final InstanceIdentifier identifier, - final DataObject addDataObj) { - - final InstanceIdentifier flowNodeIdent = - identifier.firstIdentifierOf(FlowCapableNode.class); - final Optional flowCapNode = this.readFlowCapableNode(flowNodeIdent); - - if (flowCapNode.isPresent()) { - final InstanceIdentifier nodeIdent = identifier.firstIdentifierOf(Node.class); - final NodeRef nodeRef = new NodeRef(nodeIdent); - /* Groups - have to be first */ - List 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 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
tables = flowCapNode.get().getTable(); - if(tables != null) { - for (Table flowTable : tables) { - final InstanceIdentifier
tableIdent = flowNodeIdent.child(Table.class, flowTable.getKey()); - List 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 identifier, - final DataObject original, final DataObject update) { - // NOOP - Listener is registered for DataChangeScope.BASE only - } - - @Override - protected boolean preconditionForChange(final InstanceIdentifier identifier, - final DataObject dataObj, final DataObject update) { - return (dataObj instanceof FlowCapableNode); - } - - private Optional readFlowCapableNode(final InstanceIdentifier flowNodeIdent) { - ReadOnlyTransaction readTrans = this.provider.getDataService().newReadOnlyTransaction(); - try { - ListenableFuture> confFlowNode = - readTrans.read(LogicalDatastoreType.CONFIGURATION, flowNodeIdent); - if (confFlowNode.get().isPresent()) { - return Optional. 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(); - } - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java deleted file mode 100644 index ad970d6043..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/reconil/FlowNodeReconcilProvider.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 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 Vaclav Demcak - * - * 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 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 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; - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java new file mode 100644 index 0000000000..85f4b14472 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java @@ -0,0 +1,210 @@ +/** + * 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
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, tableKey); + InstanceIdentifier 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.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 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
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, tableKey); + InstanceIdentifier 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.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 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 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
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, tableKey); + InstanceIdentifier 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.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 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 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
tableII = InstanceIdentifier.create(Nodes.class).child(Node.class, s1Key) + .augmentation(FlowCapableNode.class).child(Table.class, tableKey); + InstanceIdentifier 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.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 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 removeFlowCalls = salFlowService.getRemoveFlowCalls(); + assertEquals(1, removeFlowCalls.size()); + assertEquals("DOM-1", removeFlowCalls.get(0).getTransactionUri().getValue()); + assertEquals(flowII, removeFlowCalls.get(0).getFlowRef().getValue()); + + forwardingRulesManager.close(); + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java new file mode 100644 index 0000000000..97eb899a72 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java @@ -0,0 +1,137 @@ +/** + * 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 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 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 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 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 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 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 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 removeGroupCalls = salGroupService.getRemoveGroupCalls(); + assertEquals(1, removeGroupCalls.size()); + assertEquals("DOM-1", removeGroupCalls.get(0).getTransactionUri().getValue()); + + forwardingRulesManager.close(); + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java new file mode 100644 index 0000000000..0d32f9f89e --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java @@ -0,0 +1,141 @@ +/** + * 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 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 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 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 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 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 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 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 removeMeterCalls = salMeterService.getRemoveMeterCalls(); + assertEquals(1, removeMeterCalls.size()); + assertEquals("DOM-1", removeMeterCalls.get(0).getTransactionUri().getValue()); + assertEquals(meterII, removeMeterCalls.get(0).getMeterRef().getValue()); + + forwardingRulesManager.close(); + } + +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java new file mode 100644 index 0000000000..3cf2e936af --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java @@ -0,0 +1,52 @@ +/** + * 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 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); + } + + +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java new file mode 100644 index 0000000000..f9efa51d41 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractDataBrokerTest.java @@ -0,0 +1,60 @@ +/* + * 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 commit) { + try { + commit.get(500, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw new IllegalStateException(e); + } + } + + +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java new file mode 100644 index 0000000000..d520d59cdd --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/AbstractSchemaAwareTest.java @@ -0,0 +1,44 @@ +/* + * 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 moduleInfos; + private SchemaContext schemaContext; + + + protected Iterable 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); + +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java new file mode 100644 index 0000000000..36ab41fa68 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/DataBrokerTestCustomizer.java @@ -0,0 +1,111 @@ +/* + * 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 datastores; + private final BindingToNormalizedNodeCodec bindingToNormalized ; + + public ImmutableMap createDatastores() { + return ImmutableMap.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 getDatastores() { + if (datastores == null) { + datastores = createDatastores(); + } + return datastores; + } + + public void updateSchema(final SchemaContext ctx) { + schemaService.changeSchema(ctx); + mappingService.onGlobalContextUpdated(ctx); + } + +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java new file mode 100644 index 0000000000..811d6ca742 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java @@ -0,0 +1,42 @@ +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.emptyList()).build(); + InstanceIdentifier 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(); + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java new file mode 100644 index 0000000000..b4876a3ee0 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/MockSchemaService.java @@ -0,0 +1,62 @@ +/* + * 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 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 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 listener : listeners) { + listener.getInstance().onGlobalContextUpdated(schemaContext); + } + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java new file mode 100644 index 0000000000..ff17a0c366 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java @@ -0,0 +1,42 @@ +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 BindingAwareBroker.RpcRegistration addRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public BindingAwareBroker.RoutedRpcRegistration addRoutedRpcImplementation(Class serviceInterface, T implementation) throws IllegalStateException { + return null; + } + + @Override + public >> ListenerRegistration registerRouteChangeListener(L listener) { + return null; + } + + @Override + public T getRpcService(Class 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; + } + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java new file mode 100644 index 0000000000..4bddc69b43 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalFlowServiceMock.java @@ -0,0 +1,51 @@ +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 addFlowCalls = new ArrayList<>(); + private List removeFlowCalls = new ArrayList<>(); + private List updateFlowCalls = new ArrayList<>(); + + @Override + public Future> addFlow(AddFlowInput input) { + addFlowCalls.add(input); + return null; + } + + + @Override + public Future> removeFlow(RemoveFlowInput input) { + removeFlowCalls.add(input); + return null; + } + + @Override + public Future> updateFlow(UpdateFlowInput input) { + updateFlowCalls.add(input); + return null; + } + + public List getAddFlowCalls() { + return addFlowCalls; + } + + public List getRemoveFlowCalls() { + return removeFlowCalls; + } + + public List getUpdateFlowCalls() { + return updateFlowCalls; + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java new file mode 100644 index 0000000000..9fa7b767c4 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalGroupServiceMock.java @@ -0,0 +1,50 @@ +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 addGroupCalls = new ArrayList<>(); + private List removeGroupCalls = new ArrayList<>(); + private List updateGroupCalls = new ArrayList<>(); + + @Override + public Future> addGroup(AddGroupInput input) { + addGroupCalls.add(input); + return null; + } + + @Override + public Future> removeGroup(RemoveGroupInput input) { + removeGroupCalls.add(input); + return null; + } + + @Override + public Future> updateGroup(UpdateGroupInput input) { + updateGroupCalls.add(input); + return null; + } + + public List getAddGroupCalls() { + return addGroupCalls; + } + + public List getRemoveGroupCalls() { + return removeGroupCalls; + } + + public List getUpdateGroupCalls() { + return updateGroupCalls; + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java new file mode 100644 index 0000000000..fb053cbbd4 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/test/java/test/mock/util/SalMeterServiceMock.java @@ -0,0 +1,50 @@ +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 addMeterCalls = new ArrayList<>(); + private List removeMeterCalls = new ArrayList<>(); + private List updateMeterCalls = new ArrayList<>(); + + @Override + public Future> addMeter(AddMeterInput input) { + addMeterCalls.add(input); + return null; + } + + @Override + public Future> removeMeter(RemoveMeterInput input) { + removeMeterCalls.add(input); + return null; + } + + @Override + public Future> updateMeter(UpdateMeterInput input) { + updateMeterCalls.add(input); + return null; + } + + public List getAddMeterCalls() { + return addMeterCalls; + } + + public List getRemoveMeterCalls() { + return removeMeterCalls; + } + + public List getUpdateMeterCalls() { + return updateMeterCalls; + } +} -- 2.36.6