From: Ed Warnicke Date: Mon, 25 Nov 2013 09:42:51 +0000 (+0000) Subject: Merge "Add prefixes to type attribute in generated xml from netconf Add support for... X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~351 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=e7c8982a45c9ee5789d7ba25bb0324065efbe23e;hp=371bb07d5c970798f247170130c93147890708e8;p=controller.git Merge "Add prefixes to type attribute in generated xml from netconf Add support for parsing prefixed type attributes from incomming xml to netconf" --- diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java index baa2c78253..9740a92598 100644 --- a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java +++ b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java @@ -114,6 +114,17 @@ public class ContainerFlowConfig implements Serializable { //this.unidirectional = false; } + public ContainerFlowConfig(String name, String dlVlan, String srcIP, String dstIP, String proto, String srcPort, + String dstPort) { + this.name = name; + this.dlVlan = dlVlan; + this.nwSrc = srcIP; + this.nwDst = dstIP; + this.protocol = proto; + this.tpSrc = srcPort; + this.tpDst = dstPort; + } + public ContainerFlowConfig(ContainerFlowConfig containerFlowConfig) { this.name = containerFlowConfig.name; diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml index c61b41c065..3ad0c61d4f 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml @@ -62,6 +62,8 @@ + + diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java index 82db78e7b9..2ffe0ecd87 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java @@ -71,7 +71,7 @@ public class FlowConsumerImpl implements IForwardingRulesManager { private IContainer container; private static final String NAMEREGEX = "^[a-zA-Z0-9]+$"; private static ConcurrentMap staticFlows; - private static ConcurrentMap staticFlowsOrdinal; + private static ConcurrentMap staticFlowsOrdinal = new ConcurrentHashMap(); /* * Inactive flow list. This is for the global instance of FRM It will * contain all the flow entries which were installed on the global container @@ -86,7 +86,8 @@ public class FlowConsumerImpl implements IForwardingRulesManager { private boolean inContainerMode; // being used by global instance only public FlowConsumerImpl() { - InstanceIdentifier path = InstanceIdentifier.builder().node(Flows.class).toInstance(); + InstanceIdentifier path = InstanceIdentifier.builder(Flows.class).child(Flow.class) + .toInstance(); flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class); if (null == flowService) { @@ -499,14 +500,13 @@ public class FlowConsumerImpl implements IForwardingRulesManager { @Override public void onNodeErrorNotification(NodeErrorNotification notification) { // TODO Auto-generated method stub - + } @Override - public void onNodeExperimenterErrorNotification( - NodeExperimenterErrorNotification notification) { + public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification notification) { // TODO Auto-generated method stub - + }; } diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java index 8595491016..851e7d9b26 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java @@ -68,8 +68,8 @@ public class GroupConsumerImpl implements IForwardingRulesManager { public GroupConsumerImpl() { - InstanceIdentifier path = InstanceIdentifier.builder().node(Groups.class) - .node(Group.class).toInstance(); + InstanceIdentifier path = InstanceIdentifier.builder(Groups.class).child(Group.class) + .toInstance(); groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class); clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService(); diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java index 7f7db3ba58..bd0ceb3fea 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java @@ -66,8 +66,8 @@ public class MeterConsumerImpl implements IForwardingRulesManager { private IContainer container; public MeterConsumerImpl() { - InstanceIdentifier path = InstanceIdentifier.builder().node(Meters.class) - .node(Meter.class).toInstance(); + InstanceIdentifier path = InstanceIdentifier.builder(Meters.class).child(Meter.class) + .toInstance(); meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class); clusterMeterContainerService = FRMConsumerImpl.getClusterContainerService(); diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java new file mode 100644 index 0000000000..30556e4714 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java @@ -0,0 +1,192 @@ +package org.opendaylight.controller.forwardingrulesmanager.consumer.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.controller.sal.core.IContainer; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.Tables; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TableFeaturesConsumerImpl { + protected static final Logger logger = LoggerFactory.getLogger(TableFeaturesConsumerImpl.class); + private SalTableService tableService; + private TableDataCommitHandler commitHandler; + private final IClusterContainerServices clusterContainerService = null; + private IContainer container; + private static final String NAMEREGEX = "^[a-zA-Z0-9]+$"; + private boolean inContainerMode; // being used by global instance only + + public TableFeaturesConsumerImpl() { + InstanceIdentifier path = InstanceIdentifier.builder(Tables.class).child(Table.class) + .toInstance(); + tableService = FRMConsumerImpl.getProviderSession().getRpcService(SalTableService.class); + + if (null == tableService) { + logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended"); + System.out.println("Consumer SAL Service is down or NULL."); + return; + } + + System.out.println("-------------------------------------------------------------------"); + commitHandler = new TableDataCommitHandler(); + FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler); + container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this); + } + + /** + * Updates TableFeatures to the southbound plugin and our internal database + * + * @param path + * @param dataObject + */ + private void updateTableFeatures(InstanceIdentifier path, TableFeatures dataObject) { + + UpdateTableInputBuilder input = new UpdateTableInputBuilder(); + UpdatedTableBuilder updatedtablebuilder = new UpdatedTableBuilder(); + updatedtablebuilder.fieldsFrom(dataObject); + List features = updatedtablebuilder.build().getTableFeatures(); + for (TableFeatures feature : features) { + if (feature != null && feature.getMaxEntries() != null) { + logger.error("Max Entries field is read-only, cannot be changed"); + return; + } + } + input.setUpdatedTable(updatedtablebuilder.build()); + + // We send table feature update request to the sounthbound plugin + tableService.updateTable(input.build()); + } + + @SuppressWarnings("unchecked") + private void commitToPlugin(internalTransaction transaction) { + + for (@SuppressWarnings("unused") + Entry, TableFeatures> entry : transaction.updates.entrySet()) { + System.out.println("Coming update cc in TableDatacommitHandler"); + updateTableFeatures(entry.getKey(), entry.getValue()); + } + + } + + private final class TableDataCommitHandler implements DataCommitHandler, DataObject> { + + @SuppressWarnings("unchecked") + @Override + public DataCommitTransaction requestCommit(DataModification, DataObject> modification) { + // We should verify transaction + System.out.println("Coming in TableFeaturesDatacommitHandler"); + internalTransaction transaction = new internalTransaction(modification); + transaction.prepareUpdate(); + return transaction; + } + } + + private final class internalTransaction implements DataCommitTransaction, DataObject> { + + private final DataModification, DataObject> modification; + + @Override + public DataModification, DataObject> getModification() { + return modification; + } + + public internalTransaction(DataModification, DataObject> modification) { + this.modification = modification; + } + + Map, TableFeatures> updates = new HashMap<>(); + + /** + * We create a plan which table features will be updated. + * + */ + void prepareUpdate() { + + Set, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet(); + for (Entry, DataObject> entry : puts) { + + // validating the DataObject + + Status status = validate(container, (TableFeatures) entry); + if (!status.isSuccess()) { + logger.warn("Invalid Configuration for table features The failure is {}", entry, + status.getDescription()); + String error = "Invalid Configuration (" + status.getDescription() + ")"; + logger.error(error); + return; + } + if (entry.getValue() instanceof TableFeatures) { + TableFeatures tablefeatures = (TableFeatures) entry.getValue(); + preparePutEntry(entry.getKey(), tablefeatures); + } + + } + } + + private void preparePutEntry(InstanceIdentifier key, TableFeatures tablefeatures) { + if (tablefeatures != null) { + // Updating the Map + System.out.println("Coming update in TableFeaturesDatacommitHandler"); + updates.put(key, tablefeatures); + } + } + + /** + * We are OK to go with execution of plan + * + */ + @Override + public RpcResult finish() throws IllegalStateException { + + commitToPlugin(this); + // We return true if internal transaction is successful. + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return Rpcs.getRpcResult(true, null, null); + } + + /** + * + * We should rollback our preparation + * + */ + @Override + public RpcResult rollback() throws IllegalStateException { + // NOOP - we did not modified any internal state during + // requestCommit phase + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return Rpcs.getRpcResult(true, null, null); + + } + + public Status validate(IContainer container, TableFeatures dataObject) { + + String tablename = dataObject.getName(); + if (tablename == null || tablename.trim().isEmpty() || !tablename.matches(NAMEREGEX) + || tablename.length() != 32) { + return new Status(StatusCode.BADREQUEST, "Invalid table name"); + } + + return new Status(StatusCode.SUCCESS); + } + } +} diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang index 97ca8b3c71..25e8e7aa57 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang @@ -18,13 +18,23 @@ module opendaylight-group-types { leaf group-type { type enumeration { enum group-all; - enum group_select; - enum group_indirect; - enum group_ff; + enum group-select; + enum group-indirect; + enum group-ff; } } } + typedef group-capabilities { + type enumeration { + enum select-weight; + enum select-liveness; + enum chaining; + enum chaining-checks; + } + } + + grouping group { uses group-types; @@ -119,14 +129,21 @@ module opendaylight-group-types { } grouping group-features { - uses group-types; + leaf types { + type bits { + bit group-all; + bit group-select; + bit group-indirect; + bit group-ff; + } + } leaf capabilities { - type enumeration { - enum select-weight; - enum select-liveness; - enum chaining; - enum chaining-checks; + type bits { + bit select-weight; + bit select-liveness; + bit chaining; + bit chaining-checks; } } diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang index 5b565365a5..d29ddc0ddd 100644 --- a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang +++ b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang @@ -54,6 +54,10 @@ module opendaylight-group-statistics { rpc get-group-statistics { input { uses inv:node; + leaf group-id{ + type group-types:group-id; + } + } output { uses group-types:group-statistics-reply; diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java index c207db0478..bbbb5c8566 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java @@ -232,7 +232,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder(); groupFeatures.setActions(notification.getActions()); groupFeatures.setCapabilities(notification.getCapabilities()); - groupFeatures.setGroupType(notification.getGroupType()); + groupFeatures.setTypes(notification.getTypes()); groupFeatures.setMaxGroups(notification.getMaxGroups()); cache.get(notification.getId()).setGroupFeatures(groupFeatures.build()); diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java index 97d2a6d02a..6ec4c2ce01 100644 --- a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java +++ b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java @@ -19,10 +19,12 @@ public interface RoutingTable { * * @param routeId route identifier * @param route network address + * @throws RoutingTableException for any logical exception + * @throws SystemException */ - public void addRoute(I routeId, R route) throws SystemException, RoutingTableException; + public void addRoute(I routeId, R route) throws RoutingTableException,SystemException; - /** + /** * Adds a network address for the route. If the route already exists, * it throws DuplicateRouteException. * This method would be used when registering a global service. @@ -31,6 +33,7 @@ public interface RoutingTable { * @param routeId route identifier * @param route network address * @throws DuplicateRouteException + * @throws RoutingTableException */ public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException; @@ -50,8 +53,10 @@ public interface RoutingTable { * Remove the route. * This method would be used when registering a global service. * @param routeId + * @throws RoutingTableException + * @throws SystemException */ - public void removeGlobalRoute(I routeId); + public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException; /** * Returns a set of network addresses associated with this route @@ -69,6 +74,13 @@ public interface RoutingTable { */ public R getARoute(I routeId); + /** + * + * This will be removed after listeners + * have made change on their end to use whiteboard pattern + * @deprecated + */ + public void registerRouteChangeListener(RouteChangeListener listener); public class DuplicateRouteException extends RoutingTableException { diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java index 45414437cc..6e2d280a89 100644 --- a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java +++ b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java @@ -11,6 +11,7 @@ package org.opendaylight.controller.sal.connector.remoterpc.impl; import org.apache.felix.dm.Component; import org.opendaylight.controller.clustering.services.ICacheUpdateAware; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener; import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; import org.slf4j.Logger; @@ -72,6 +73,15 @@ public class Activator extends ComponentActivatorAbstractBase { c.setInterface(new String[] { RoutingTable.class.getName(),ICacheUpdateAware.class.getName() }, props); logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class); + + // RouteChangeListener services will be none or many so the + // dependency is optional + c.add(createServiceDependency() + .setService(RouteChangeListener.class) + .setCallbacks("setRouteChangeListener", "unsetRouteChangeListener") + .setRequired(false)); + + //dependency is required as it provides us the caching support c.add(createServiceDependency().setService( IClusterGlobalServices.class).setCallbacks( "setClusterGlobalServices", diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java index 558c8a80d3..4e1dfb0058 100644 --- a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java +++ b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java @@ -10,12 +10,16 @@ package org.opendaylight.controller.sal.connector.remoterpc.impl; import com.google.common.base.Preconditions; import org.apache.felix.dm.Component; -import org.opendaylight.controller.clustering.services.*; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.CacheListenerAddException; +import org.opendaylight.controller.clustering.services.ICacheUpdateAware; +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.clustering.services.IClusterServices; import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener; import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable; import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException; import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException; -import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,243 +27,298 @@ import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; -import java.util.*; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.ConcurrentMap; /** * @author: syedbahm */ -public class RoutingTableImpl implements RoutingTable,ICacheUpdateAware { +public class RoutingTableImpl implements RoutingTable, ICacheUpdateAware { public static final String ROUTING_TABLE_GLOBAL_CACHE = "routing_table_global_cache"; - private Logger log = LoggerFactory - .getLogger(RoutingTableImpl.class); - - private IClusterGlobalServices clusterGlobalServices = null; - private RoutingTableImpl routingTableInstance = null; - private ConcurrentMap routingTableCache = null; - private List routeChangeListeners = new ArrayList(); - private ServiceRegistration cacheAwareRegistration = null; - - public RoutingTableImpl() { - } - - @Override - public void addRoute(I routeId, R route) throws RoutingTableException { - throw new UnsupportedOperationException(" Not implemented yet!"); - } - - @Override - public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException { - Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!"); - Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!"); - try { - - Set existingRoute = null; - // ok does the global route is already registered ? - if ((existingRoute = getRoutes(routeId)) == null) { - - if(log.isDebugEnabled()){ - log.debug("addGlobalRoute: adding a new route with id"+ routeId + " and value = "+route); - } - // lets start a transaction - clusterGlobalServices.tbegin(); - Set routes = new HashSet(); - routes.add(route); - routingTableCache.put(routeId, routes); - clusterGlobalServices.tcommit(); - } else { - throw new DuplicateRouteException(" There is already existing route " + existingRoute); - } - - } catch (NotSupportedException e) { - throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e); - } catch (HeuristicRollbackException e) { - throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e); - } catch (RollbackException e) { - throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e); - } catch (HeuristicMixedException e) { - throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e); - } catch (javax.transaction.SystemException e){ - throw new SystemException ( "System error occurred - while trying to create with value",e); + private Logger log = LoggerFactory.getLogger(RoutingTableImpl.class); + + private IClusterGlobalServices clusterGlobalServices = null; + private RoutingTableImpl routingTableInstance = null; + private ConcurrentMap routingTableCache = null; + private Set routeChangeListeners = Collections + .synchronizedSet(new HashSet()); + + public RoutingTableImpl() { } - } + @Override + public void addRoute(I routeId, R route) throws RoutingTableException { + throw new UnsupportedOperationException(" Not implemented yet!"); + } - @Override - public void removeRoute(I routeId, R route) { - throw new UnsupportedOperationException("Not implemented yet!"); - } @Override - public void removeGlobalRoute(I routeId) { - routingTableCache.remove(routeId); + public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException { + Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!"); + Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!"); + try { + + Set existingRoute = null; + // ok does the global route is already registered ? + if ((existingRoute = getRoutes(routeId)) == null) { + + if (log.isDebugEnabled()) { + log.debug("addGlobalRoute: adding a new route with id" + routeId + " and value = " + + route); + } + // lets start a transaction + clusterGlobalServices.tbegin(); + Set routes = new HashSet(); + routes.add(route); + routingTableCache.put(routeId, routes); + clusterGlobalServices.tcommit(); + } else { + throw new DuplicateRouteException(" There is already existing route " + existingRoute); + } + + } catch (NotSupportedException e) { + throw new RoutingTableException("Transaction error - while trying to create route id=" + + routeId + "with route" + route, e); + } catch (HeuristicRollbackException e) { + throw new RoutingTableException("Transaction error - while trying to create route id=" + + routeId + "with route" + route, e); + } catch (RollbackException e) { + throw new RoutingTableException("Transaction error - while trying to create route id=" + + routeId + "with route" + route, e); + } catch (HeuristicMixedException e) { + throw new RoutingTableException("Transaction error - while trying to create route id=" + + routeId + "with route" + route, e); + } catch (javax.transaction.SystemException e) { + throw new SystemException("System error occurred - while trying to create with value", e); + } + } - @Override - public Set getRoutes(I routeId) { + @Override + public void removeRoute(I routeId, R route) { + throw new UnsupportedOperationException("Not implemented yet!"); + } - //Note: currently works for global routes only wherein there is just single route - Preconditions.checkNotNull(routeId, "getARoute: routeId cannot be null!"); - return (Set) routingTableCache.get(routeId); - } + @Override + public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException { + Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!"); + try { + if (log.isDebugEnabled()) { + log.debug("removeGlobalRoute: removing a new route with id" + routeId); + } + // lets start a transaction + clusterGlobalServices.tbegin(); + + routingTableCache.remove(routeId); + clusterGlobalServices.tcommit(); + + } catch (NotSupportedException e) { + throw new RoutingTableException("Transaction error - while trying to remove route id=" + + routeId, e); + } catch (HeuristicRollbackException e) { + throw new RoutingTableException("Transaction error - while trying to remove route id=" + + routeId, e); + } catch (RollbackException e) { + throw new RoutingTableException("Transaction error - while trying to remove route id=" + + routeId, e); + } catch (HeuristicMixedException e) { + throw new RoutingTableException("Transaction error - while trying to remove route id=" + + routeId, e); + } catch (javax.transaction.SystemException e) { + throw new SystemException("System error occurred - while trying to remove with value", e); + } + } - @Override - public R getARoute(I routeId) { - throw new UnsupportedOperationException("Not implemented yet!"); - } + @Override + public Set getRoutes(I routeId) { - /** - * Registers listener for sending any change notification - * - * @param listener - */ - @Override - public void registerRouteChangeListener(RouteChangeListener listener) { - routeChangeListeners.add(listener); - } + // Note: currently works for global routes only wherein there is just single + // route + Preconditions.checkNotNull(routeId, "getARoute: routeId cannot be null!"); + return (Set) routingTableCache.get(routeId); + } + @Override + public R getARoute(I routeId) { + throw new UnsupportedOperationException("Not implemented yet!"); + } /** - * Returning the list of route change listeners for Unit testing - * Note: the package scope is default - * @return List of registered RouteChangeListener listeners + * @deprecated doesn't do anything will be removed once listeners used + * whiteboard pattern Registers listener for sending any change + * notification + * @param listener */ - List getRegisteredRouteChangeListeners(){ - return routeChangeListeners; - } + @Override + public void registerRouteChangeListener(RouteChangeListener listener) { - public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) { - this.clusterGlobalServices = clusterGlobalServices; - } + } - public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) { - if(cacheAwareRegistration != null) { - cacheAwareRegistration.unregister(); + public void setRouteChangeListener(RouteChangeListener rcl) { + if(rcl != null){ + routeChangeListeners.add(rcl); + }else{ + log.warn("setRouteChangeListener called with null listener"); + } + } + + public void unSetRouteChangeListener(RouteChangeListener rcl) { + if(rcl != null){ + routeChangeListeners.remove(rcl); + }else{ + log.warn("unSetRouteChangeListener called with null listener"); + } } - this.clusterGlobalServices = null; - } /** - * Creates the Routing Table clustered global services cache - * @throws CacheExistException -- cluster global services exception when cache exist - * @throws CacheConfigException -- cluster global services exception during cache config - * @throws CacheListenerAddException -- cluster global services exception during adding of listener + * Returning the set of route change listeners for Unit testing Note: the + * package scope is default + * + * @return List of registered RouteChangeListener listeners */ + Set getRegisteredRouteChangeListeners() { + return routeChangeListeners; + } - void createRoutingTableCache() throws CacheExistException, CacheConfigException, CacheListenerAddException { - // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it - // should be caching? - - // let us check here if the cache already exists -- if so don't create - if (!clusterGlobalServices.existCache( - ROUTING_TABLE_GLOBAL_CACHE)) { + public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) { + this.clusterGlobalServices = clusterGlobalServices; + } - if(log.isDebugEnabled()){ - log.debug("createRoutingTableCache: creating a new routing table cache "+ROUTING_TABLE_GLOBAL_CACHE ); - } - routingTableCache = clusterGlobalServices.createCache( - ROUTING_TABLE_GLOBAL_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); - } else { - if(log.isDebugEnabled()){ - log.debug("createRoutingTableCache: found existing routing table cache "+ROUTING_TABLE_GLOBAL_CACHE ); + public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) { + if((clusterGlobalServices != null ) && (this.clusterGlobalServices.equals(clusterGlobalServices))){ + this.clusterGlobalServices = null; } - routingTableCache = clusterGlobalServices.getCache( - ROUTING_TABLE_GLOBAL_CACHE); } - } - - /** - * Function called by the dependency manager when all the required - * dependencies are satisfied - * - */ - void init(Component c) { - try { - - createRoutingTableCache(); - } catch (CacheExistException e) { - throw new IllegalStateException("could not construct routing table cache"); - } catch (CacheConfigException e) { - throw new IllegalStateException("could not construct routing table cache"); - } catch (CacheListenerAddException e) { - throw new IllegalStateException("could not construct routing table cache"); + /** + * Creates the Routing Table clustered global services cache + * + * @throws CacheExistException + * -- cluster global services exception when cache exist + * @throws CacheConfigException + * -- cluster global services exception during cache config + * @throws CacheListenerAddException + * -- cluster global services exception during adding of listener + */ + + void createRoutingTableCache() throws CacheExistException, CacheConfigException, + CacheListenerAddException { + // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it + // should be caching? + + // let us check here if the cache already exists -- if so don't create + if (!clusterGlobalServices.existCache(ROUTING_TABLE_GLOBAL_CACHE)) { + + if (log.isDebugEnabled()) { + log.debug("createRoutingTableCache: creating a new routing table cache " + + ROUTING_TABLE_GLOBAL_CACHE); + } + routingTableCache = clusterGlobalServices.createCache(ROUTING_TABLE_GLOBAL_CACHE, + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + } else { + if (log.isDebugEnabled()) { + log.debug("createRoutingTableCache: found existing routing table cache " + + ROUTING_TABLE_GLOBAL_CACHE); + } + routingTableCache = clusterGlobalServices.getCache(ROUTING_TABLE_GLOBAL_CACHE); + } + } - } + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + try { + + createRoutingTableCache(); + } catch (CacheExistException e) { + throw new IllegalStateException("could not construct routing table cache"); + } catch (CacheConfigException e) { + throw new IllegalStateException("could not construct routing table cache"); + } catch (CacheListenerAddException e) { + throw new IllegalStateException("could not construct routing table cache"); + } + } /** - * Get routing table method is useful for unit testing - * It has package scope + * Get routing table method is useful for unit testing It has package + * scope */ - ConcurrentMap getRoutingTableCache(){ + ConcurrentMap getRoutingTableCache() { return this.routingTableCache; } + /** + * Invoked when a new entry is available in the cache, the key is only + * provided, the value will come as an entryUpdate invocation + * + * @param key + * Key for the entry just created + * @param cacheName + * name of the cache for which update has been received + * @param originLocal + * true if the event is generated from this node + */ + @Override + public void entryCreated(I key, String cacheName, boolean originLocal) { + // TBD: do we require this. + if (log.isDebugEnabled()) { + log.debug("RoutingTableUpdates: entryCreated routeId = " + key + " cacheName=" + cacheName); + } + } - /** - * Invoked when a new entry is available in the cache, the key is - * only provided, the value will come as an entryUpdate invocation - * - * @param key Key for the entry just created - * @param cacheName name of the cache for which update has been - * received - * @param originLocal true if the event is generated from this - * node - */ - @Override - public void entryCreated(I key, String cacheName, boolean originLocal) { - //TBD: do we require this. - if(log.isDebugEnabled()){ - log.debug("RoutingTableUpdates: entryCreated routeId = "+key - + " cacheName="+cacheName - ); - } - } - - /** - * Called anytime a given entry is updated - * - * @param key Key for the entry modified - * @param new_value the new value the key will have - * @param cacheName name of the cache for which update has been - * received - * @param originLocal true if the event is generated from this - * node - */ - @Override - public void entryUpdated(I key, R new_value, String cacheName, boolean originLocal) { - if(log.isDebugEnabled()){ - log.debug("RoutingTableUpdates: entryUpdated routeId = "+key - + ",value = "+ new_value - + " ,cacheName="+cacheName - ); - } - for(RouteChangeListener rcl:routeChangeListeners){ - rcl.onRouteUpdated(key, new_value); - } - } - - /** - * Called anytime a given key is removed from the - * ConcurrentHashMap we are listening to. - * - * @param key Key of the entry removed - * @param cacheName name of the cache for which update has been - * received - * @param originLocal true if the event is generated from this - * node - */ - @Override - public void entryDeleted(I key, String cacheName, boolean originLocal) { - if(log.isDebugEnabled()){ - log.debug("RoutingTableUpdates: entryUpdated routeId = "+key - + " local = "+ originLocal - + " cacheName="+cacheName - ); - } - for(RouteChangeListener rcl:routeChangeListeners){ - rcl.onRouteDeleted(key); - } - } - } \ No newline at end of file + /** + * Called anytime a given entry is updated + * + * @param key + * Key for the entry modified + * @param new_value + * the new value the key will have + * @param cacheName + * name of the cache for which update has been received + * @param originLocal + * true if the event is generated from this node + */ + @Override + public void entryUpdated(I key, R new_value, String cacheName, boolean originLocal) { + if (log.isDebugEnabled()) { + log.debug("RoutingTableUpdates: entryUpdated routeId = " + key + ",value = " + new_value + + " ,cacheName=" + cacheName + " originLocal="+originLocal); + } + if (!originLocal) { + for (RouteChangeListener rcl : routeChangeListeners) { + rcl.onRouteUpdated(key, new_value); + } + } + } + + /** + * Called anytime a given key is removed from the ConcurrentHashMap we are + * listening to. + * + * @param key + * Key of the entry removed + * @param cacheName + * name of the cache for which update has been received + * @param originLocal + * true if the event is generated from this node + */ + @Override + public void entryDeleted(I key, String cacheName, boolean originLocal) { + if (log.isDebugEnabled()) { + log.debug("RoutingTableUpdates: entryUpdated routeId = " + key + " local = " + originLocal + + " cacheName=" + cacheName + " originLocal="+originLocal); + } + if (!originLocal) { + for (RouteChangeListener rcl : routeChangeListeners) { + rcl.onRouteDeleted(key); + } + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java index 75cc6f5da8..2ef251d9a1 100644 --- a/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java +++ b/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java @@ -103,7 +103,12 @@ public class RoutingTableImplTest { Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0); rti.registerRouteChangeListener(new RouteChangeListenerImpl()); - Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1); + Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0); //old should not work + //what about the new approach - using whiteboard pattern + rti.setRouteChangeListener(new RouteChangeListenerImpl()); + + Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1); //should not work + } @Test diff --git a/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java b/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java index 3b6d398511..a7929e82fc 100644 --- a/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java +++ b/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java @@ -21,7 +21,6 @@ import java.io.Serializable; import java.net.URI; import java.util.Set; - import static org.ops4j.pax.exam.CoreOptions.junitBundles; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; @@ -41,6 +40,7 @@ public class public static final String YANG = "org.opendaylight.yangtools"; public static final String CONTROLLER = "org.opendaylight.controller"; public static final String YANGTOOLS = "org.opendaylight.yangtools"; + RoutingIdentifierImpl rii = new RoutingIdentifierImpl(); // get the OSGI bundle context @Inject private BundleContext bc; @@ -171,9 +171,6 @@ public class mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), // - mavenBundle(YANG, "concepts").versionAsInProject(), - mavenBundle(YANG, "yang-binding").versionAsInProject(), // - mavenBundle(YANG, "yang-common").versionAsInProject(), // mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), mavenBundle("com.google.guava", "guava").versionAsInProject(), // mavenBundle("org.javassist", "javassist").versionAsInProject(), @@ -248,7 +245,7 @@ public class @Test public void testAddGlobalRoute () throws Exception{ - RoutingIdentifierImpl rii = new RoutingIdentifierImpl(); + routingTable.addGlobalRoute(rii,"172.27.12.1:5000"); Set routes = routingTable.getRoutes(rii); @@ -261,6 +258,20 @@ public class } + @Test + public void testDeleteGlobalRoute () throws Exception{ + + routingTable.removeGlobalRoute(rii); + + Set routes = routingTable.getRoutes(rii); + + Assert.assertNull(routes); + + + } + + + class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable { private final URI namespace = URI.create("http://cisco.com/example"); @@ -281,6 +292,28 @@ public class public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() { return InstanceIdentifier.of(instance); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RoutingIdentifierImpl that = (RoutingIdentifierImpl) o; + + if (QNAME != null ? !QNAME.equals(that.QNAME) : that.QNAME != null) return false; + if (instance != null ? !instance.equals(that.instance) : that.instance != null) return false; + if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = namespace != null ? namespace.hashCode() : 0; + result = 31 * result + (QNAME != null ? QNAME.hashCode() : 0); + result = 31 * result + (instance != null ? instance.hashCode() : 0); + return result; + } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java index b163c639a5..f26bcf718c 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java @@ -415,7 +415,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, */ if (inPort == null || container.equals(GlobalConstants.DEFAULT.toString()) - || this.containerToNc.get(container).contains(inPort)) { + || (containerToNc.containsKey(container) && containerToNc.get(container).contains(inPort))) { notifier.flowRemoved(node, flow); } }