From: Giovanni Meo Date: Fri, 26 Apr 2013 14:55:12 +0000 (+0000) Subject: Merge "Added support for annotations in generated APIs." X-Git-Tag: releasepom-0.1.0~521 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=258cac6ec48a0a4ff62b33b4bdcbac5105a1e006;hp=4221068644c7e8d08880b4d54e2a099a646796b9 Merge "Added support for annotations in generated APIs." --- diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java index 3034d3ca6d..0b2610797f 100644 --- a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java @@ -248,7 +248,7 @@ public class ClusterManager implements IClusterServices { logger.info("Starting the ClusterManager"); try { //FIXME keeps throwing FileNotFoundException - this.cm = new DefaultCacheManager("/config/infinispan-config.xml"); + this.cm = new DefaultCacheManager("config/infinispan-config.xml"); logger.debug("Allocated ClusterManager"); if (this.cm != null) { this.cm.start(); diff --git a/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml index 96eff96919..03a9b4d93e 100644 --- a/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml +++ b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml @@ -2,7 +2,7 @@ - + diff --git a/opendaylight/clustering/services_implementation/src/test/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerTest.java b/opendaylight/clustering/services_implementation/src/test/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerTest.java new file mode 100644 index 0000000000..736a2b23ec --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/test/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerTest.java @@ -0,0 +1,160 @@ +package org.opendaylight.controller.clustering.services_implementation.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.infinispan.CacheImpl; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.IClusterServices.cacheMode; + +public class ClusterManagerTest { + + @Test + public void NoManagerSetTest() throws CacheExistException, + CacheConfigException { + ClusterManager cm = new ClusterManager(); + CacheImpl c1 = null; + CacheImpl c2 = null; + Assert.assertNull(cm.createCache("Container", "Cache", null)); + Assert.assertNull(cm.getCacheProperties("Container", "Cache")); + Assert.assertNull(cm.getCache("Container", "Cache")); + Assert.assertFalse(cm.existCache("Container", "Cache")); + Assert.assertNull(cm.getCacheList("Container")); + Assert.assertTrue(cm.amIStandby()); + Assert.assertNull(cm.getActiveAddress()); + Assert.assertNull(cm.getMyAddress()); + Assert.assertNull(cm.getClusteredControllers()); + } + + @Test + public void WithManagerTest() throws CacheExistException, + CacheConfigException { + + ClusterManager cm = new ClusterManager(); + CacheImpl c1 = null; + CacheImpl c2 = null; + + cm.start(); + + // Check no cache created yet + assertFalse(cm.existCache("NonExistantContainerName", + "NonExistantCacheName")); + + // Create cache with no cacheMode set, expecting it to fail + HashSet cacheModeSet = new HashSet(); + Assert.assertNull(cm.createCache("Container1", "Cache1", cacheModeSet)); + + // Create first cache as transactional + cacheModeSet.add(cacheMode.TRANSACTIONAL); + try { + c1 = (CacheImpl) cm.createCache("Container1", + "Cache1", cacheModeSet); + } catch (CacheExistException cee) { + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + Assert.assertTrue(false); + } + + // Try creating exact same cache again + try { + c1 = (CacheImpl) cm.createCache("Container1", + "Cache1", cacheModeSet); + } catch (CacheExistException cee) { + Assert.assertTrue(true); + } catch (CacheConfigException cce) { + Assert.assertTrue(false); + } + + // Create second cache with both types of cacheMode, expecting it to + // complain + cacheModeSet.add(cacheMode.NON_TRANSACTIONAL); + try { + c2 = (CacheImpl) cm.createCache("Container1", + "Cache2", cacheModeSet); + } catch (CacheExistException cee) { + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + Assert.assertTrue(true); + } + + // Create second cache properly this time, as non_transactional + cacheModeSet.remove(cacheMode.TRANSACTIONAL); + try { + c2 = (CacheImpl) cm.createCache("Container1", + "Cache2", cacheModeSet); + } catch (CacheExistException cee) { + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + Assert.assertTrue(false); + } + + // Make sure correct caches exists + Assert.assertTrue(cm.existCache("Container1", "Cache1")); + c1 = (CacheImpl) cm.getCache("Container1", "Cache1"); + Assert.assertTrue(c1 != null); + + Assert.assertTrue(cm.existCache("Container1", "Cache2")); + c2 = (CacheImpl) cm.getCache("Container1", "Cache2"); + Assert.assertTrue(c2 != null); + + Assert.assertNull(cm.getCache("Container1", "Cache3")); + + // Get CacheList + HashSet cacheList = (HashSet) cm + .getCacheList("Container2"); + Assert.assertEquals(0, cacheList.size()); + + cacheList = (HashSet) cm.getCacheList("Container1"); + Assert.assertEquals(2, cacheList.size()); + Assert.assertTrue(cacheList.contains("Cache1")); + Assert.assertTrue(cacheList.contains("Cache2")); + + // Get CacheProperties + Assert.assertNull(cm.getCacheProperties("Container1", "")); + Properties p = cm.getCacheProperties("Container1", "Cache1"); + Assert.assertEquals(3, p.size()); + Assert.assertNotNull(p + .getProperty(IClusterServices.cacheProps.TRANSACTION_PROP + .toString())); + Assert.assertNotNull(p + .getProperty(IClusterServices.cacheProps.CLUSTERING_PROP + .toString())); + Assert.assertNotNull(p + .getProperty(IClusterServices.cacheProps.LOCKING_PROP + .toString())); + + // Destroy cache1 and make sure it's gone + cm.destroyCache("Container1", "Cache1"); + cm.destroyCache("Container1", "Cache3"); + Assert.assertFalse(cm.existCache("Container1", "Cache1")); + Assert.assertTrue(cm.existCache("Container1", "Cache2")); + + // Check amIStandBy() + boolean standby = cm.amIStandby(); + Assert.assertFalse(standby); + + // Check addresses, which are all loopback + InetAddress activeAddress = cm.getActiveAddress(); + Assert.assertEquals("/127.0.0.1", activeAddress.toString()); + InetAddress myAddress = cm.getMyAddress(); + Assert.assertEquals("/127.0.0.1", myAddress.toString()); + + List cc = cm.getClusteredControllers(); + Assert.assertEquals(0, cc.size()); + + cm.stop(); + } + +} diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java index dfe331ad5f..96b6819e57 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java @@ -28,6 +28,7 @@ public class FlowEntryInstall { private FlowEntry original; private ContainerFlow cFlow; private FlowEntry install; + transient private long requestId; // async request id transient private boolean deletePending; public FlowEntryInstall(FlowEntry original, ContainerFlow cFlow) { @@ -36,6 +37,7 @@ public class FlowEntryInstall { this.install = (cFlow == null) ? original.clone() : original .mergeWith(cFlow); deletePending = false; + requestId = 0; } @Override @@ -84,9 +86,17 @@ public class FlowEntryInstall { this.deletePending = true; } + public void setRequestId(long rid) { + this.requestId = rid; + } + + public long getRequestId() { + return requestId; + } + @Override public String toString() { - return "[Install = " + install + " Original: " + original + " cFlow: " - + cFlow + "]"; + return "[Install = " + install + " Original = " + original + " cFlow = " + + cFlow + " rid = " + requestId + "]"; } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java index d0efe4a83f..78917c9c80 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java @@ -73,12 +73,90 @@ public interface IForwardingRulesManager { * not valid an error code is returned. If the existing flow is equal to the * passed one it will be a no op and success code is returned. * + * * @param newone * the new flow entry to install * @return the {@code Status} object indicating the result of this action */ public Status modifyOrAddFlowEntry(FlowEntry newone); + /** + * It requests FRM to install the passed Flow Entry through an asynchronous + * call. A unique request id is returned to the caller. FRM will request the + * SDN protocol plugin to install the flow on the network node. As immediate + * result of this asynchronous call, FRM will update its flow database as if + * the flow was successfully installed. + * + * @param flow + * the flow entry to install + * @return the status of this request containing the request id associated + * to this asynchronous request + */ + public Status installFlowEntryAsync(FlowEntry flow); + + /** + * It requests FRM to remove the passed Flow Entry through an asynchronous + * call. A unique request id is returned to the caller. FRM will request the + * SDN protocol plugin to uninstall the flow from the network node. As + * immediate result of this asynchronous call, FRM will update its flow + * database as if the flow was successfully installed. + * + * @param flow + * the flow entry to uninstall + * @return the status of this request containing the unique id associated to + * this asynchronous request + */ + public Status uninstallFlowEntryAsync(FlowEntry flow); + + /** + * It requests FRM to replace the currently installed Flow Entry with the + * new one through an asynchronous call. A unique request id is returned to + * the caller. It is up to the SDN protocol plugin to decide how to convey + * this message to the network node. It could be a delete + add or a single + * modify message depending on the SDN protocol specifications. If the + * current flow is equal to the new one it will be a no op. + * + * @param current + * the current flow entry to modify + * @param newone + * the new flow entry which will replace the current one + * @return the status of this request containing the request id associated + * to this asynchronous request + */ + public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone); + + /** + * It requests the FRM to replace the currently installed Flow Entry with + * the new one through an asynchronous call. A unique request id is returned + * to the caller. The currently installed entry is derived by the Match + * portion of the passed Flow. FRM looks in its database for a previously + * installed FlowEntry which Match equals the Match of the passed Flow. If + * it finds it, it will request the SDN protocol plugin to replace the + * existing flow with the new one on the network node. If it does not find + * it, it will request plugin to add the new flow. If the passed entry is + * not valid a zero request id is returned. If the existing flow is equal to + * the passed one it will be a no op. + * + * @param newone + * the new flow entry to install + * @return the unique id associated to this request. In case of not + * acceptable request -1 will be returned. + */ + public Status modifyOrAddFlowEntryAsync(FlowEntry newone); + + /** + * Requests ForwardingRulesManager to solicit the network node to inform + * us about the status of his execution on the asynchronous requests that + * were sent to it so far. It is a way for an application to poke the + * network node in order to get a feedback asap on the asynchronous + * requests generated by the application. It is a non-blocking call + * and does not guarantee the node will respond in any given time. + * + * @param node + * The network node to solicit a response + */ + public void solicitStatusResponse(Node node); + /** * Check whether the passed flow entry conflicts with the Container flows * @@ -209,7 +287,7 @@ public interface IForwardingRulesManager { * @param name * the flow name * @param n - * the netwrok node identifier + * the network node identifier * @return the {@code FlowConfig} object */ public FlowConfig getStaticFlow(String name, Node n); diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java index e2ccdd60c3..43d1b29a75 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java @@ -26,4 +26,18 @@ public interface IForwardingRulesManagerAware { * otherwise */ public void policyUpdate(String policyName, boolean add); + + /** + * Inform listeners that the network node has notified us about a failure in + * executing the controller generated asynchronous request identified by the + * passed unique id. + * + * @param requestId + * the unique id associated with the request which failed to be + * executed on the network node + * @param error + * the string describing the error reported by the network node + */ + public void requestFailed(long requestId, String error); + } diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java index c86363fef6..fe2cdc4738 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java @@ -138,9 +138,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * * @param flowEntry * the original flow entry application requested to add - * @return + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ - private Status addEntry(FlowEntry flowEntry) { + private Status addEntry(FlowEntry flowEntry, boolean async) { + // Sanity Check if (flowEntry == null || flowEntry.getNode() == null) { String msg = "Invalid FlowEntry"; @@ -190,14 +194,22 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Try to install an entry at the time Status error = new Status(null, null); + Status succeded = null; boolean oneSucceded = false; - for (FlowEntryInstall installEntry : toInstallList) { + for (FlowEntryInstall installEntry : toInstallSafe) { // Install and update database - Status ret = addEntriesInternal(installEntry); + Status ret = addEntriesInternal(installEntry, async); if (ret.isSuccess()) { oneSucceded = true; + /* + * The first successful status response will be returned + * For the asynchronous call, we can discard the container flow + * complication for now and assume we will always deal with + * one flow only per request + */ + succeded = ret; } else { error = ret; log.warn("Failed to install the entry: {}. The failure is: {}", @@ -205,7 +217,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } - return (oneSucceded) ? new Status(StatusCode.SUCCESS, null) : error; + return (oneSucceded) ? succeded : error; } /** @@ -251,10 +263,14 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * * @param currentFlowEntry * @param newFlowEntry - * @return Success or error string + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ private Status modifyEntry(FlowEntry currentFlowEntry, - FlowEntry newFlowEntry) { + FlowEntry newFlowEntry, boolean async) { + Status retExt; // Sanity checks @@ -329,6 +345,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * So, for the above two cases, to simplify, let's decouple the modify * in: 1) remove current entries 2) install new entries */ + Status succeeded = null; boolean decouple = false; if (installedList.size() != toInstallList.size()) { log.info("Modify: New flow entry does not satisfy the same " @@ -354,11 +371,11 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (decouple) { // Remove current entries for (FlowEntryInstall currEntry : installedList) { - this.removeEntryInternal(currEntry); + this.removeEntryInternal(currEntry, async); } // Install new entries for (FlowEntryInstall newEntry : toInstallSafe) { - this.addEntriesInternal(newEntry); + succeeded = this.addEntriesInternal(newEntry, async); } } else { /* @@ -372,13 +389,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * fails, we need to stop, restore the already modified entries, and * declare failure. */ - Status retModify; + Status retModify = null; int i = 0; int size = toInstallList.size(); while (i < size) { // Modify and update database retModify = modifyEntryInternal(installedList.get(i), - toInstallList.get(i)); + toInstallList.get(i), async); if (retModify.isSuccess()) { i++; } else { @@ -394,7 +411,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, while (j < i) { log.info("Attempting to restore initial entries"); retExt = modifyEntryInternal(toInstallList.get(i), - installedList.get(i)); + installedList.get(i), async); if (retExt.isSuccess()) { j++; } else { @@ -408,8 +425,15 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return new Status(StatusCode.INTERNALERROR, msg); } } + succeeded = retModify; } - return new Status(StatusCode.SUCCESS, null); + /* + * The first successful status response will be returned. + * For the asynchronous call, we can discard the container flow + * complication for now and assume we will always deal with + * one flow only per request + */ + return succeeded; } /** @@ -419,14 +443,22 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * * @param currentEntries * @param newEntries - * @return + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ private Status modifyEntryInternal(FlowEntryInstall currentEntries, - FlowEntryInstall newEntries) { + FlowEntryInstall newEntries, boolean async) { // Modify the flow on the network node - Status status = programmer.modifyFlow(currentEntries.getNode(), - currentEntries.getInstall().getFlow(), newEntries.getInstall() - .getFlow()); + Status status = (async)? + programmer.modifyFlowAsync(currentEntries.getNode(), + currentEntries.getInstall().getFlow(), newEntries.getInstall() + .getFlow()) : + programmer.modifyFlow(currentEntries.getNode(), + currentEntries.getInstall().getFlow(), newEntries.getInstall() + .getFlow()); + if (!status.isSuccess()) { log.warn( @@ -439,6 +471,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, newEntries.getInstall()); // Update DB + newEntries.setRequestId(status.getRequestId()); updateLocalDatabase(currentEntries, false); updateLocalDatabase(newEntries, true); @@ -450,9 +483,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * (entry or node not present), it return successfully * * @param flowEntry - * @return + * the flow entry to remove + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ - private Status removeEntry(FlowEntry flowEntry) { + private Status removeEntry(FlowEntry flowEntry, boolean async) { Status error = new Status(null, null); // Sanity Check @@ -468,6 +505,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, flowEntry.clone(), container.getContainerFlows()); Set flowsOnNode = nodeFlows.get(flowEntry.getNode()); + Status succeeded = null; boolean atLeastOneRemoved = false; for (FlowEntryInstall entry : installedList) { if (flowsOnNode == null) { @@ -481,14 +519,14 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, log.debug(logMsg, flowEntry); if (installedList.size() == 1) { // If we had only one entry to remove, we are done - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } else { continue; } } // Remove and update DB - Status ret = removeEntryInternal(entry); + Status ret = removeEntryInternal(entry, async); if (!ret.isSuccess()) { error = ret; @@ -499,6 +537,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return error; } } else { + succeeded = ret; atLeastOneRemoved = true; } } @@ -508,8 +547,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * of removing the stale entries later, or adjusting the software * database if not in sync with hardware */ - return (atLeastOneRemoved) ? new Status(StatusCode.SUCCESS, null) - : error; + return (atLeastOneRemoved) ? succeeded : error; } /** @@ -518,16 +556,23 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * validity checks are passed * * @param entry - * the FlowEntryInstall - * @return "Success" or error string + * the flow entry to remove + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ - private Status removeEntryInternal(FlowEntryInstall entry) { + private Status removeEntryInternal(FlowEntryInstall entry, boolean async) { // Mark the entry to be deleted (for CC just in case we fail) entry.toBeDeleted(); // Remove from node - Status status = programmer.removeFlow(entry.getNode(), entry - .getInstall().getFlow()); + Status status = (async)? + programmer.removeFlowAsync(entry.getNode(), entry + .getInstall().getFlow()) : + programmer.removeFlow(entry.getNode(), entry + .getInstall().getFlow()); + if (!status.isSuccess()) { log.warn( @@ -535,7 +580,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, entry.getInstall(), status.getDescription()); return status; } - log.info("Removed {}", entry.getInstall()); + log.trace("Removed {}", entry.getInstall()); // Update DB updateLocalDatabase(entry, false); @@ -550,13 +595,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * whether this flow would conflict or overwrite an existing one. * * @param entry - * the FlowEntryInstall - * @return "Success" or error string + * the flow entry to install + * @param async + * the flag indicating if this is a asynchronous request + * @return the status of this request. In case of asynchronous call, it + * will contain the unique id assigned to this request */ - private Status addEntriesInternal(FlowEntryInstall entry) { + private Status addEntriesInternal(FlowEntryInstall entry, boolean async) { // Install the flow on the network node - Status status = programmer.addFlow(entry.getNode(), entry.getInstall() - .getFlow()); + Status status = (async)? + programmer.addFlow(entry.getNode(), entry.getInstall() + .getFlow()) : + programmer.addFlowAsync(entry.getNode(), entry.getInstall() + .getFlow()); + if (!status.isSuccess()) { log.warn( @@ -565,9 +617,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return status; } - log.info("Added {}", entry.getInstall()); + log.trace("Added {}", entry.getInstall()); // Update DB + entry.setRequestId(status.getRequestId()); updateLocalDatabase(entry, true); return status; @@ -740,7 +793,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, status = new Status(StatusCode.NOTACCEPTABLE, msg); log.warn(logMsg, flowEntry); } else { - status = addEntry(flowEntry); + status = addEntry(flowEntry, false); + } + return status; + } + + @Override + public Status installFlowEntryAsync(FlowEntry flowEntry) { + Status status; + if (inContainerMode) { + String msg = "Controller in container mode: Install Refused"; + status = new Status(StatusCode.NOTACCEPTABLE, msg); + log.warn(msg); + } else { + status = addEntry(flowEntry, true); } return status; } @@ -754,11 +820,24 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, status = new Status(StatusCode.NOTACCEPTABLE, msg); log.warn(logMsg, entry); } else { - status = removeEntry(entry); + status = removeEntry(entry, false); } return status; } + @Override + public Status uninstallFlowEntryAsync(FlowEntry flowEntry) { + Status status; + if (inContainerMode) { + String msg = "Controller in container mode: Uninstall Refused"; + status = new Status(StatusCode.NOTACCEPTABLE, msg); + log.warn(msg); + } else { + status = removeEntry(flowEntry, true); + } + return status; + } + @Override public Status modifyFlowEntry(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) { @@ -769,7 +848,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, status = new Status(StatusCode.NOTACCEPTABLE, msg); log.warn(logMsg, newFlowEntry); } else { - status = modifyEntry(currentFlowEntry, newFlowEntry); + status = modifyEntry(currentFlowEntry, newFlowEntry, false); + } + return status; + } + + @Override + public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone) { + Status status = null; + if (inContainerMode) { + String msg = "Controller in container mode: Modify Refused"; + status = new Status(StatusCode.NOTACCEPTABLE, msg); + log.warn(msg); + } else { + status = modifyEntry(current, newone, true); } return status; } @@ -795,6 +887,28 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } + @Override + public Status modifyOrAddFlowEntryAsync(FlowEntry newone) { + /* + * Run a loose check on the installed entries to decide whether to go + * with a add or modify method. A loose check means only check against + * the original flow entry requests and not against the installed flow + * entries which are the result of the original entry merged with the + * container flow(s) (if any). The modifyFlowEntry method in presence of + * conflicts with the Container flows (if any) would revert back to a + * delete + add pattern + */ + FlowEntryInstall currentFlowEntries = findMatch(newone, true); + + if (currentFlowEntries != null) { + return modifyFlowEntryAsync(currentFlowEntries.getOriginal(), + newone); + } else { + return installFlowEntry(newone); + } + } + + /** * Try to find in the database if a Flow with the same Match and priority of * the passed one already exists for the specified network node. Flow, @@ -858,7 +972,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Remove the old couples. No validity checks to be run, use the // internal remove for (FlowEntryInstall oldCouple : oldCouples) { - this.removeEntryInternal(oldCouple); + this.removeEntryInternal(oldCouple, false); } // Reinstall the original flow entries, via the regular path: new // cFlow merge + validations @@ -951,7 +1065,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, for (NodeConnector dstPort : portList) { newFlowEntry.getFlow().addAction(new Output(dstPort)); } - Status error = modifyEntry(currentFlowEntry, newFlowEntry); + Status error = modifyEntry(currentFlowEntry, newFlowEntry, false); if (error.isSuccess()) { log.info("Ports {} added to FlowEntry {}", portList, flowName); @@ -982,7 +1096,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Action action = new Output(dstPort); newFlowEntry.getFlow().removeAction(action); } - Status status = modifyEntry(currentFlowEntry, newFlowEntry); + Status status = modifyEntry(currentFlowEntry, newFlowEntry, false); if (status.isSuccess()) { log.info("Ports {} removed from FlowEntry {}", portList, flowName); @@ -1037,7 +1151,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, newFlowEntry.getFlow().addAction(new Output(outPort)); // Modify on network node - Status status = modifyEntry(currentFlowEntry, newFlowEntry); + Status status = modifyEntry(currentFlowEntry, newFlowEntry, false); if (status.isSuccess()) { log.info("Output port replaced with {} for flow {} on node {}", @@ -1280,7 +1394,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Program hw if (config.installInHw()) { FlowEntry entry = config.getFlowEntry(); - status = this.addEntry(entry); + status = this.addEntry(entry, false); if (!status.isSuccess()) { config.setStatus(status.getDescription()); if (!restore) { @@ -1316,7 +1430,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, portGroupChanged(pgconfig, existingData, true); } } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } private void addStaticFlowsToSwitch(Node node) { @@ -1328,7 +1442,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (config.installInHw() && !config.getStatus().equals( StatusCode.SUCCESS.toString())) { - Status status = this.addEntry(config.getFlowEntry()); + Status status = this.addEntry(config.getFlowEntry(), false); config.setStatus(status.getDescription()); } } @@ -1395,7 +1509,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, for (Map.Entry entry : staticFlows.entrySet()) { if (entry.getValue().isByNameAndNodeIdEqual(config)) { // Program the network node - Status status = this.removeEntry(config.getFlowEntry()); + Status status = this.removeEntry(config.getFlowEntry(), false); // Update configuration database if programming was successful if (status.isSuccess()) { staticFlows.remove(entry.getKey()); @@ -1425,7 +1539,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } if (!entry.isPortGroupEnabled()) { // Program the network node - status = this.removeEntry(entry.getFlowEntry()); + status = this.removeEntry(entry.getFlowEntry(), false); } // Update configuration database if programming was successful if (status.isSuccess()) { @@ -1492,7 +1606,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Status status = new Status(StatusCode.SUCCESS, "Saved in config"); if (oldFlowConfig.installInHw()) { status = this.modifyEntry(oldFlowConfig.getFlowEntry(), - newFlowConfig.getFlowEntry()); + newFlowConfig.getFlowEntry(), false); } // Update configuration database if programming was successful @@ -1529,11 +1643,11 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, FlowConfig conf = entry.getValue(); if (conf.isByNameAndNodeIdEqual(config)) { // Program the network node - Status status = new Status(StatusCode.SUCCESS, null); + Status status = new Status(StatusCode.SUCCESS); if (conf.installInHw()) { - status = this.removeEntry(conf.getFlowEntry()); + status = this.removeEntry(conf.getFlowEntry(), false); } else { - status = this.addEntry(conf.getFlowEntry()); + status = this.addEntry(conf.getFlowEntry(), false); } if (!status.isSuccess()) { conf.setStatus(status.getDescription()); @@ -1569,10 +1683,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Now remove the entries for (FlowEntry flowEntry : inactiveFlows) { - Status status = this.removeEntry(flowEntry); + Status status = this.removeEntry(flowEntry, false); if (!status.isSuccess()) { - log.warn("Failed to remove entry: {}. The failure is: {}" - + flowEntry, status.getDescription()); + log.warn("Failed to remove entry: {}. The failure is: {}", + flowEntry, status.getDescription()); } } } @@ -1586,10 +1700,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, log.info("Reinstalling all inactive flows"); for (FlowEntry flowEntry : this.inactiveFlows) { - Status status = this.addEntry(flowEntry); + Status status = this.addEntry(flowEntry, false); if (!status.isSuccess()) { - log.warn("Failed to install entry: {}. The failure is: {}" - + flowEntry, status.getDescription()); + log.warn("Failed to install entry: {}. The failure is: {}", + flowEntry, status.getDescription()); } } @@ -1923,7 +2037,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public void portGroupChanged(PortGroupConfig config, Map data, boolean add) { - log.info("PortGroup Changed for :" + config + " Data: " + portGroupData); + log.info("PortGroup Changed for: {} Data: {}", config, portGroupData); Map existingData = portGroupData.get(config); if (existingData != null) { for (Map.Entry entry : data.entrySet()) { @@ -2424,7 +2538,49 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public void flowErrorReported(Node node, long rid, Object err) { - log.error("Got error {} for message rid {} from node {}", new Object[] { - err, rid, node }); + log.trace("Got error {} for message rid {} from node {}", + new Object[] {err, rid, node }); + /* + * If this was for a flow install, remove the corresponding entry + * from the software view. If it was a Looking for the rid going through the + * software database. + * TODO: A more efficient rid <-> FlowEntryInstall mapping will + * have to be added in future + */ + Set entries = nodeFlows.get(node); + if (entries != null) { + FlowEntryInstall target = null; + for (FlowEntryInstall entry : entries) { + if (entry.getRequestId() == rid) { + target = entry; + break; + } + } + if (target != null) { + // This was a flow install, update database + this.updateLocalDatabase(target, false); + } + } + + // Notify listeners + if (frmAware != null) { + synchronized (frmAware) { + for (IForwardingRulesManagerAware frma : frmAware) { + try { + frma.requestFailed(rid, err.toString()); + } catch (Exception e) { + log.warn("Failed to notify {}", frma); + } + } + } + } + } + + @Override + public void solicitStatusResponse(Node node) { + if (this.programmer != null) { + programmer.sendBarrierMessage(node); + } } + } diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java index d455a0ae20..6bafee0b2c 100644 --- a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java @@ -12,6 +12,7 @@ package org.opendaylight.controller.logging.bridge.internal; import org.osgi.service.log.LogEntry; import java.util.Enumeration; import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; import org.osgi.framework.BundleActivator; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.ServiceReference; @@ -64,6 +65,14 @@ public class Activator implements BundleActivator { */ Thread.setDefaultUncaughtExceptionHandler(new org.opendaylight. controller.logging.bridge.internal.UncaughtExceptionHandler()); + + /* + * Install the Shutdown handler. This will intercept SIGTERM signal and + * close the system bundle. This allows for a graceful closing of OSGI + * framework. + */ + + Runtime.getRuntime().addShutdownHook(new shutdownHandler(context)); } else { this.log.error("Cannot register the LogListener because " + "cannot retrieve LogReaderService"); @@ -86,4 +95,21 @@ public class Activator implements BundleActivator { this.listener = null; this.log = null; } + + private class shutdownHandler extends Thread { + BundleContext bundlecontext; + public shutdownHandler(BundleContext ctxt) { + this.bundlecontext = ctxt; + } + + public void run () { + try { + this.bundlecontext.getBundle(0).stop(); + log.debug("shutdown handler thread called"); + } catch (BundleException e) { + log.debug("Bundle couldn't be stopped"); + } + } + } + } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java index 9ec5b10ea8..bfa6f0ba0f 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -53,7 +52,8 @@ public class Controller implements IController, CommandProvider { private AtomicInteger switchInstanceNumber; /* - * this thread monitors the switchEvents queue for new incoming events from switch + * this thread monitors the switchEvents queue for new incoming events from + * switch */ private class EventHandler implements Runnable { @Override @@ -64,17 +64,13 @@ public class Controller implements IController, CommandProvider { SwitchEvent ev = switchEvents.take(); SwitchEvent.SwitchEventType eType = ev.getEventType(); ISwitch sw = ev.getSwitch(); - if (eType != SwitchEvent.SwitchEventType.SWITCH_MESSAGE) { - //logger.debug("Received " + ev.toString() + " from " + sw.toString()); - } switch (eType) { case SWITCH_ADD: Long sid = sw.getId(); ISwitch existingSwitch = switches.get(sid); if (existingSwitch != null) { - logger.info(" Replacing existing " - + existingSwitch.toString() + " with New " - + sw.toString()); + logger.info("Replacing existing {} with New {}", + existingSwitch.toString(), sw.toString()); disconnectSwitch(existingSwitch); } switches.put(sid, sw); @@ -97,7 +93,7 @@ public class Controller implements IController, CommandProvider { } break; default: - logger.error("unknow switch event " + eType.ordinal()); + logger.error("Unknown switch event {}", eType.ordinal()); } } catch (InterruptedException e) { switchEvents.clear(); @@ -111,10 +107,10 @@ public class Controller implements IController, CommandProvider { /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ public void init() { - logger.debug("OpenFlowCore init"); + logger.debug("Initializing!"); this.switches = new ConcurrentHashMap(); this.switchEvents = new LinkedBlockingQueue(); this.messageListeners = new ConcurrentHashMap(); @@ -124,13 +120,12 @@ public class Controller implements IController, CommandProvider { } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry - * + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * */ public void start() { - logger.debug("OpenFlowCore start() is called"); + logger.debug("Starting!"); /* * start a thread to handle event coming from the switch */ @@ -142,15 +137,15 @@ public class Controller implements IController, CommandProvider { try { controllerIO.start(); } catch (IOException ex) { - logger.error("Caught exception: " + ex + " during start"); + logger.error("Caught exception while starting:", ex); } } - + /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls - * + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * */ public void stop() { for (Iterator> it = switches.entrySet().iterator(); it @@ -161,17 +156,17 @@ public class Controller implements IController, CommandProvider { } switchEventThread.interrupt(); try { - controllerIO.shutDown(); + controllerIO.shutDown(); } catch (IOException ex) { - logger.error("Caught exception: " + ex + " during stop"); + logger.error("Caught exception while stopping:", ex); } } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ public void destroy() { } @@ -180,18 +175,20 @@ public class Controller implements IController, CommandProvider { public void addMessageListener(OFType type, IMessageListener listener) { IMessageListener currentListener = this.messageListeners.get(type); if (currentListener != null) { - logger.warn(type.toString() + " already listened by " - + currentListener.toString()); + logger.warn("{} is already listened by {}", type.toString(), + currentListener.toString()); } this.messageListeners.put(type, listener); - logger.debug(type.toString() + " is now listened by " - + listener.toString()); + logger.debug("{} is now listened by {}", type.toString(), + listener.toString()); } @Override public void removeMessageListener(OFType type, IMessageListener listener) { IMessageListener currentListener = this.messageListeners.get(type); if ((currentListener != null) && (currentListener == listener)) { + logger.debug("{} listener {} is Removed", type.toString(), + listener.toString()); this.messageListeners.remove(type); } } @@ -199,17 +196,20 @@ public class Controller implements IController, CommandProvider { @Override public void addSwitchStateListener(ISwitchStateListener listener) { if (this.switchStateListener != null) { - logger.warn(this.switchStateListener.toString() - + "already listened to switch events"); + logger.warn("Switch events are already listened by {}", + this.switchStateListener.toString()); } this.switchStateListener = listener; - logger.debug(listener.toString() + " now listens to switch events"); + logger.debug("Switch events are now listened by {}", + listener.toString()); } @Override public void removeSwitchStateListener(ISwitchStateListener listener) { if ((this.switchStateListener != null) && (this.switchStateListener == listener)) { + logger.debug("SwitchStateListener {} is Removed", + listener.toString()); this.switchStateListener = null; } } @@ -227,7 +227,12 @@ public class Controller implements IController, CommandProvider { SwitchHandler switchHandler = new SwitchHandler(this, sc, instanceName); switchHandler.start(); - logger.info(instanceName + " connected: " + sc.toString()); + if (sc.isConnected()) { + logger.info("Switch:{} is connected to the Controller", + sc.socket().getRemoteSocketAddress() + .toString().split("/")[1]); + } + } catch (IOException e) { return; } @@ -237,11 +242,8 @@ public class Controller implements IController, CommandProvider { if (((SwitchHandler) sw).isOperational()) { Long sid = sw.getId(); if (this.switches.remove(sid, sw)) { - logger.warn(sw.toString() + " is disconnected"); + logger.warn("{} is Disconnected", sw.toString()); notifySwitchDeleted(sw); - } else { - //logger.warn(sw.toString() + " has been replaced by " + - // this.switches.get(sid)); } } ((SwitchHandler) sw).stop(); @@ -268,7 +270,7 @@ public class Controller implements IController, CommandProvider { } } - public void takeSwtichEventAdd(ISwitch sw) { + public void takeSwitchEventAdd(ISwitch sw) { SwitchEvent ev = new SwitchEvent( SwitchEvent.SwitchEventType.SWITCH_ADD, sw, null); addSwitchEvent(ev); @@ -317,7 +319,8 @@ public class Controller implements IController, CommandProvider { while (iter.hasNext()) { Long sid = iter.next(); Date date = switches.get(sid).getConnectedDate(); - String switchInstanceName = ((SwitchHandler) switches.get(sid)).getInstanceName(); + String switchInstanceName = ((SwitchHandler) switches.get(sid)) + .getInstanceName(); s.append(switchInstanceName + "/" + HexString.toHexString(sid) + " connected since " + date.toString() + "\n"); } @@ -369,7 +372,7 @@ public class Controller implements IController, CommandProvider { @Override public String getHelp() { StringBuffer help = new StringBuffer(); - help.append("-- Open Flow Controller --\n"); + help.append("---Open Flow Controller---\n"); help.append("\t controllerShowSwitches\n"); help.append("\t controllerReset\n"); help.append("\t controllerShowConnConfig\n"); diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java index a4b7584337..868e208651 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -40,8 +39,8 @@ public class ControllerIO { try { openFlowPort = Short.decode(portString).shortValue(); } catch (NumberFormatException e) { - logger.warn("Invalid port:" + portString + ", use default(" - + openFlowPort + ")"); + logger.warn("Invalid port:{}, use default({})", portString, + openFlowPort); } } } @@ -72,8 +71,8 @@ public class ControllerIO { SelectionKey skey = selectedKeys.next(); selectedKeys.remove(); if (skey.isValid() && skey.isAcceptable()) { - ((Controller) listener).handleNewConnection(selector, - serverSelectionKey); + ((Controller) listener).handleNewConnection( + selector, serverSelectionKey); } } } catch (Exception e) { @@ -83,7 +82,7 @@ public class ControllerIO { } }, "ControllerI/O Thread"); controllerIOThread.start(); - logger.info("Controller is now listening on port " + openFlowPort); + logger.info("Controller is now listening on port {}", openFlowPort); } public void shutDown() throws IOException { diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java index bbf3e91462..57098ae3c6 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java @@ -356,11 +356,6 @@ public class SwitchHandler implements ISwitch { } for (OFMessage msg : msgs) { logger.trace("Message received: {}", msg.toString()); - /* - * if ((msg.getType() != OFType.ECHO_REQUEST) && (msg.getType() != - * OFType.ECHO_REPLY)) { logger.debug(msg.getType().toString() + - * " received from sw " + toString()); } - */ this.lastMsgReceivedTimeStamp = System.currentTimeMillis(); OFType type = msg.getType(); switch (type) { @@ -422,21 +417,14 @@ public class SwitchHandler implements ISwitch { } private void processPortStatusMsg(OFPortStatus msg) { - // short portNumber = msg.getDesc().getPortNumber(); OFPhysicalPort port = msg.getDesc(); if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) { updatePhysicalPort(port); - // logger.debug("Port " + portNumber + " on " + toString() + - // " modified"); } else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) { updatePhysicalPort(port); - // logger.debug("Port " + portNumber + " on " + toString() + - // " added"); } else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE .ordinal()) { deletePhysicalPort(port); - // logger.debug("Port " + portNumber + " on " + toString() + - // " deleted"); } } @@ -457,8 +445,9 @@ public class SwitchHandler implements ISwitch { reportSwitchStateChange(false); } else { // send a probe to see if the switch is still alive - // logger.debug("Send idle probe (Echo Request) to " - // + switchName()); + logger.debug( + "Send idle probe (Echo Request) to {}", + toString()); probeSent = true; OFMessage echo = factory .getMessage(OFType.ECHO_REQUEST); @@ -500,8 +489,7 @@ public class SwitchHandler implements ISwitch { private void reportError(Exception e) { if (e instanceof AsynchronousCloseException || e instanceof InterruptedException - || e instanceof SocketException - || e instanceof IOException) { + || e instanceof SocketException || e instanceof IOException) { logger.debug("Caught exception {}", e.getMessage()); } else { logger.warn("Caught exception ", e); @@ -512,7 +500,7 @@ public class SwitchHandler implements ISwitch { private void reportSwitchStateChange(boolean added) { if (added) { - ((Controller) core).takeSwtichEventAdd(this); + ((Controller) core).takeSwitchEventAdd(this); } else { ((Controller) core).takeSwitchEventDelete(this); } @@ -567,7 +555,7 @@ public class SwitchHandler implements ISwitch { .getValue() | OFPortFeatures.OFPPF_1GB_HD .getValue() | OFPortFeatures.OFPPF_10GB_FD - .getValue())); + .getValue())); } private void deletePhysicalPort(OFPhysicalPort port) { @@ -583,11 +571,16 @@ public class SwitchHandler implements ISwitch { @Override public String toString() { - return ("[" - + this.socket.toString() - + " SWID " - + (isOperational() ? HexString.toHexString(this.sid) - : "unkbown") + "]"); + try { + return ("Switch:" + + socket.socket().getRemoteSocketAddress().toString().split("/")[1] + + " SWID:" + (isOperational() ? HexString + .toHexString(this.sid) : "unknown")); + } catch (Exception e) { + return (isOperational() ? HexString.toHexString(this.sid) + : "unknown"); + } + } @Override @@ -823,14 +816,14 @@ public class SwitchHandler implements ISwitch { } /** - * Sends synchronous Barrier message + * Sends synchronous Barrier message */ @Override public Object sendBarrierMessage() { OFBarrierRequest barrierMsg = new OFBarrierRequest(); - return syncSend(barrierMsg); + return syncSend(barrierMsg); } - + /** * This method returns the switch liveness timeout value. If controller did * not receive any message from the switch for such a long period, diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DescStatisticsConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DescStatisticsConverter.java index 7a09a480dc..abad0b2ab5 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DescStatisticsConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DescStatisticsConverter.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -11,19 +10,22 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.util.List; +import org.opendaylight.controller.sal.reader.NodeDescription; import org.openflow.protocol.statistics.OFDescriptionStatistics; import org.openflow.protocol.statistics.OFStatistics; - -import org.opendaylight.controller.sal.reader.NodeDescription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Utility class for converting openflow description statistics - * into SAL NodeDescription object - * - * - * + * Utility class for converting openflow description statistics into SAL + * NodeDescription object + * + * + * */ public class DescStatisticsConverter { + private static final Logger log = LoggerFactory + .getLogger(DescStatisticsConverter.class); NodeDescription hwDesc; OFDescriptionStatistics ofDesc; @@ -41,6 +43,8 @@ public class DescStatisticsConverter { hwDesc.setDescription(ofDesc.getDatapathDescription()); hwDesc.setSerialNumber(ofDesc.getSerialNumber()); } + log.trace("OFDescriptionStatistics: {}", ofDesc); + log.trace("NodeDescription: {}", hwDesc); return hwDesc; } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java index 6379b5d74e..074774a25e 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java @@ -16,29 +16,6 @@ import java.util.List; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFVendor; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionDataLayerDestination; -import org.openflow.protocol.action.OFActionDataLayerSource; -import org.openflow.protocol.action.OFActionNetworkLayerAddress; -import org.openflow.protocol.action.OFActionNetworkLayerDestination; -import org.openflow.protocol.action.OFActionNetworkLayerSource; -import org.openflow.protocol.action.OFActionNetworkTypeOfService; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.protocol.action.OFActionStripVirtualLan; -import org.openflow.protocol.action.OFActionTransportLayer; -import org.openflow.protocol.action.OFActionTransportLayerDestination; -import org.openflow.protocol.action.OFActionTransportLayerSource; -import org.openflow.protocol.action.OFActionVirtualLanIdentifier; -import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint; -import org.openflow.util.U16; -import org.openflow.util.U32; - import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.Controller; @@ -67,6 +44,28 @@ import org.opendaylight.controller.sal.match.MatchField; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.openflow.protocol.OFFlowMod; +import org.openflow.protocol.OFMatch; +import org.openflow.protocol.OFMessage; +import org.openflow.protocol.OFPacketOut; +import org.openflow.protocol.OFPort; +import org.openflow.protocol.OFVendor; +import org.openflow.protocol.action.OFAction; +import org.openflow.protocol.action.OFActionDataLayerDestination; +import org.openflow.protocol.action.OFActionDataLayerSource; +import org.openflow.protocol.action.OFActionNetworkLayerAddress; +import org.openflow.protocol.action.OFActionNetworkLayerDestination; +import org.openflow.protocol.action.OFActionNetworkLayerSource; +import org.openflow.protocol.action.OFActionNetworkTypeOfService; +import org.openflow.protocol.action.OFActionOutput; +import org.openflow.protocol.action.OFActionStripVirtualLan; +import org.openflow.protocol.action.OFActionTransportLayer; +import org.openflow.protocol.action.OFActionTransportLayerDestination; +import org.openflow.protocol.action.OFActionTransportLayerSource; +import org.openflow.protocol.action.OFActionVirtualLanIdentifier; +import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint; +import org.openflow.util.U16; +import org.openflow.util.U32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,7 +74,7 @@ import org.slf4j.LoggerFactory; */ public class FlowConverter { protected static final Logger logger = LoggerFactory - .getLogger(FlowConverter.class); + .getLogger(FlowConverter.class); private Flow flow; // SAL Flow private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match private List actionsList; // OF 1.0 actions @@ -256,7 +255,8 @@ public class FlowConverter { ofMatch.setWildcards(U32.t(Long.valueOf(wildcards))); } } - + logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(), + ofMatch); return ofMatch; } @@ -416,6 +416,8 @@ public class FlowConverter { } } } + logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(), + actionsList); return actionsList; } @@ -483,6 +485,9 @@ public class FlowConverter { } } } + logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch, + actionsList); + logger.trace("Openflow Mod Message: {}", fm); return fm; } @@ -684,7 +689,7 @@ public class FlowConverter { try { ip = InetAddress.getByAddress(addr); } catch (UnknownHostException e) { - logger.error("",e); + logger.error("", e); } salAction = new SetNwSrc(ip); } else if (ofAction instanceof OFActionNetworkLayerDestination) { @@ -695,7 +700,7 @@ public class FlowConverter { try { ip = InetAddress.getByAddress(addr); } catch (UnknownHostException e) { - logger.error("",e); + logger.error("", e); } salAction = new SetNwDst(ip); } else if (ofAction instanceof OFActionNetworkTypeOfService) { @@ -719,6 +724,9 @@ public class FlowConverter { // Create Flow flow = new Flow(salMatch, salActionList); } + logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch, + actionsList); + logger.trace("SAL Flow: {}", flow); return flow; } 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 4d3dca1878..1d19c8b45c 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 @@ -8,7 +8,6 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -24,15 +23,6 @@ import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExtern import org.opendaylight.controller.protocol_plugin.openflow.core.IController; import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener; import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch; -import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error; -import org.openflow.protocol.OFError; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFFlowRemoved; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; - import org.opendaylight.controller.sal.core.ContainerFlow; import org.opendaylight.controller.sal.core.IContainerListener; import org.opendaylight.controller.sal.core.Node; @@ -47,8 +37,15 @@ import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NodeCreator; -import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.openflow.protocol.OFError; +import org.openflow.protocol.OFFlowMod; +import org.openflow.protocol.OFFlowRemoved; +import org.openflow.protocol.OFMessage; +import org.openflow.protocol.OFPort; +import org.openflow.protocol.OFType; +import org.openflow.protocol.action.OFAction; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; @@ -208,22 +205,11 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( - StatusCode.SUCCESS, null) : new Status( + StatusCode.SUCCESS, rid) : new Status( StatusCode.TIMEOUT, errorString(null, action, "Request Timed Out")); } else if (result instanceof OFError) { OFError res = (OFError) result; - if (res.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) { - V6Error er = new V6Error(res); - byte[] b = res.getError(); - ByteBuffer bb = ByteBuffer.allocate(b.length); - bb.put(b); - bb.rewind(); - er.readFrom(bb); - return new Status(StatusCode.INTERNALERROR, - errorString("program", action, - "Vendor Extension Internal Error")); - } return new Status(StatusCode.INTERNALERROR, errorString( "program", action, Utils.getOFErrorString(res))); } else { @@ -286,7 +272,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, return new Status(StatusCode.TIMEOUT, errorString(null, action, "Request Timed Out")); } else if (msg2 == null) { - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS, rid); } } else if (result instanceof OFError) { return new Status(StatusCode.INTERNALERROR, errorString( @@ -315,7 +301,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( - StatusCode.SUCCESS, null) : new Status( + StatusCode.SUCCESS, rid) : new Status( StatusCode.TIMEOUT, errorString(null, action, "Request Timed Out")); } else if (result instanceof OFError) { @@ -364,7 +350,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, } if (result instanceof Boolean) { return ((Boolean) result == Boolean.TRUE) ? new Status( - StatusCode.SUCCESS, null) : new Status( + StatusCode.SUCCESS, rid) : new Status( StatusCode.TIMEOUT, errorString(null, action, "Request Timed Out")); } else if (result instanceof OFError) { @@ -445,7 +431,20 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, xid = errorMsg.getXid(); } - long rid = getMessageRid(sw.getId(), xid); + Long rid = getMessageRid(sw.getId(), xid); + /* + * Null or zero requestId indicates that the error message is meant for + * a sync message. It will be handled by the sync message worker thread. + * Hence we are done here. + */ + if ((rid == null) || (rid == 0)) { + return; + } + + /* + * Notifies the caller that error has been reported for a previous flow + * programming request + */ for (Map.Entry containerNotifier : flowProgrammerNotifiers .entrySet()) { IFlowProgrammerNotifier notifier = containerNotifier.getValue(); @@ -585,10 +584,14 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService, * The OF message xid * @return The Request ID */ - public long getMessageRid(long swid, int xid) { + private Long getMessageRid(long swid, Integer xid) { + Long rid = null; + + if (xid == null) { + return rid; + } + Map swxid2rid = this.xid2rid.get(swid); - long rid = 0; - if (swxid2rid != null) { rid = swxid2rid.get(xid); } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java index 72482f0d13..7afe6ce5be 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -13,20 +12,24 @@ import java.util.ArrayList; import java.util.List; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsReply; -import org.openflow.protocol.statistics.OFFlowStatisticsReply; -import org.openflow.protocol.statistics.OFStatistics; - import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.reader.FlowOnNode; +import org.openflow.protocol.statistics.OFFlowStatisticsReply; +import org.openflow.protocol.statistics.OFStatistics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Converts an openflow list of flow statistics in a SAL list of FlowOnNode objects - * - * - * + * Converts an openflow list of flow statistics in a SAL list of FlowOnNode + * objects + * + * + * */ public class FlowStatisticsConverter { + private static final Logger log = LoggerFactory + .getLogger(FlowStatisticsConverter.class); private List ofStatsList; private List flowOnNodeList; @@ -34,7 +37,8 @@ public class FlowStatisticsConverter { if (statsList == null) {// || statsList.isEmpty()) { this.ofStatsList = new ArrayList(1); // dummy list } else { - this.ofStatsList = statsList; //new ArrayList(statsList); + this.ofStatsList = statsList; // new + // ArrayList(statsList); } this.flowOnNodeList = null; } @@ -83,6 +87,8 @@ public class FlowStatisticsConverter { flowOnNodeList.add(flowOnNode); } } + log.trace("OFStatistics: {} FlowOnNode: {}", ofStatsList, + flowOnNodeList); return flowOnNodeList; } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java index 73dcea574a..98a2962606 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -63,9 +62,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * It periodically polls the different OF statistics from the OF switches - * and caches them for quick retrieval for the above layers' modules - * It also provides an API to directly query the switch about the statistics + * It periodically polls the different OF statistics from the OF switches and + * caches them for quick retrieval for the above layers' modules It also + * provides an API to directly query the switch about the statistics */ public class OFStatisticsManager implements IOFStatisticsManager, IInventoryShimExternalListener, CommandProvider { @@ -94,15 +93,18 @@ public class OFStatisticsManager implements IOFStatisticsManager, private Timer statisticsTimer; private TimerTask statisticsTimerTask; private ConcurrentMap switchSupportsVendorExtStats; - private Map> txRates; // Per port sampled (every portStatsPeriod) transmit rate + private Map> txRates; // Per port sampled (every + // portStatsPeriod) transmit + // rate private Set descriptionListeners; /** - * The object containing the latest factoredSamples tx rate samples - * for a given switch port + * The object containing the latest factoredSamples tx rate samples for a + * given switch port */ protected class TxRates { - Deque sampledTxBytes; // contains the latest factoredSamples sampled transmitted bytes + Deque sampledTxBytes; // contains the latest factoredSamples + // sampled transmitted bytes public TxRates() { sampledTxBytes = new LinkedBlockingDeque(); @@ -110,8 +112,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, public void update(Long txBytes) { /* - * Based on how many samples our average works on, - * we might have to remove the oldest sample + * Based on how many samples our average works on, we might have to + * remove the oldest sample */ if (sampledTxBytes.size() == factoredSamples) { sampledTxBytes.removeLast(); @@ -123,6 +125,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * Returns the average transmit rate in bps + * * @return the average transmit rate [bps] */ public long getAverageTxRate() { @@ -155,10 +158,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init() { - flowStatistics = new ConcurrentHashMap>(); + flowStatistics = new ConcurrentHashMap>(); descStatistics = new ConcurrentHashMap>(); portStatistics = new ConcurrentHashMap>(); dummyList = new ArrayList(1); @@ -190,8 +193,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, StatsRequest req = pendingStatsRequests.take(); acquireStatistics(req.switchId, req.type); } catch (InterruptedException e) { - log.warn("Flow Statistics Collector thread " + - "interrupted"); + log.warn("Flow Statistics Collector thread " + + "interrupted", e); } } } @@ -206,7 +209,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, long switchId = switchPortStatsUpdated.take(); updatePortsTxRate(switchId); } catch (InterruptedException e) { - log.warn("TX Rate Updater thread interrupted"); + log.warn("TX Rate Updater thread interrupted", e); } } } @@ -214,19 +217,18 @@ public class OFStatisticsManager implements IOFStatisticsManager, } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ void destroy() { } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry - * + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * */ void start() { // Start managed timers @@ -243,10 +245,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, } /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls - * + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * */ void stop() { // Stop managed timers @@ -254,15 +256,15 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public void setStatisticsListener(IStatisticsListener s) { - this.descriptionListeners.add(s); + this.descriptionListeners.add(s); } - + public void unsetStatisticsListener(IStatisticsListener s) { - if (s != null) { - this.descriptionListeners.remove(s); - } + if (s != null) { + this.descriptionListeners.remove(s); + } } - + private void registerWithOSGIConsole() { BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()) .getBundleContext(); @@ -320,10 +322,15 @@ public class OFStatisticsManager implements IOFStatisticsManager, } private void addStatisticsTicks(Long switchId) { - switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume switch supports Vendor extension stats + switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume + // switch + // supports + // Vendor + // extension + // stats statisticsTimerTicks.put(switchId, new StatisticsTicks(true)); - log.info("Added Switch {} to target pool", HexString - .toHexString(switchId.longValue())); + log.info("Added Switch {} to target pool", + HexString.toHexString(switchId.longValue())); } protected static class StatisticsTicks { @@ -349,7 +356,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public boolean decrementFlowTicksIsZero() { - // Please ensure no code is inserted between the if check and the flowStatisticsTicks reset + // Please ensure no code is inserted between the if check and the + // flowStatisticsTicks reset if (--flowStatisticsTicks == 0) { flowStatisticsTicks = statisticsTickNumber; return true; @@ -358,7 +366,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public boolean decrementDescTicksIsZero() { - // Please ensure no code is inserted between the if check and the descriptionTicks reset + // Please ensure no code is inserted between the if check and the + // descriptionTicks reset if (--descriptionTicks == 0) { descriptionTicks = descriptionTickNumber; return true; @@ -367,7 +376,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public boolean decrementPortTicksIsZero() { - // Please ensure no code is inserted between the if check and the descriptionTicks reset + // Please ensure no code is inserted between the if check and the + // descriptionTicks reset if (--portStatisticsTicks == 0) { portStatisticsTicks = portTickNumber; return true; @@ -382,13 +392,11 @@ public class OFStatisticsManager implements IOFStatisticsManager, } private void printInfoMessage(String type, StatsRequest request) { - log - .info( - type - + " stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.", - new Object[] { HexString.toHexString(request.switchId), - pendingStatsRequests.size(), - statisticsCollector.getState().toString() }); + log.info( + "{} stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.", + new Object[] { type, HexString.toHexString(request.switchId), + pendingStatsRequests.size(), + statisticsCollector.getState().toString() }); } protected void decrementTicks() { @@ -399,9 +407,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, Long switchId = entry.getKey(); if (clock.decrementFlowTicksIsZero() == true) { request = (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) ? new StatsRequest( - switchId, OFStatisticsType.VENDOR) - : new StatsRequest(switchId, OFStatisticsType.FLOW); - // If a request for this switch is already in the queue, skip to add this new request + switchId, OFStatisticsType.VENDOR) : new StatsRequest( + switchId, OFStatisticsType.FLOW); + // If a request for this switch is already in the queue, skip to + // add this new request if (!pendingStatsRequests.contains(request) && false == pendingStatsRequests.offer(request)) { printInfoMessage("Flow", request); @@ -410,7 +419,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (clock.decrementDescTicksIsZero() == true) { request = new StatsRequest(switchId, OFStatisticsType.DESC); - // If a request for this switch is already in the queue, skip to add this new request + // If a request for this switch is already in the queue, skip to + // add this new request if (!pendingStatsRequests.contains(request) && false == pendingStatsRequests.offer(request)) { printInfoMessage("Description", request); @@ -419,7 +429,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (clock.decrementPortTicksIsZero() == true) { request = new StatsRequest(switchId, OFStatisticsType.PORT); - // If a request for this switch is already in the queue, skip to add this new request + // If a request for this switch is already in the queue, skip to + // add this new request if (!pendingStatsRequests.contains(request) && false == pendingStatsRequests.offer(request)) { printInfoMessage("Port", request); @@ -429,9 +440,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, } private void removeStatsRequestTasks(Long switchId) { - log.info("Cleaning Statistics database for switch " - + HexEncode.longToHexString(switchId)); - // To be safe, let's attempt removal of both VENDOR and FLOW request. It does not hurt + log.info("Cleaning Statistics database for switch {}", + HexEncode.longToHexString(switchId)); + // To be safe, let's attempt removal of both VENDOR and FLOW request. It + // does not hurt pendingStatsRequests.remove(new StatsRequest(switchId, OFStatisticsType.VENDOR)); pendingStatsRequests.remove(new StatsRequest(switchId, @@ -449,8 +461,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, statisticsTimerTicks.remove(switchId); removeStatsRequestTasks(switchId); flowStatistics.remove(switchId); - log.info("Statistics removed for switch " - + HexString.toHexString(switchId)); + log.info("Statistics removed for switch {}", + HexString.toHexString(switchId)); } private void acquireStatistics(Long switchId, OFStatisticsType statType) { @@ -465,29 +477,30 @@ public class OFStatisticsManager implements IOFStatisticsManager, || (statType == OFStatisticsType.VENDOR)) { flowStatistics.put(switchId, values); } else if (statType == OFStatisticsType.DESC) { - // Notify who may be interested in a description change - notifyDescriptionListeners(switchId, values); - + // Notify who may be interested in a description change + notifyDescriptionListeners(switchId, values); + // Overwrite cache descStatistics.put(switchId, values); } else if (statType == OFStatisticsType.PORT) { // Overwrite cache with new port statistics for this switch portStatistics.put(switchId, values); - // Wake up the thread which maintains the TX byte counters for each port + // Wake up the thread which maintains the TX byte counters for + // each port switchPortStatsUpdated.offer(switchId); } } } private void notifyDescriptionListeners(Long switchId, - List values) { - for (IStatisticsListener l : this.descriptionListeners) { - l.descriptionRefreshed(switchId, - ((OFDescriptionStatistics)values.get(0))); - } + List values) { + for (IStatisticsListener l : this.descriptionListeners) { + l.descriptionRefreshed(switchId, + ((OFDescriptionStatistics) values.get(0))); + } } - + /* * Generic function to get the statistics form a OF switch */ @@ -511,8 +524,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, match.setWildcards(0xffffffff); } else if (!(target instanceof OFMatch)) { // Malformed request - log.warn("Invalid target type for Flow stats request: " - + target.getClass()); + log.warn("Invalid target type for Flow stats request: {}", + target.getClass()); return null; } else { // Specific flow request @@ -552,8 +565,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, targetPort = (short) OFPort.OFPP_NONE.getValue(); } else if (!(target instanceof Short)) { // Malformed request - log.warn("Invalid target type for Port stats request: " - + target.getClass()); + log.warn("Invalid target type for Port stats request: {}", + target.getClass()); return null; } else { // Specific port request @@ -585,14 +598,13 @@ public class OFStatisticsManager implements IOFStatisticsManager, log.warn("Request Timed Out for ({}) from switch {}", type, HexString.toHexString(switchId)); } else if (result instanceof OFError) { - log.warn("Switch {} failed to handle ({}) stats request: " - + Utils.getOFErrorString((OFError) result), HexString - .toHexString(switchId), type); + log.warn("Switch {} failed to handle ({}) stats request: {}", + new Object[] { HexString.toHexString(switchId), type, + Utils.getOFErrorString((OFError) result) }); if (this.switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) { - log - .warn( - "Switching back to regular Flow stats requests for switch {}", - HexString.toHexString(switchId)); + log.warn( + "Switching back to regular Flow stats requests for switch {}", + HexString.toHexString(switchId)); this.switchSupportsVendorExtStats.put(switchId, Boolean.FALSE); } @@ -608,8 +620,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, List list = flowStatistics.get(switchId); /* - * Check on emptiness as interference between add and get is still - * possible on the inner list (the concurrentMap entry's value) + * Check on emptiness as interference between add and get is still + * possible on the inner list (the concurrentMap entry's value) */ return (list == null || list.isEmpty()) ? this.dummyList : (list.get(0) instanceof OFVendorStatistics) ? this @@ -621,8 +633,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, List statsList = flowStatistics.get(switchId); /* - * Check on emptiness as interference between add and get is still - * possible on the inner list (the concurrentMap entry's value) + * Check on emptiness as interference between add and get is still + * possible on the inner list (the concurrentMap entry's value) */ if (statsList == null || statsList.isEmpty()) { return this.dummyList; @@ -630,10 +642,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (statsList.get(0) instanceof OFVendorStatistics) { /* - * Caller could provide regular OF match when we - * instead pull the vendor statistics from this node - * Caller is not supposed to know whether this switch supports - * vendor extensions statistics requests + * Caller could provide regular OF match when we instead pull the + * vendor statistics from this node Caller is not supposed to know + * whether this switch supports vendor extensions statistics + * requests */ V6Match targetMatch = (ofMatch instanceof V6Match) ? (V6Match) ofMatch : new V6Match(ofMatch); @@ -689,19 +701,18 @@ public class OFStatisticsManager implements IOFStatisticsManager, ByteBuffer data = ByteBuffer.allocate(length); stat.writeTo(data); data.rewind(); - log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}", HexString - .toHexString(data.array())); + log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}", + HexString.toHexString(data.array())); - int vendor = data.getInt(); //first 4 bytes is vendor id. + int vendor = data.getInt(); // first 4 bytes is vendor id. if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) { - log - .debug("Unexpected vendor id: 0x{}", Integer - .toHexString(vendor)); + log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor)); return null; } else { - //go ahead by 8 bytes which is 8 bytes of 0 - data.getLong(); //should be all 0's - length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have been consumed + // go ahead by 8 bytes which is 8 bytes of 0 + data.getLong(); // should be all 0's + length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have + // been consumed } V6StatsReply v6statsreply; @@ -727,8 +738,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, public List queryStatistics(Long switchId, OFStatisticsType statType, Object target) { /* - * Caller does not know and it is not supposed to know whether - * this switch supports vendor extension. We adjust the target for him + * Caller does not know and it is not supposed to know whether this + * switch supports vendor extension. We adjust the target for him */ if (statType == OFStatisticsType.FLOW) { if (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) { @@ -782,7 +793,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } /* - * InventoryShim replay for us all the switch addition which happened before we were brought up + * InventoryShim replay for us all the switch addition which happened before + * we were brought up */ @Override public void updateNode(Node node, UpdateType type, Set props) { @@ -804,8 +816,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, } /** - * Update the cached port rates for this switch with the latest - * retrieved port transmit byte count + * Update the cached port rates for this switch with the latest retrieved + * port transmit byte count + * * @param switchId */ private synchronized void updatePortsTxRate(long switchId) { @@ -861,8 +874,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, public String getHelp() { StringBuffer help = new StringBuffer(); help.append("---OF Statistics Manager utilities---\n"); - help.append("\t ofdumpstatsmgr - " + - "Print Internal Stats Mgr db\n"); + help.append("\t ofdumpstatsmgr - " + + "Print Internal Stats Mgr db\n"); return help.toString(); } @@ -909,9 +922,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, public void _ofdumpstatsmgr(CommandInterpreter ci) { ci.println("Global Counter: " + counter); - ci - .println("Timer Ticks: " - + prettyPrintSwitchMap(statisticsTimerTicks)); + ci.println("Timer Ticks: " + prettyPrintSwitchMap(statisticsTimerTicks)); ci.println("PendingStatsQueue: " + pendingStatsRequests); ci.println("PendingStatsQueue size: " + pendingStatsRequests.size()); ci.println("Stats Collector alive: " + statisticsCollector.isAlive()); @@ -973,10 +984,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, String averageWindow = ci.nextArgument(); short seconds = 0; if (averageWindow == null) { - ci.println("Insert the length in seconds of the median " + - "window for tx rate"); - ci.println("Current: " + factoredSamples * portTickNumber - + " secs"); + ci.println("Insert the length in seconds of the median " + + "window for tx rate"); + ci.println("Current: " + factoredSamples * portTickNumber + " secs"); return; } try { @@ -984,40 +994,40 @@ public class OFStatisticsManager implements IOFStatisticsManager, } catch (NumberFormatException e) { ci.println("Invalid period."); } - OFStatisticsManager.factoredSamples = (short) (seconds/portTickNumber); + OFStatisticsManager.factoredSamples = (short) (seconds / portTickNumber); ci.println("New: " + factoredSamples * portTickNumber + " secs"); } public void _ofstatsmgrintervals(CommandInterpreter ci) { String flowStatsInterv = ci.nextArgument(); String portStatsInterv = ci.nextArgument(); - + if (flowStatsInterv == null || portStatsInterv == null) { ci.println("Usage: ostatsmgrintervals (in seconds)"); - ci.println("Current Values: fP=" + statisticsTickNumber + - "s pP=" + portTickNumber + "s"); + ci.println("Current Values: fP=" + statisticsTickNumber + "s pP=" + + portTickNumber + "s"); return; } Short fP, pP; try { - fP = Short.parseShort(flowStatsInterv); - pP = Short.parseShort(portStatsInterv); + fP = Short.parseShort(flowStatsInterv); + pP = Short.parseShort(portStatsInterv); } catch (Exception e) { - ci.println("Invalid format values: " + e.getMessage()); - return; + ci.println("Invalid format values: " + e.getMessage()); + return; } - if (pP <= 1 || fP <=1) { - ci.println("Invalid values. fP and pP have to be greater than 1."); - return; + if (pP <= 1 || fP <= 1) { + ci.println("Invalid values. fP and pP have to be greater than 1."); + return; } - + statisticsTickNumber = fP; portTickNumber = pP; - - ci.println("New Values: fP=" + statisticsTickNumber + - "s pP=" + portTickNumber + "s"); + + ci.println("New Values: fP=" + statisticsTickNumber + "s pP=" + + portTickNumber + "s"); } } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortConverter.java index 61d6730042..410781683b 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortConverter.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -9,24 +8,27 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; -import org.openflow.protocol.OFPort; - import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.openflow.protocol.OFPort; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Abstract class which provides the utilities for converting - * the Openflow port number to the equivalent NodeConnector and vice versa - * - * - * + * Abstract class which provides the utilities for converting the Openflow port + * number to the equivalent NodeConnector and vice versa + * + * + * */ public abstract class PortConverter { - private static final int maxOFPhysicalPort = - NetUtils.getUnsignedShort(OFPort.OFPP_MAX.getValue()); + private static final Logger log = LoggerFactory + .getLogger(PortConverter.class); + private static final int maxOFPhysicalPort = NetUtils + .getUnsignedShort(OFPort.OFPP_MAX.getValue()); /** * Converts the Openflow port number to the equivalent NodeConnector. @@ -34,7 +36,8 @@ public abstract class PortConverter { public static NodeConnector toNodeConnector(short ofPort, Node node) { // Restore original OF unsigned 16 bits value for the comparison int unsignedOFPort = NetUtils.getUnsignedShort(ofPort); - + log.trace("Openflow port number signed: {} unsigned: {}", ofPort, + unsignedOFPort); if (unsignedOFPort > maxOFPhysicalPort) { if (ofPort == OFPort.OFPP_LOCAL.getValue()) { return NodeConnectorCreator.createNodeConnector( @@ -57,13 +60,12 @@ public abstract class PortConverter { * Converts the NodeConnector to the equivalent Openflow port number */ public static short toOFPort(NodeConnector salPort) { + log.trace("SAL Port", salPort); if (salPort.getType().equals(NodeConnectorIDType.SWSTACK)) { return OFPort.OFPP_LOCAL.getValue(); - } else if (salPort.getType().equals( - NodeConnectorIDType.HWPATH)) { + } else if (salPort.getType().equals(NodeConnectorIDType.HWPATH)) { return OFPort.OFPP_NORMAL.getValue(); - } else if (salPort.getType().equals( - NodeConnectorIDType.CONTROLLER)) { + } else if (salPort.getType().equals(NodeConnectorIDType.CONTROLLER)) { return OFPort.OFPP_CONTROLLER.getValue(); } return (Short) salPort.getID(); diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortStatisticsConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortStatisticsConverter.java index 2b4df3f0c1..3fbf68fbc1 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortStatisticsConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortStatisticsConverter.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -12,21 +11,24 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.util.ArrayList; import java.util.List; -import org.openflow.protocol.statistics.OFPortStatisticsReply; -import org.openflow.protocol.statistics.OFStatistics; - import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; import org.opendaylight.controller.sal.utils.NodeCreator; +import org.openflow.protocol.statistics.OFPortStatisticsReply; +import org.openflow.protocol.statistics.OFStatistics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Converts an openflow list of port statistics in a SAL list of * NodeConnectorStatistics objects - * - * - * + * + * + * */ public class PortStatisticsConverter { + private static final Logger log = LoggerFactory + .getLogger(PortStatisticsConverter.class); private long switchId; private List ofStatsList; private List ncStatsList; @@ -63,13 +65,13 @@ public class PortStatisticsConverter { .getReceiveFrameErrors()); NCStat.setReceiveOverRunErrorCount(ofPortStat .getReceiveOverrunErrors()); - NCStat - .setReceiveCRCErrorCount(ofPortStat - .getReceiveCRCErrors()); + NCStat.setReceiveCRCErrorCount(ofPortStat.getReceiveCRCErrors()); NCStat.setCollisionCount(ofPortStat.getCollisions()); this.ncStatsList.add(NCStat); } } + log.trace("OFStatistics: {} NodeConnectorStatistics: {}", ofStatsList, + ncStatsList); return this.ncStatsList; } diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Utils.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Utils.java index 77a39e904a..f1ce03af28 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Utils.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Utils.java @@ -9,6 +9,9 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; +import java.nio.ByteBuffer; + +import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error; import org.openflow.protocol.OFError; import org.openflow.protocol.OFError.OFBadActionCode; import org.openflow.protocol.OFError.OFBadRequestCode; @@ -20,6 +23,18 @@ import org.openflow.protocol.OFError.OFQueueOpFailedCode; public abstract class Utils { public static String getOFErrorString(OFError error) { + // Handle VENDOR extension errors here + if (error.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) { + V6Error er = new V6Error(error); + byte[] b = error.getError(); + ByteBuffer bb = ByteBuffer.allocate(b.length); + bb.put(b); + bb.rewind(); + er.readFrom(bb); + return er.toString(); + } + + // Handle OF1.0 errors here OFErrorType et = OFErrorType.values()[0xffff & error.getErrorType()]; String errorStr = "Error : " + et.toString(); switch (et) { diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java index 5cdf9d8368..dbd7eafa36 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java @@ -20,7 +20,10 @@ public interface IFlowProgrammerService { * Synchronously add a flow to the network node * * @param node + * The target network node * @param flow + * The flow to install + * @return The status of this request */ Status addFlow(Node node, Flow flow); @@ -28,7 +31,12 @@ public interface IFlowProgrammerService { * Synchronously modify existing flow on the switch * * @param node - * @param flow + * The target network node + * @param oldFlow + * The existing flow to modify + * @param newFlow + * The new flow to install + * @return The status of this request */ Status modifyFlow(Node node, Flow oldFlow, Flow newFlow); @@ -36,7 +44,10 @@ public interface IFlowProgrammerService { * Synchronously remove the flow from the network node * * @param node + * The target network node * @param flow + * The flow to remove + * @return The status of this request */ Status removeFlow(Node node, Flow flow); @@ -44,7 +55,10 @@ public interface IFlowProgrammerService { * Asynchronously add a flow to the network node * * @param node + * The target network node * @param flow + * The flow to install + * @return The status of this request containing the unique request id */ Status addFlowAsync(Node node, Flow flow); @@ -52,7 +66,12 @@ public interface IFlowProgrammerService { * Asynchronously modify existing flow on the switch * * @param node - * @param flow + * The target network node + * @param oldFlow + * The existing flow to modify + * @param newFlow + * The new flow to install + * @return The status of this request containing the unique request id */ Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow); @@ -60,7 +79,10 @@ public interface IFlowProgrammerService { * Asynchronously remove the flow from the network node * * @param node + * The target network node * @param flow + * The flow to remove + * @return The status of this request containing the unique request id */ Status removeFlowAsync(Node node, Flow flow); @@ -68,13 +90,23 @@ public interface IFlowProgrammerService { * Remove all flows present on the network node * * @param node + * The target network node + * @return The status of this request containing the unique request id */ Status removeAllFlows(Node node); /** - * Send synchronous Barrier message + * Send synchronous Barrier message + * + * Solicit the network node to report whether all the requests sent so far + * are completed. When this call is done, caller knows that all past flow + * operations requested to the node in asynchronous fashion were satisfied + * by the network node and that in case of any failure, a message was sent + * to the controller. * * @param node + * The network node to solicit + * @return The status of this request containing the unique request id */ Status sendBarrierMessage(Node node); } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java index 503e08e714..2fbb3e55f8 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java @@ -14,8 +14,9 @@ package org.opendaylight.controller.sal.utils; * a string which describes a failure reason (if any) in human readable form. */ public class Status { - StatusCode code; - String description; + private StatusCode code; + private String description; + private long requestId; /** * Generates an instance of the Status class. This is used as return code @@ -34,6 +35,7 @@ public class Status { this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED; this.description = (description != null) ? description : this.code .toString(); + this.requestId = 0; } /** @@ -49,6 +51,27 @@ public class Status { this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED; this.description = (description != null) ? description : this.code .toString(); + this.requestId = 0; + } + + /** + * Generates an instance of the Status class to be used in case of + * asynchronous call. It is supposed to be created by the underlying + * infrastructure only when it was successful in allocating the asynchronous + * request id, hence caller should expect StatusCode to be successful. + * + * @param errorCode + * The status code. If passed as null, code will be stored as + * {@code StatusCode.UNDEFINED} + * @param requestId + * The request id set by underlying infrastructure for this + * request + */ + public Status(StatusCode errorCode, long requestId) { + this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED; + this.description = (description != null) ? description : this.code + .toString(); + this.requestId = requestId; } /** @@ -78,9 +101,20 @@ public class Status { return code == StatusCode.SUCCESS; } + /** + * Return the request id assigned by underlying infrastructure in case of + * asynchronous request. In case of synchronous requests, the returned id + * is expected to be 0 + * + * @return The request id assigned for this asynchronous request + */ + public long getRequestId() { + return requestId; + } + @Override public String toString() { - return code + ": " + description; + return code + ": " + description + " (" + requestId + ")"; } @Override diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java index 1c63e4e200..0abebf8352 100644 --- a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java @@ -28,8 +28,8 @@ import org.opendaylight.controller.sal.action.PopVlan; import org.opendaylight.controller.sal.action.SetNwDst; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Node; -import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener; import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; @@ -37,11 +37,11 @@ import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerSer import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml index add138e8b9..ce0543dafd 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml @@ -54,7 +54,13 @@ org.mockito mockito-all 1.8.4 - + + + com.google.guava + guava + 14.0.1 + + diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/antlr/YangParser.g4 b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/antlr/YangParser.g4 index 1ef6242c5f..e15184dea5 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/antlr/YangParser.g4 +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/antlr/YangParser.g4 @@ -16,7 +16,7 @@ string : STRING (PLUS STRING)*; identifier_stmt : IDENTIFIER string? stmtend; -stmtend : (SEMICOLON identifier_stmt?) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE); +stmtend : (SEMICOLON) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE); deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE)); deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE)); deviate_add_stmt : DEVIATE_KEYWORD string /*ADD_KEYWORD*/ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE)); @@ -78,7 +78,7 @@ require_instance_stmt : REQUIRE_INSTANCE_KEYWORD require_instance_arg stmtend; path_stmt : PATH_KEYWORD string stmtend; leafref_specification : path_stmt; enum_stmt : ENUM_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |value_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE)); -enum_specification : enum_stmt (identifier_stmt | enum_stmt )+; +enum_specification : enum_stmt (identifier_stmt | enum_stmt )*; default_stmt : DEFAULT_KEYWORD string stmtend; pattern_stmt : PATTERN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE)); length_stmt : LENGTH_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE)); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/IdentitySchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/IdentitySchemaNodeBuilder.java index 906afd97a0..979d89298a 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/IdentitySchemaNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/IdentitySchemaNodeBuilder.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.yang.model.parser.builder.impl; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -24,6 +25,7 @@ public class IdentitySchemaNodeBuilder implements SchemaNodeBuilder { private final IdentitySchemaNodeImpl instance; private IdentitySchemaNodeBuilder baseIdentity; private String baseIdentityName; + private final List addedUnknownNodes = new ArrayList(); IdentitySchemaNodeBuilder(final QName qname) { this.qname = qname; @@ -38,6 +40,14 @@ public class IdentitySchemaNodeBuilder implements SchemaNodeBuilder { final IdentitySchemaNode base = baseIdentity.build(); instance.setBaseIdentity(base); } + + // UNKNOWN NODES + final List unknownNodes = new ArrayList(); + for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { + unknownNodes.add(b.build()); + } + instance.setUnknownSchemaNodes(unknownNodes); + return instance; } @@ -73,10 +83,13 @@ public class IdentitySchemaNodeBuilder implements SchemaNodeBuilder { } } + public List getUnknownNodes() { + return addedUnknownNodes; + } + @Override - public void addUnknownSchemaNode(final UnknownSchemaNodeBuilder unknownNode) { - throw new IllegalStateException( - "Can not add schema node to identity statement"); + public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) { + addedUnknownNodes.add(unknownNode); } public String getBaseIdentityName() { @@ -98,6 +111,7 @@ public class IdentitySchemaNodeBuilder implements SchemaNodeBuilder { private String reference; private Status status = Status.CURRENT; private SchemaPath path; + private List unknownNodes = Collections.emptyList(); private IdentitySchemaNodeImpl(final QName qname) { this.qname = qname; @@ -157,7 +171,14 @@ public class IdentitySchemaNodeBuilder implements SchemaNodeBuilder { @Override public List getUnknownSchemaNodes() { - return Collections.emptyList(); + return unknownNodes; + } + + private void setUnknownSchemaNodes( + List unknownSchemaNodes) { + if (unknownSchemaNodes != null) { + this.unknownNodes = unknownSchemaNodes; + } } @Override diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java index 996ba6e2ee..e309172f4c 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java @@ -514,7 +514,7 @@ public class ModuleBuilder implements Builder { List pathToCase = new ArrayList(parentPath); ChoiceCaseBuilder builder = new ChoiceCaseBuilder(caseName); - final ChoiceBuilder parent = (ChoiceBuilder) moduleNodes + final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes .get(pathToCase); if (parent != null) { if (parent instanceof AugmentationSchemaBuilder) { @@ -524,7 +524,6 @@ public class ModuleBuilder implements Builder { } pathToCase.add(caseName.getLocalName()); - addedChilds.put(pathToCase, builder); moduleNodes.put(pathToCase, builder); return builder; @@ -591,11 +590,12 @@ public class ModuleBuilder implements Builder { } public void addIdentityrefType(String baseString, List parentPath) { + List pathToIdentityref = new ArrayList(parentPath); TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes - .get(parentPath); + .get(pathToIdentityref); IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(baseString); parent.setType(identityref); - dirtyNodes.put(parentPath, parent); + dirtyNodes.put(pathToIdentityref, parent); } public DeviationBuilder addDeviation(String targetPath, @@ -608,8 +608,11 @@ public class ModuleBuilder implements Builder { return builder; } - public IdentitySchemaNodeBuilder addIdentity(QName qname) { + public IdentitySchemaNodeBuilder addIdentity(QName qname, List parentPath) { + List pathToIdentity = new ArrayList(parentPath); IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(qname); + pathToIdentity.add(qname.getLocalName()); + moduleNodes.put(pathToIdentity, builder); addedIdentities.add(builder); return builder; } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java index e2ebea7f88..b10798b980 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java @@ -78,6 +78,7 @@ import org.opendaylight.controller.yang.model.parser.util.YangParseException; import org.opendaylight.controller.yang.model.util.ExtendedType; import org.opendaylight.controller.yang.model.util.IdentityrefType; import org.opendaylight.controller.yang.model.util.UnknownType; +import org.opendaylight.controller.yang.model.validator.YangModelBasicValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -161,19 +162,8 @@ public class YangModelParserImpl implements YangModelParser { final List trees = parseStreams(yangFiles); final ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; - // validation - // if validation fails with any file, do not continue and throw - // exception - for (int i = 0; i < trees.size(); i++) { - try { - final YangModelValidationListener yangModelParser = new YangModelValidationListener(); - walker.walk(yangModelParser, trees.get(i)); - } catch (IllegalStateException e) { - // wrap exception to add information about which file failed - throw new YangValidationException( - "Yang validation failed for file" + yangFiles[i], e); - } - } + // validate yang + new YangModelBasicValidator(walker).validate(trees); YangModelParserListenerImpl yangModelParser = null; for (int i = 0; i < trees.size(); i++) { @@ -727,7 +717,6 @@ public class YangModelParserImpl implements YangModelParser { final QName currentQName = currentParent.getQName(); final QName lastAugmentPathElement = path.get(path.size() - 1); - if (currentQName.getLocalName().equals( lastAugmentPathElement.getLocalName())) { fillAugmentTarget(augmentBuilder, @@ -902,7 +891,6 @@ public class YangModelParserImpl implements YangModelParser { } } } - } /** @@ -997,7 +985,7 @@ public class YangModelParserImpl implements YangModelParser { if(baseString.contains(":")) { String[] splittedBase = baseString.split(":"); if(splittedBase.length > 2) { - throw new YangParseException("Failed to parse identity base: "+ baseString); + throw new YangParseException("Failed to parse identityref base: "+ baseString); } String prefix = splittedBase[0]; String name = splittedBase[1]; @@ -1029,7 +1017,7 @@ public class YangModelParserImpl implements YangModelParser { if (prefix.equals(module.getPrefix())) { dependentModule = module; } else { - final ModuleImport dependentModuleImport = getModuleImport(module, + final ModuleImport dependentModuleImport = ParserUtils.getModuleImport(module, prefix); if (dependentModuleImport == null) { throw new YangParseException("No import found with prefix '" @@ -1065,26 +1053,6 @@ public class YangModelParserImpl implements YangModelParser { return dependentModule; } - /** - * Get module import referenced by given prefix. - * - * @param builder - * module to search - * @param prefix - * prefix associated with import - * @return ModuleImport based on given prefix - */ - private ModuleImport getModuleImport(final ModuleBuilder builder, - final String prefix) { - ModuleImport moduleImport = null; - for (ModuleImport mi : builder.getModuleImports()) { - if (mi.getPrefix().equals(prefix)) { - moduleImport = mi; - break; - } - } - return moduleImport; - } private static class SchemaContextImpl implements SchemaContext { private final Set modules; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java index 76eafaa26d..bc5f77be83 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java @@ -78,8 +78,8 @@ import org.opendaylight.controller.yang.model.util.YangTypesConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class YangModelParserListenerImpl extends YangParserBaseListener { - +public final class YangModelParserListenerImpl extends YangParserBaseListener { + private static final Logger logger = LoggerFactory .getLogger(YangModelParserListenerImpl.class); @@ -90,7 +90,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { private String yangModelPrefix; private Date revision = new Date(0L); - final static DateFormat simpleDateFormat = new SimpleDateFormat( + public final static DateFormat simpleDateFormat = new SimpleDateFormat( "yyyy-MM-dd"); private final Stack actualPath = new Stack(); @@ -325,7 +325,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { if (YangTypesConverter.isBaseYangType(typeName)) { if (typeBody == null) { // if there are no constraints, just grab default base yang type - type = YangTypesConverter.javaTypeForBaseYangType(typeName); + type = YangTypesConverter.javaTypeForBaseYangType(actualPath, namespace, revision, typeName); moduleBuilder.setType(type, actualPath); } else { if ("union".equals(typeName)) { @@ -770,7 +770,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { final QName identityQName = new QName(namespace, revision, yangModelPrefix, identityName); IdentitySchemaNodeBuilder builder = moduleBuilder - .addIdentity(identityQName); + .addIdentity(identityQName, actualPath); updatePath(identityName); builder.setPath(createActualSchemaPath(actualPath, namespace, revision, diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListener.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListener.java deleted file mode 100644 index 68887a1915..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListener.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 2013 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.yang.model.parser.impl; - -import java.net.URI; -import java.net.URISyntaxException; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; - -import org.antlr.v4.runtime.tree.ParseTree; -import org.opendaylight.controller.antlrv4.code.gen.YangParser; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener; -import org.opendaylight.controller.yang.model.parser.util.YangModelBuilderUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Validation listener that validates yang statements according to RFC-6020. - * This validator expects only one module or submodule per file. - */ - -/* - * TODO is this assumption(module per file) correct ? if so, should a check be - * performed ? - * - * TODO break into smaller classes e.g. class for header statements, body - * statements... - */ -final class YangModelValidationListener extends YangParserBaseListener { - - private static final Logger logger = LoggerFactory - .getLogger(YangModelValidationListener.class); - - private final Set uniquePrefixes; - private final Set uniqueImports; - private final Set uniqueIncludes; - - public YangModelValidationListener() { - super(); - uniquePrefixes = new HashSet(); - uniqueImports = new HashSet(); - uniqueIncludes = new HashSet(); - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. One revision statements present
  4. - *
  5. One header statements present
  6. - *
- */ - @Override - public void enterModule_stmt(YangParser.Module_stmtContext ctx) { - String moduleName = getName(ctx); - - checkIdentifier(moduleName, "Module"); - - checkPresentChildOfType(ctx, Revision_stmtsContext.class, - f("Missing revision statements in module:%s", moduleName), true); - - checkPresentChildOfType(ctx, Module_header_stmtsContext.class, - f("Missing header statements in module:%s", moduleName), true); - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. One revision statements present
  4. - *
  5. One header statements present
  6. - *
- */ - @Override - public void enterSubmodule_stmt(Submodule_stmtContext ctx) { - String submoduleName = getName(ctx); - - checkIdentifier(submoduleName, "Submodule"); - - checkPresentChildOfType( - ctx, - Revision_stmtsContext.class, - f("Missing revision statements in submodule:%s", submoduleName), - true); - - checkPresentChildOfType(ctx, Submodule_header_stmtsContext.class, - f("Missing header statements in submodule:%s", submoduleName), - true); - } - - /** - * Rules: - *
    - *
  1. One Belongs-to statement present
  2. - *
- */ - @Override - public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) { - String submoduleName = getRootParentName(ctx); - - checkPresentChildOfType( - ctx, - Belongs_to_stmtContext.class, - f("Missing belongs-to statement in submodule:%s", submoduleName), - true); - - // check Yang version present, if not issue warning - checkYangVersion(ctx, submoduleName); - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. One Prefix statement child
  4. - *
- */ - @Override - public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) { - String belongToName = getName(ctx); - String rootParentName = getRootParentName(ctx); - - checkIdentifier(belongToName, - f("In (sub)module:%s , Belongs-to statement", rootParentName)); - - checkPresentChildOfType( - ctx, - Prefix_stmtContext.class, - f("Missing prefix statement in belongs-to:%s, in (sub)module:%s", - belongToName, rootParentName), true); - } - - /** - * Rules: - *
    - *
  1. At least one Revision statement present
  2. - *
- */ - @Override - public void enterRevision_stmts(Revision_stmtsContext ctx) { - String rootParentName = getRootParentName(ctx); - - checkPresentChildOfType( - ctx, - Revision_stmtContext.class, - f("Missing at least one revision statement in (sub)module:%s", - rootParentName), false); - } - - /** - * Rules: - *
    - *
  1. One Namespace statement present
  2. - *
- */ - @Override - public void enterModule_header_stmts(Module_header_stmtsContext ctx) { - String moduleName = getRootParentName(ctx); - - checkPresentChildOfType(ctx, Namespace_stmtContext.class, - f("Missing namespace statement in module:%s", moduleName), true); - - // check Yang version present, if not issue warning - checkYangVersion(ctx, moduleName); - } - - /** - * Rules: - *
    - *
  1. Namespace string can be parsed as URI
  2. - *
- */ - @Override - public void enterNamespace_stmt(Namespace_stmtContext ctx) { - String namespaceName = getName(ctx); - String rootParentName = getRootParentName(ctx); - - try { - new URI(namespaceName); - } catch (URISyntaxException e) { - throw new YangValidationException(f( - "Namespace:%s in module:%s cannot be parsed as URI", - namespaceName, rootParentName)); - } - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. Every import(identified by identifier) within a module/submodule is - * present only once
  4. - *
  5. One prefix statement child
  6. - *
  7. One revision-date statement child
  8. - *
- */ - @Override - public void enterImport_stmt(Import_stmtContext ctx) { - String importName = getName(ctx); - String rootParentName = getRootParentName(ctx); - - checkIdentifier(importName, - f("In (sub)module:%s , Import statement", rootParentName)); - - if (uniqueImports.contains(importName)) - throw new YangValidationException(f( - "Module:%s imported twice in (sub)module:%s", importName, - rootParentName)); - uniqueImports.add(importName); - - checkPresentChildOfType( - ctx, - Prefix_stmtContext.class, - f("Missing prefix statement in import:%s, in (sub)module:%s", - importName, rootParentName), true); - //checkPresentChildOfType( - // ctx, - // Revision_date_stmtContext.class, - // f("Missing revision-date statement in import:%s, in (sub)module:%s", - // importName, rootParentName), true); - } - - /** - * Rules: - *
    - *
  1. Date is in valid format
  2. - *
- */ - @Override - public void enterRevision_date_stmt(Revision_date_stmtContext ctx) { - String rootParentName = getRootParentName(ctx); - String exceptionMessage = f( - "Invalid date format for revision-date:%s in import/include statement:%s, in (sub)module:%s , expected date format is:%s", - getName(ctx), getRootParentName(ctx), rootParentName, - YangModelParserListenerImpl.simpleDateFormat.format(new Date())); - - validateDateFormat(getName(ctx), - YangModelParserListenerImpl.simpleDateFormat, exceptionMessage); - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. Every include(identified by identifier) within a module/submodule is - * present only once
  4. - *
  5. One Revision-date statement child
  6. - *
- */ - @Override - public void enterInclude_stmt(Include_stmtContext ctx) { - String includeName = getName(ctx); - String rootParentName = getRootParentName(ctx); - - checkIdentifier(includeName, - f("In (sub)module:%s , Include statement", rootParentName)); - - if (uniqueIncludes.contains(includeName)) - throw new YangValidationException(f( - "Submodule:%s included twice in (sub)module:%s", - includeName, rootParentName)); - uniqueIncludes.add(includeName); - - checkPresentChildOfType( - ctx, - Revision_date_stmtContext.class, - f("Missing revision-date statement in include:%s, in (sub)module:%s", - includeName, rootParentName), true); - } - - static final String SUPPORTED_YANG_VERSION = "1"; - - /** - * Rules: - *
    - *
  1. Yang-version is specified as 1
  2. - *
- */ - @Override - public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) { - String version = getName(ctx); - String rootParentName = getRootParentName(ctx); - if (!version.equals(SUPPORTED_YANG_VERSION)) { - throw new YangValidationException( - f("Unsupported yang version:%s, in (sub)module:%s, supported version:%s", - version, rootParentName, SUPPORTED_YANG_VERSION)); - } - } - - /** - * Rules: - *
    - *
  1. Date is in valid format
  2. - *
- */ - @Override - public void enterRevision_stmt(YangParser.Revision_stmtContext ctx) { - String parentName = getRootParentName(ctx); - String exceptionMessage = f( - "Invalid date format for revision:%s in (sub)module:%s, expected date format is:%s", - getName(ctx), parentName, - YangModelParserListenerImpl.simpleDateFormat.format(new Date())); - - validateDateFormat(getName(ctx), - YangModelParserListenerImpl.simpleDateFormat, exceptionMessage); - } - - /** - * Rules: - *
    - *
  1. Identifier contains only permitted characters
  2. - *
  3. Every prefix(identified by identifier) within a module/submodule is - * presented only once
  4. - *
- */ - @Override - public void enterPrefix_stmt(Prefix_stmtContext ctx) { - String name = getName(ctx); - checkIdentifier( - name, - f("In module or import statement:%s , Prefix", - getRootParentName(ctx))); - - if (uniquePrefixes.contains(name)) - throw new YangValidationException(f( - "Not a unique prefix:%s, in (sub)module:%s", name, - getRootParentName(ctx))); - uniquePrefixes.add(name); - } - - private String getRootParentName(ParseTree ctx) { - ParseTree root = ctx; - while (root.getParent() != null) { - root = root.getParent(); - } - return getName(root); - } - - private static String getName(ParseTree child) { - return YangModelBuilderUtil.stringFromNode(child); - } - - private static String f(String base, Object... args) { - return String.format(base, args); - } - - private static void checkYangVersion(ParseTree ctx, String moduleName) { - if (!checkPresentChildOfType(ctx, Yang_version_stmtContext.class, true)) - logger.warn(f( - "Yang version statement not present in module:%s, Validating as yang version:%s", - moduleName, SUPPORTED_YANG_VERSION)); - } - - private static void validateDateFormat(String string, DateFormat format, - String message) { - try { - format.parse(string); - } catch (ParseException e) { - throw new YangValidationException(message); - } - } - - private static Pattern identifierPattern = Pattern - .compile("[a-zA-Z_][a-zA-Z0-9_.-]*"); - - static void checkIdentifier(String name, String messagePrefix) { - if (!identifierPattern.matcher(name).matches()) - throw new YangValidationException(f( - "%s identifier:%s is not in required format:%s", - messagePrefix, name, identifierPattern.toString())); - } - - private static void checkPresentChildOfType(ParseTree ctx, - Class expectedChildType, String message, boolean atMostOne) { - if (!checkPresentChildOfType(ctx, expectedChildType, atMostOne)) - throw new YangValidationException(message); - } - - private static boolean checkPresentChildOfType(ParseTree ctx, - Class expectedChildType, boolean atMostOne) { - - int count = 0; - - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (expectedChildType.isInstance(child)) - count++; - } - - return atMostOne ? count == 1 ? true : false : count != 0 ? true - : false; - } -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/ParserUtils.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/ParserUtils.java index f533b8e6d7..e7775ce734 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/ParserUtils.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/ParserUtils.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ModuleImport; import org.opendaylight.controller.yang.model.api.MustDefinition; import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.TypeDefinition; @@ -27,6 +28,7 @@ import org.opendaylight.controller.yang.model.parser.builder.impl.ContainerSchem import org.opendaylight.controller.yang.model.parser.builder.impl.LeafListSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.LeafSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.ListSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.UnknownSchemaNodeBuilder; public final class ParserUtils { @@ -34,6 +36,32 @@ public final class ParserUtils { private ParserUtils() { } + /** + * Get module import referenced by given prefix. + * + * @param builder + * module to search + * @param prefix + * prefix associated with import + * @return ModuleImport based on given prefix + */ + public static ModuleImport getModuleImport(final ModuleBuilder builder, + final String prefix) { + ModuleImport moduleImport = null; + for (ModuleImport mi : builder.getModuleImports()) { + if (mi.getPrefix().equals(prefix)) { + moduleImport = mi; + break; + } + } + return moduleImport; + } + + /** + * Parse uses path. + * @param usesPath as String + * @return SchemaPath from given String + */ public static SchemaPath parseUsesPath(final String usesPath) { final boolean absolute = usesPath.startsWith("/"); final String[] splittedPath = usesPath.split("/"); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java index 8b33702d47..94b790f78f 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java @@ -88,13 +88,21 @@ import org.opendaylight.controller.yang.model.parser.util.RefineHolder.Refine; import org.opendaylight.controller.yang.model.util.BaseConstraints; import org.opendaylight.controller.yang.model.util.BinaryType; import org.opendaylight.controller.yang.model.util.BitsType; +import org.opendaylight.controller.yang.model.util.Decimal64; import org.opendaylight.controller.yang.model.util.EnumerationType; import org.opendaylight.controller.yang.model.util.InstanceIdentifier; +import org.opendaylight.controller.yang.model.util.Int16; +import org.opendaylight.controller.yang.model.util.Int32; +import org.opendaylight.controller.yang.model.util.Int64; +import org.opendaylight.controller.yang.model.util.Int8; import org.opendaylight.controller.yang.model.util.Leafref; import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl; import org.opendaylight.controller.yang.model.util.StringType; +import org.opendaylight.controller.yang.model.util.Uint16; +import org.opendaylight.controller.yang.model.util.Uint32; +import org.opendaylight.controller.yang.model.util.Uint64; +import org.opendaylight.controller.yang.model.util.Uint8; import org.opendaylight.controller.yang.model.util.UnknownType; -import org.opendaylight.controller.yang.model.util.YangTypesConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -982,19 +990,32 @@ public final class YangModelBuilderUtil { typeBody, actualPath, namespace, revision, prefix); if ("decimal64".equals(typeName)) { - type = YangTypesConverter.javaTypeForBaseYangDecimal64Type( - rangeStatements, fractionDigits); + type = new Decimal64(actualPath, namespace, revision, fractionDigits); } else if (typeName.startsWith("int")) { - type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType( - typeName, rangeStatements); + if (typeName.equals("int8")) { + type = new Int8(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("int16")) { + type = new Int16(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("int32")) { + type = new Int32(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("int64")) { + type = new Int64(actualPath, namespace, revision, rangeStatements, null, null); + } } else if (typeName.startsWith("uint")) { - type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType( - typeName, rangeStatements); + if (typeName.equals("uint8")) { + type = new Uint8(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("uint16")) { + type = new Uint16(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("uint32")) { + type = new Uint32(actualPath, namespace, revision, rangeStatements, null, null); + } else if (typeName.equals("uint64")) { + type = new Uint64(actualPath, namespace, revision, rangeStatements, null, null); + } } else if ("enumeration".equals(typeName)) { type = new EnumerationType(actualPath, namespace, revision, enumConstants); } else if ("string".equals(typeName)) { - type = new StringType(lengthStatements, patternStatements); + type = new StringType(actualPath, namespace, revision, lengthStatements, patternStatements); } else if ("bits".equals(typeName)) { type = new BitsType(getBits(typeBody, actualPath, namespace, revision, prefix)); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangValidationException.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangValidationException.java similarity index 78% rename from opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangValidationException.java rename to opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangValidationException.java index 43d39406de..25d317da12 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangValidationException.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangValidationException.java @@ -5,13 +5,13 @@ * 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.yang.model.parser.impl; +package org.opendaylight.controller.yang.model.parser.util; /** * Unchecked exception thrown if yang definition is not valid according to - * {@link YangModelValidationListener} + * {@link YangModelBasicValidationListener} */ -public class YangValidationException extends RuntimeException { +public final class YangValidationException extends RuntimeException { private static final long serialVersionUID = 7414330400390825381L; diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/BasicValidations.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/BasicValidations.java new file mode 100644 index 0000000000..f9e3fc2770 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/BasicValidations.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2013 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/eplv10.html + */ +package org.opendaylight.controller.yang.model.validator; + +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; +import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +import com.google.common.collect.Sets; + +/** + * Reusable checks of basic constraints on yang statements + */ +final class BasicValidations { + + static final String SUPPORTED_YANG_VERSION = "1"; + + static void checkNotPresentBoth(ParseTree parent, + Class childType1, + Class childType2) { + if (BasicValidations.checkPresentChildOfTypeSafe(parent, childType1, + true) + && BasicValidations.checkPresentChildOfTypeSafe(parent, + childType2, false)) + ValidationUtil + .ex(ValidationUtil + .f("(In (sub)module:%s) Both %s and %s statement present in %s:%s", + ValidationUtil.getRootParentName(parent), + ValidationUtil + .getSimpleStatementName(childType1), + ValidationUtil + .getSimpleStatementName(childType2), + ValidationUtil + .getSimpleStatementName(parent + .getClass()), + ValidationUtil.getName(parent))); + } + + static void checkOnlyPermittedValues(ParseTree ctx, + Set permittedValues) { + String mandatory = ValidationUtil.getName(ctx); + String rootParentName = ValidationUtil.getRootParentName(ctx); + + if (!permittedValues.contains(mandatory)) + ValidationUtil + .ex(ValidationUtil + .f("(In (sub)module:%s) %s:%s, illegal value for %s statement, only permitted:%s", + rootParentName, ValidationUtil + .getSimpleStatementName(ctx + .getClass()), mandatory, + ValidationUtil.getSimpleStatementName(ctx + .getClass()), permittedValues)); + } + + static void checkUniquenessInNamespace(ParseTree stmt, Set uniques) { + String name = ValidationUtil.getName(stmt); + String rootParentName = ValidationUtil.getRootParentName(stmt); + + if (uniques.contains(name)) + ValidationUtil.ex(ValidationUtil.f( + "(In (sub)module:%s) %s:%s not unique in (sub)module", + rootParentName, + ValidationUtil.getSimpleStatementName(stmt.getClass()), + name)); + uniques.add(name); + } + + /** + * Check if only one module or submodule is present in session(one yang + * file) + */ + static void checkOnlyOneModulePresent(String moduleName, String globalId) { + if (globalId != null) + ValidationUtil.ex(ValidationUtil + .f("Multiple (sub)modules per file")); + } + + static void checkPresentYangVersion(ParseTree ctx, String moduleName) { + if (!checkPresentChildOfTypeSafe(ctx, Yang_version_stmtContext.class, + true)) + ValidationUtil + .ex(ValidationUtil + .f("Yang version statement not present in module:%s, Validating as yang version:%s", + moduleName, SUPPORTED_YANG_VERSION)); + } + + static void checkDateFormat(ParseTree stmt, DateFormat format) { + try { + format.parse(ValidationUtil.getName(stmt)); + } catch (ParseException e) { + String exceptionMessage = ValidationUtil + .f("(In (sub)module:%s) %s:%s, invalid date format expected date format is:%s", + ValidationUtil.getRootParentName(stmt), + ValidationUtil.getSimpleStatementName(stmt + .getClass()), ValidationUtil.getName(stmt), + YangModelParserListenerImpl.simpleDateFormat + .format(new Date())); + ValidationUtil.ex(exceptionMessage); + } + } + + static Pattern identifierPattern = Pattern + .compile("[a-zA-Z_][a-zA-Z0-9_.-]*"); + + static void checkIdentifier(ParseTree statement) { + checkIdentifierInternal(statement, ValidationUtil.getName(statement)); + } + + static void checkIdentifierInternal(ParseTree statement, String name) { + if (!identifierPattern.matcher(name).matches()) { + + String message = ValidationUtil + .f("%s statement identifier:%s is not in required format:%s", + ValidationUtil.getSimpleStatementName(statement + .getClass()), name, identifierPattern + .toString()); + String parent = ValidationUtil.getRootParentName(statement); + message = parent.equals(name) ? message : ValidationUtil.f( + "(In (sub)module:%s) %s", parent, message); + + ValidationUtil.ex(message); + } + } + + static Pattern prefixedIdentifierPattern = Pattern.compile("(.+):(.+)"); + + static void checkPrefixedIdentifier(ParseTree statement) { + checkPrefixedIdentifierInternal(statement, + ValidationUtil.getName(statement)); + } + + private static void checkPrefixedIdentifierInternal(ParseTree statement, + String id) { + Matcher matcher = prefixedIdentifierPattern.matcher(id); + + if (matcher.matches()) { + try { + // check prefix + checkIdentifierInternal(statement, matcher.group(1)); + // check ID + checkIdentifierInternal(statement, matcher.group(2)); + } catch (YangValidationException e) { + ValidationUtil.ex(ValidationUtil.f( + "Prefixed id:%s not in required format, details:%s", + id, e.getMessage())); + } + } else + checkIdentifierInternal(statement, id); + } + + static void checkSchemaNodeIdentifier(ParseTree statement) { + String id = ValidationUtil.getName(statement); + + try { + for (String oneOfId : id.split("/")) { + if (oneOfId.isEmpty()) + continue; + checkPrefixedIdentifierInternal(statement, oneOfId); + } + } catch (YangValidationException e) { + ValidationUtil.ex(ValidationUtil.f( + "Schema node id:%s not in required format, details:%s", id, + e.getMessage())); + } + } + + private static interface MessageProvider { + String getMessage(); + } + + static void checkPresentChildOfTypeInternal(ParseTree parent, + Set> expectedChildType, + MessageProvider message, boolean atMostOne) { + if (!checkPresentChildOfTypeSafe(parent, expectedChildType, atMostOne)) { + String str = atMostOne ? "(Expected exactly one statement) " + + message.getMessage() : message.getMessage(); + ValidationUtil.ex(str); + } + } + + static void checkPresentChildOfType(final ParseTree parent, + final Class expectedChildType, + boolean atMostOne) { + + // Construct message in checkPresentChildOfTypeInternal only if + // validaiton fails, not in advance + MessageProvider message = new MessageProvider() { + + @Override + public String getMessage() { + String message = ValidationUtil + .f("Missing %s statement in %s:%s", ValidationUtil + .getSimpleStatementName(expectedChildType), + ValidationUtil.getSimpleStatementName(parent + .getClass()), ValidationUtil + .getName(parent)); + + String root = ValidationUtil.getRootParentName(parent); + message = parent.equals(ValidationUtil + .getRootParentName(parent)) ? message : ValidationUtil + .f("(In (sub)module:%s) %s", root, message); + return message; + } + }; + + Set> expectedChildTypeSet = Sets + .newHashSet(); + expectedChildTypeSet.add(expectedChildType); + + checkPresentChildOfTypeInternal(parent, expectedChildTypeSet, message, + atMostOne); + } + + static void checkPresentChildOfTypes(final ParseTree parent, + final Set> expectedChildTypes, + boolean atMostOne) { + + // Construct message in checkPresentChildOfTypeInternal only if + // validaiton fails, not in advance + MessageProvider message = new MessageProvider() { + + @Override + public String getMessage() { + StringBuilder childTypes = new StringBuilder(); + String orStr = " OR "; + for (Class type : expectedChildTypes) { + childTypes.append(ValidationUtil + .getSimpleStatementName(type)); + childTypes.append(orStr); + } + + String message = ValidationUtil + .f("Missing %s statement in %s:%s", childTypes + .toString(), ValidationUtil + .getSimpleStatementName(parent.getClass()), + ValidationUtil.getName(parent)); + + String root = ValidationUtil.getRootParentName(parent); + message = parent.equals(ValidationUtil + .getRootParentName(parent)) ? message : ValidationUtil + .f("(In (sub)module:%s) %s", root, message); + + return message; + } + }; + + checkPresentChildOfTypeInternal(parent, expectedChildTypes, message, + atMostOne); + } + + static boolean checkPresentChildOfTypeSafe(ParseTree parent, + Set> expectedChildType, boolean atMostOne) { + + int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType( + parent, expectedChildType); + + return atMostOne ? foundChildrenOfType == 1 ? true : false + : foundChildrenOfType != 0 ? true : false; + } + + static boolean checkPresentChildOfTypeSafe(ParseTree parent, + Class expectedChildType, boolean atMostOne) { + + int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType( + parent, expectedChildType); + + return atMostOne ? foundChildrenOfType == 1 ? true : false + : foundChildrenOfType != 0 ? true : false; + } + + static List getAndCheckUniqueKeys(ParseTree ctx) { + String key = ValidationUtil.getName(ctx); + ParseTree parent = ctx.getParent(); + String rootParentName = ValidationUtil.getRootParentName(ctx); + + List keyList = ValidationUtil.listKeysFromId(key); + Set duplicates = ValidationUtil.getDuplicates(keyList); + + if (duplicates.size() != 0) + ValidationUtil.ex(ValidationUtil.f( + "(In (sub)module:%s) %s:%s, %s:%s contains duplicates:%s", + rootParentName, + ValidationUtil.getSimpleStatementName(parent.getClass()), + ValidationUtil.getName(parent), + ValidationUtil.getSimpleStatementName(ctx.getClass()), key, + duplicates)); + return keyList; + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/ValidationUtil.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/ValidationUtil.java new file mode 100644 index 0000000000..31c4b8a34b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/ValidationUtil.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013 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/eplv10.html + */ +package org.opendaylight.controller.yang.model.validator; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext; +import org.opendaylight.controller.yang.model.parser.util.YangModelBuilderUtil; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +/** + * Validation utilities + */ +final class ValidationUtil { + + static void ex(String message) { + throw new YangValidationException(message); + } + + static Set getDuplicates(Collection keyList) { + Set all = new HashSet(); + Set duplicates = new HashSet(); + + for (String key : keyList) { + if (!all.add(key)) + duplicates.add(key); + } + return duplicates; + } + + static List listKeysFromId(String keys) { + return Arrays.asList(keys.split(" ")); + } + + static String getRootParentName(ParseTree ctx) { + ParseTree root = getRootParent(ctx); + return ValidationUtil.getName(root); + } + + private static ParseTree getRootParent(ParseTree ctx) { + ParseTree root = ctx; + while (root.getParent() != null) { + if (root.getClass().equals(Module_stmtContext.class) + || root.getClass().equals(Submodule_stmtContext.class)) + break; + root = root.getParent(); + } + return root; + } + + static String getName(ParseTree child) { + return YangModelBuilderUtil.stringFromNode(child); + } + + static String f(String base, Object... args) { + return String.format(base, args); + } + + /** + * Get simple name from statement class e.g. Module from Module_stmt_context + */ + static String getSimpleStatementName( + Class typeOfStatement) { + + String className = typeOfStatement.getSimpleName(); + int lastIndexOf = className.indexOf('$'); + className = lastIndexOf == -1 ? className : className + .substring(lastIndexOf + 1); + int indexOfStmt = className.indexOf("_stmt"); + int index = indexOfStmt == -1 ? className.indexOf("_arg") : indexOfStmt; + return className.substring(0, index).replace('_', '-'); + } + + static int countPresentChildrenOfType(ParseTree parent, + Set> expectedChildTypes) { + int foundChildrenOfType = 0; + + for (Class type : expectedChildTypes) { + foundChildrenOfType += countPresentChildrenOfType(parent, type); + } + return foundChildrenOfType; + } + + static int countPresentChildrenOfType(ParseTree parent, + Class expectedChildType) { + int foundChildrenOfType = 0; + + for (int i = 0; i < parent.getChildCount(); i++) { + ParseTree child = parent.getChild(i); + if (expectedChildType.isInstance(child)) + foundChildrenOfType++; + } + return foundChildrenOfType; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidationListener.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidationListener.java new file mode 100644 index 0000000000..37e2a215b3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidationListener.java @@ -0,0 +1,672 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Set; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Anyxml_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Case_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Choice_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Extension_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Feature_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Grouping_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identity_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.If_feature_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Notification_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Rpc_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Typedef_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Uses_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener; +import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; + +/** + * Validation listener that validates yang statements according to RFC-6020. + * This validator expects only one module or submodule per file and performs + * only basic validation where context from all yang models is not present. + */ +final class YangModelBasicValidationListener extends YangParserBaseListener { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelBasicValidationListener.class); + + private final Set uniquePrefixes; + private final Set uniqueImports; + private final Set uniqueIncludes; + + private String globalModuleId; + + YangModelBasicValidationListener() { + super(); + uniquePrefixes = Sets.newHashSet(); + uniqueImports = Sets.newHashSet(); + uniqueIncludes = Sets.newHashSet(); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Header statements present(mandatory prefix and namespace statements + * are in header)
  4. + *
  5. Only one module or submodule per file
  6. + *
+ */ + @Override + public void enterModule_stmt(Module_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, + Module_header_stmtsContext.class, true); + + String moduleName = ValidationUtil.getName(ctx); + BasicValidations.checkOnlyOneModulePresent(moduleName, globalModuleId); + globalModuleId = moduleName; + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Header statements present(mandatory belongs-to statement is in + * header)
  4. + *
  5. Only one module or submodule per file
  6. + *
+ */ + @Override + public void enterSubmodule_stmt(Submodule_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, + Submodule_header_stmtsContext.class, true); + + String submoduleName = ValidationUtil.getName(ctx); + BasicValidations.checkOnlyOneModulePresent(submoduleName, + globalModuleId); + globalModuleId = submoduleName; + + } + + /** + * Constraints: + *
    + *
  1. One Belongs-to statement present
  2. + *
+ */ + @Override + public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) { + BasicValidations.checkPresentChildOfType(ctx, + Belongs_to_stmtContext.class, true); + + // check Yang version present, if not log + try { + BasicValidations.checkPresentYangVersion(ctx, + ValidationUtil.getRootParentName(ctx)); + } catch (Exception e) { + logger.debug(e.getMessage()); + } + } + + /** + * Constraints: + *
    + *
  1. One Namespace statement present
  2. + *
  3. One Prefix statement present
  4. + *
+ */ + @Override + public void enterModule_header_stmts(Module_header_stmtsContext ctx) { + String moduleName = ValidationUtil.getRootParentName(ctx); + + BasicValidations.checkPresentChildOfType(ctx, + Namespace_stmtContext.class, true); + BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class, + true); + + // check Yang version present, if not log + try { + BasicValidations.checkPresentYangVersion(ctx, moduleName); + } catch (Exception e) { + logger.debug(e.getMessage()); + } + } + + /** + * Constraints: + *
    + *
  1. Date is in valid format
  2. + *
+ */ + @Override + public void enterRevision_stmt(Revision_stmtContext ctx) { + BasicValidations.checkDateFormat(ctx, + YangModelParserListenerImpl.simpleDateFormat); + + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. One Prefix statement child
  4. + *
+ */ + @Override + public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class, + true); + } + + /** + * Constraints: + *
    + *
  1. Namespace string can be parsed as URI
  2. + *
+ */ + @Override + public void enterNamespace_stmt(Namespace_stmtContext ctx) { + String namespaceName = ValidationUtil.getName(ctx); + String rootParentName = ValidationUtil.getRootParentName(ctx); + + try { + new URI(namespaceName); + } catch (URISyntaxException e) { + ValidationUtil.ex(ValidationUtil.f( + "(In module:%s) Namespace:%s cannot be parsed as URI", + rootParentName, namespaceName)); + } + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Every import(identified by identifier) within a module/submodule is + * present only once
  4. + *
  5. One prefix statement child
  6. + *
+ */ + @Override + public void enterImport_stmt(Import_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkUniquenessInNamespace(ctx, uniqueImports); + + BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class, + true); + + } + + /** + * Constraints: + *
    + *
  1. Date is in valid format
  2. + *
+ */ + @Override + public void enterRevision_date_stmt(Revision_date_stmtContext ctx) { + BasicValidations.checkDateFormat(ctx, + YangModelParserListenerImpl.simpleDateFormat); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Every include(identified by identifier) within a module/submodule is + * present only once
  4. + *
+ */ + @Override + public void enterInclude_stmt(Include_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkUniquenessInNamespace(ctx, uniqueIncludes); + } + + /** + * Constraints: + *
    + *
  1. Yang-version is specified as 1
  2. + *
+ */ + @Override + public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) { + String version = ValidationUtil.getName(ctx); + String rootParentName = ValidationUtil.getRootParentName(ctx); + if (!version.equals(BasicValidations.SUPPORTED_YANG_VERSION)) { + ValidationUtil + .ex(ValidationUtil + .f("(In (sub)module:%s) Unsupported yang version:%s, supported version:%s", + rootParentName, version, + BasicValidations.SUPPORTED_YANG_VERSION)); + } + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Every prefix(identified by identifier) within a module/submodule is + * presented only once
  4. + *
+ */ + @Override + public void enterPrefix_stmt(Prefix_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkUniquenessInNamespace(ctx, uniquePrefixes); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. One type statement child
  4. + *
+ */ + @Override + public void enterTypedef_stmt(Typedef_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class, + true); + } + + /** + * Constraints: + *
    + *
  1. (Prefix):Identifier is in required format
  2. + *
+ */ + @Override + public void enterType_stmt(Type_stmtContext ctx) { + BasicValidations.checkPrefixedIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterContainer_stmt(Container_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. One type statement child
  4. + *
  5. Default statement must not be present if mandatory statement is
  6. + *
+ */ + @Override + public void enterLeaf_stmt(Leaf_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class, + true); + + BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class, + Default_stmtContext.class); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. One type statement child
  4. + *
+ */ + @Override + public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) { + + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class, + true); + } + + private static final Set permittedOrderByArgs = Sets.newHashSet( + "system", "user"); + + /** + * Constraints: + *
    + *
  1. Value must be one of: system, user
  2. + *
+ */ + @Override + public void enterOrdered_by_arg(Ordered_by_argContext ctx) { + BasicValidations.checkOnlyPermittedValues(ctx, permittedOrderByArgs); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterList_stmt(List_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + // TODO check: "if config==true then key must be present" could be + // performed + } + + /** + * Constraints: + *
    + *
  1. No duplicate keys
  2. + *
+ */ + @Override + public void enterKey_stmt(Key_stmtContext ctx) { + BasicValidations.getAndCheckUniqueKeys(ctx); + } + + /** + * Constraints: + *
    + * + *
+ */ + @Override + public void enterUnique_stmt(Unique_stmtContext ctx) { + BasicValidations.getAndCheckUniqueKeys(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
  3. Default statement must not be present if mandatory statement is
  4. + *
+ */ + @Override + public void enterChoice_stmt(Choice_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + + BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class, + Default_stmtContext.class); + + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterCase_stmt(Case_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + private static final Set permittedBooleanArgs = Sets.newHashSet( + "true", "false"); + + /** + * Constraints: + *
    + *
  1. Value must be one of: true, false
  2. + *
+ */ + @Override + public void enterMandatory_arg(Mandatory_argContext ctx) { + BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterAnyxml_stmt(Anyxml_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterGrouping_stmt(Grouping_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. (Prefix):Identifier is in required format
  2. + *
+ */ + @Override + public void enterUses_stmt(Uses_stmtContext ctx) { + BasicValidations.checkPrefixedIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterRefine_stmt(Refine_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterRpc_stmt(Rpc_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterNotification_stmt(Notification_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Schema Node Identifier is in required format
  2. + *
+ */ + @Override + public void enterAugment_stmt(Augment_stmtContext ctx) { + BasicValidations.checkSchemaNodeIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterIdentity_stmt(Identity_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. (Prefix):Identifier is in required format
  2. + *
+ */ + @Override + public void enterBase_stmt(Base_stmtContext ctx) { + BasicValidations.checkPrefixedIdentifier(ctx); + + } + + /** + * Constraints: + *
    + *
  1. Value must be one of: true, false
  2. + *
+ */ + @Override + public void enterYin_element_arg(Yin_element_argContext ctx) { + BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterExtension_stmt(Extension_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterArgument_stmt(Argument_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Identifier is in required format
  2. + *
+ */ + @Override + public void enterFeature_stmt(Feature_stmtContext ctx) { + BasicValidations.checkIdentifier(ctx); + + } + + /** + * Constraints: + *
    + *
  1. (Prefix):Identifier is in required format
  2. + *
+ */ + @Override + public void enterIf_feature_stmt(If_feature_stmtContext ctx) { + BasicValidations.checkPrefixedIdentifier(ctx); + } + + /** + * Constraints: + *
    + *
  1. Schema Node Identifier is in required format
  2. + *
  3. At least one deviate-* statement child
  4. + *
+ */ + @Override + public void enterDeviation_stmt(Deviation_stmtContext ctx) { + BasicValidations.checkSchemaNodeIdentifier(ctx); + + Set> types = Sets.newHashSet(); + types.add(Deviate_add_stmtContext.class); + types.add(Deviate_add_stmtContext.class); + BasicValidations.checkPresentChildOfTypes(ctx, types, false); + } + + /** + * Constraints: + *
    + *
  1. Value must be one of: true, false
  2. + *
+ */ + @Override + public void enterConfig_arg(Config_argContext ctx) { + BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs); + } + + private static final Set permittedStatusArgs = Sets.newHashSet( + "current", "deprecated", "obsolete"); + + /** + * Constraints: + *
    + *
  1. Value must be one of: "current", "deprecated", "obsolete"
  2. + *
+ */ + @Override + public void enterStatus_arg(Status_argContext ctx) { + BasicValidations.checkOnlyPermittedValues(ctx, permittedStatusArgs); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidator.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidator.java new file mode 100644 index 0000000000..dc80dba014 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/validator/YangModelBasicValidator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import java.util.List; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +/** + * Exposed basic yang validation. + * + * Every file is validated using {@link YangModelBasicValidationListener}. + */ +public final class YangModelBasicValidator { + + private final ParseTreeWalker walker; + + public YangModelBasicValidator(ParseTreeWalker walker) { + this.walker = walker; + } + + public YangModelBasicValidator() { + this.walker = new ParseTreeWalker(); + } + + public void validate(List trees) { + for (int i = 0; i < trees.size(); i++) { + try { + final YangModelBasicValidationListener yangModelParser = new YangModelBasicValidationListener(); + walker.walk(yangModelParser, trees.get(i)); + } catch (YangValidationException e) { + // wrap exception to add information about which file failed + throw new YangValidationException( + "Yang validation failed for file" + e); + } + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java index de8f7a4256..736efe7efe 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java @@ -189,10 +189,10 @@ public class YangModelParserTest { LeafSchemaNode ifIndex = (LeafSchemaNode) ifEntry .getDataChildByName("ifIndex"); - assertEquals(new Uint32(), ifIndex.getType()); + assertTrue(ifIndex.getType() instanceof Uint32); LeafSchemaNode ifMtu = (LeafSchemaNode) ifEntry .getDataChildByName("ifMtu"); - assertEquals(new Int32(), ifMtu.getType()); + assertTrue(ifMtu.getType() instanceof Int32); } @Test @@ -677,11 +677,4 @@ public class YangModelParserTest { assertNotNull(output.getDataChildByName("data")); } - @Test - public void test() { - Module testModule = TestUtils.findModule(modules, "types4"); - - boolean flag = false; - } - } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_Module.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_Module.java deleted file mode 100644 index 76715e864d..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_Module.java +++ /dev/null @@ -1,315 +0,0 @@ -package org.opendaylight.controller.yang.model.parser.impl; - -import static org.hamcrest.core.Is.*; -import static org.junit.Assert.*; -import static org.junit.matchers.JUnitMatchers.*; -import static org.mockito.Mockito.*; - -import java.util.Date; - -import org.antlr.v4.runtime.tree.ParseTree; -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; - -public class YangModelValidationListenerTest_Module { - - private YangModelValidationListener valid; - private Module_stmtContext ctx; - - @Before - public void setUp() { - valid = new YangModelValidationListener(); - } - - @Test(expected = YangValidationException.class) - public void testRevisionInvalidDateFormat() { - Revision_stmtContext mockedRev = mockModuleWithRevision(2, "badFormat"); - - try { - valid.enterRevision_stmt(mockedRev); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Invalid date format for revision:badFormat in (sub)module:module1, expected date format is:")); - throw e; - } - } - - private Revision_stmtContext mockModuleWithRevision(int moduleChildren, - String date) { - Revision_stmtContext mockedRev = mock(Revision_stmtContext.class); - doReturn(1).when(mockedRev).getChildCount(); - mockName(mockedRev, date); - - Revision_stmtsContext revs = mockRevisionsParent(2, mockedRev); - - mockModuleParent(moduleChildren, revs, "module1"); - return mockedRev; - } - - @Test - public void testRevisionValidDateFormat() { - Revision_stmtContext mockedRev = mockModuleWithRevision(2, - getFormattedDate()); - - valid.enterRevision_stmt(mockedRev); - } - - private String getFormattedDate() { - return YangModelParserListenerImpl.simpleDateFormat.format(new Date()); - } - - @Test(expected = YangValidationException.class) - public void testNoRevision() { - - Module_stmtContext ctx = mock(Module_stmtContext.class); - doReturn(1).when(ctx).getChildCount(); - mockName(ctx, "module1"); - - try { - valid.enterModule_stmt(ctx); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing revision statements in module:module1")); - throw e; - } - } - - @Test(expected = YangValidationException.class) - public void testNoHeaderStmts() { - mockModuleWithRevision(2, "1999-4-5"); - - try { - valid.enterModule_stmt(ctx); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing header statements in module:module1")); - throw e; - } - } - - @Test(expected = YangValidationException.class) - public void testNoNamespace() { - Module_header_stmtsContext header = mock(Module_header_stmtsContext.class); - mockModuleParent(2, header, "module1"); - - try { - valid.enterModule_header_stmts(header); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing namespace statement in module:module1")); - throw e; - } - } - - @Test - public void testPrefixes() { - Prefix_stmtContext pref = mock(Prefix_stmtContext.class); - doReturn(1).when(pref).getChildCount(); - mockName(pref, "unique1"); - mockModuleParent(2, pref, "module1"); - valid.enterPrefix_stmt(pref); - - pref = mock(Prefix_stmtContext.class); - doReturn(1).when(pref).getChildCount(); - mockName(pref, "unique1"); - mockModuleParent(2, pref, "module1"); - - try { - valid.enterPrefix_stmt(pref); - } catch (Exception e) { - return; - } - - fail("Validation Exception should have occured"); - } - - @Test - public void testNamespace() { - Namespace_stmtContext namespace = mock(Namespace_stmtContext.class); - doReturn(1).when(namespace).getChildCount(); - mockName(namespace, "http://test.parsing.uri.com"); - mockModuleParent(2, namespace, "module1"); - valid.enterNamespace_stmt(namespace); - - namespace = mock(Namespace_stmtContext.class); - doReturn(1).when(namespace).getChildCount(); - mockName(namespace, "invalid uri"); - mockModuleParent(2, namespace, "module1"); - try { - valid.enterNamespace_stmt(namespace); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Namespace:invalid uri in module:module1 cannot be parsed as URI")); - return; - } - - fail("Validation Exception should have occured"); - } - - @Test - public void testImports() { - Import_stmtContext impor = mockImport("unique1", "p1"); - mockModuleParent(2, impor, "module1"); - valid.enterImport_stmt(impor); - - impor = mockImport("unique1", "p2"); - mockModuleParent(2, impor, "module1"); - mockName(impor, "unique1"); - - try { - valid.enterImport_stmt(impor); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Module:unique1 imported twice in (sub)module:module1")); - return; - } - - fail("Validation Exception should have occured"); - } - - @Test - public void testIncludes() { - Include_stmtContext impor = mockInclude("unique1"); - mockModuleParent(2, impor, "module1"); - valid.enterInclude_stmt(impor); - - impor = mockInclude("unique1"); - mockModuleParent(2, impor, "module1"); - mockName(impor, "unique1"); - - try { - valid.enterInclude_stmt(impor); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Submodule:unique1 included twice in (sub)module:module1")); - return; - } - - fail("Validation Exception should have occured"); - } - - private Import_stmtContext mockImport(String name, String prefixName) { - Import_stmtContext impor = mock(Import_stmtContext.class); - doReturn(3).when(impor).getChildCount(); - Prefix_stmtContext prefix = mock(Prefix_stmtContext.class); - mockName(prefix, prefixName); - doReturn(prefix).when(impor).getChild(1); - Revision_date_stmtContext revDate = mock(Revision_date_stmtContext.class); - mockName(revDate, getFormattedDate()); - doReturn(revDate).when(impor).getChild(2); - mockName(impor, name); - return impor; - } - - private Include_stmtContext mockInclude(String name) { - Include_stmtContext impor = mock(Include_stmtContext.class); - doReturn(2).when(impor).getChildCount(); - Revision_date_stmtContext revDate = mock(Revision_date_stmtContext.class); - mockName(revDate, getFormattedDate()); - doReturn(revDate).when(impor).getChild(1); - mockName(impor, name); - return impor; - } - - @Test(expected = YangValidationException.class) - public void testInvalidYangVersion() { - - Yang_version_stmtContext yangVersion = mock(Yang_version_stmtContext.class); - doReturn(1).when(yangVersion).getChildCount(); - mockName(yangVersion, "55Unsup"); - - mockModuleParent(2, yangVersion, "module1"); - - try { - valid.enterYang_version_stmt(yangVersion); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Unsupported yang version:55Unsup, in (sub)module:module1, supported version:" - + YangModelValidationListener.SUPPORTED_YANG_VERSION)); - throw e; - } - } - - private void mockModuleParent(int moduleChildren, ParseTree child, - String moduleName) { - ctx = mock(Module_stmtContext.class); - doReturn(moduleChildren).when(ctx).getChildCount(); - mockName(ctx, moduleName); - doReturn(child).when(ctx).getChild(1); - doReturn(ctx).when(child).getParent(); - } - - static Revision_stmtsContext mockRevisionsParent(int moduleChildren, - Revision_stmtContext mockedRev) { - Revision_stmtsContext revs = mock(Revision_stmtsContext.class); - doReturn(moduleChildren).when(revs).getChildCount(); - doReturn(mockedRev).when(revs).getChild(1); - doReturn(revs).when(mockedRev).getParent(); - return revs; - } - - @Test - public void testValidYangVersion() { - - Yang_version_stmtContext ctx = mock(Yang_version_stmtContext.class); - doReturn(1).when(ctx).getChildCount(); - mockName(ctx, "1"); - - valid.enterYang_version_stmt(ctx); - } - - @Test - public void testIdentifierMatching() { - YangModelValidationListener.checkIdentifier("_ok98-.87.-.8...88-asdAD", - null); - YangModelValidationListener.checkIdentifier("AA.bcd", null); - YangModelValidationListener.checkIdentifier("a", null); - - int thrown = 0; - - try { - YangModelValidationListener.checkIdentifier("9aa", null); - } catch (YangValidationException e) { - thrown++; - } - try { - YangModelValidationListener.checkIdentifier("-", null); - } catch (YangValidationException e) { - thrown++; - } - try { - YangModelValidationListener.checkIdentifier(".", null); - } catch (YangValidationException e) { - thrown++; - } - - assertThat(thrown, is(3)); - } - - static void mockName(ParseTree mockedRev, String name) { - StringContext nameCtx = mock(StringContext.class); - ParseTree internalName = mock(ParseTree.class); - doReturn(name).when(internalName).getText(); - doReturn(internalName).when(nameCtx).getChild(0); - doReturn(nameCtx).when(mockedRev).getChild(0); - } -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_SubModule.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_SubModule.java deleted file mode 100644 index 056e869db8..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelValidationListenerTest_SubModule.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.opendaylight.controller.yang.model.parser.impl; - -import static org.junit.Assert.*; -import static org.junit.matchers.JUnitMatchers.*; -import static org.mockito.Mockito.*; - -import org.antlr.v4.runtime.tree.ParseTree; -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext; - -public class YangModelValidationListenerTest_SubModule { - - private YangModelValidationListener valid; - private Submodule_stmtContext ctx; - - @Before - public void setUp() { - valid = new YangModelValidationListener(); - } - - @Test(expected = YangValidationException.class) - public void testNoRevision() { - - Submodule_stmtContext ctx = mock(Submodule_stmtContext.class); - doReturn(1).when(ctx).getChildCount(); - YangModelValidationListenerTest_Module.mockName(ctx, "submodule1"); - - try { - valid.enterSubmodule_stmt(ctx); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing revision statements in submodule:submodule1")); - throw e; - } - } - - @Test(expected = YangValidationException.class) - public void testNoHeaderStmts() { - mockSubmoduleWithRevision(2, "1999-4-5", "submodule"); - - try { - valid.enterSubmodule_stmt(ctx); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing header statements in submodule:submodule")); - throw e; - } - } - - @Test(expected = YangValidationException.class) - public void testNoBelongsTo() { - Submodule_header_stmtsContext header = mock(Submodule_header_stmtsContext.class); - mockSubmoduleParent(2, header, "submodule"); - - try { - valid.enterSubmodule_header_stmts(header); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing belongs-to statement in submodule:submodule")); - throw e; - } - } - - @Test(expected = YangValidationException.class) - public void testBelongsToNoPrefix() { - Belongs_to_stmtContext belongsTo = mock(Belongs_to_stmtContext.class); - doReturn(1).when(belongsTo).getChildCount(); - YangModelValidationListenerTest_Module.mockName(belongsTo, - "supermodule"); - - mockSubmoduleParent(2, belongsTo, "submodule"); - - try { - valid.enterBelongs_to_stmt(belongsTo); - } catch (YangValidationException e) { - assertThat( - e.getMessage(), - containsString("Missing prefix statement in belongs-to:supermodule, in (sub)module:submodule")); - throw e; - } - } - - @Test - public void testBelongsTo() { - Belongs_to_stmtContext belongsTo = mock(Belongs_to_stmtContext.class); - doReturn(2).when(belongsTo).getChildCount(); - YangModelValidationListenerTest_Module.mockName(belongsTo, - "supermodule"); - - Prefix_stmtContext prefix = mock(Prefix_stmtContext.class); - doReturn(prefix).when(belongsTo).getChild(1); - doReturn(belongsTo).when(prefix).getParent(); - - mockSubmoduleParent(2, belongsTo, "submodule"); - valid.enterBelongs_to_stmt(belongsTo); - - } - - private Revision_stmtContext mockSubmoduleWithRevision(int moduleChildren, - String date, String nameOfSubmodule) { - Revision_stmtContext mockedRev = mock(Revision_stmtContext.class); - doReturn(1).when(mockedRev).getChildCount(); - YangModelValidationListenerTest_Module.mockName(mockedRev, date); - - Revision_stmtsContext revs = YangModelValidationListenerTest_Module - .mockRevisionsParent(2, mockedRev); - - mockSubmoduleParent(moduleChildren, revs, nameOfSubmodule); - return mockedRev; - } - - private void mockSubmoduleParent(int moduleChildren, ParseTree child, - String moduleName) { - ctx = mock(Submodule_stmtContext.class); - doReturn(moduleChildren).when(ctx).getChildCount(); - YangModelValidationListenerTest_Module.mockName(ctx, moduleName); - doReturn(child).when(ctx).getChild(1); - doReturn(ctx).when(child).getParent(); - } -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationListTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationListTest.java new file mode 100644 index 0000000000..4e05f48a77 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationListTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import static org.junit.Assert.*; +import static org.junit.matchers.JUnitMatchers.*; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +public class YangModelValidationListTest { + + private YangModelBasicValidationListener valid; + + @Before + public void setUp() { + valid = new YangModelBasicValidationListener(); + } + + @Test(expected = YangValidationException.class) + public void testKeyValidationDuplicates() { + + List_stmtContext list = YangModelValidationTest.mockStatement( + List_stmtContext.class, "list"); + Key_stmtContext key = YangModelValidationTest.mockStatement( + Key_stmtContext.class, "leaf1 leaf2 leaf1 leaf1"); + YangModelValidationTest.addChild(list, key); + + try { + valid.enterKey_stmt(key); + } catch (YangValidationException e) { + assertThat(e.getMessage(), + containsString("contains duplicates:[leaf1]")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testUniqueValidationDuplicates() { + List_stmtContext list = YangModelValidationTest.mockStatement( + List_stmtContext.class, "list"); + Unique_stmtContext unique = YangModelValidationTest.mockStatement( + Unique_stmtContext.class, "leaf1/a leaf2/n leaf1/a leaf1"); + YangModelValidationTest.addChild(list, unique); + + try { + valid.enterUnique_stmt(unique); + } catch (YangValidationException e) { + assertThat(e.getMessage(), + containsString("contains duplicates:[leaf1/a]")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testOrderBy() { + Ordered_by_argContext ctx = YangModelValidationTest.mockStatement( + Ordered_by_argContext.class, "unknown"); + + try { + valid.enterOrdered_by_arg(ctx); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Ordered-by:unknown, illegal value for Ordered-by statement, only permitted:")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testLeaf() { + Leaf_stmtContext ctx = YangModelValidationTest.mockStatement( + Leaf_stmtContext.class, "leaf1"); + Default_stmtContext def = YangModelValidationTest.mockStatement( + Default_stmtContext.class, "default"); + YangModelValidationTest.addChild(ctx, def); + Type_stmtContext typ = YangModelValidationTest.mockStatement( + Type_stmtContext.class, "type"); + YangModelValidationTest.addChild(ctx, def); + YangModelValidationTest.addChild(ctx, typ); + + Mandatory_stmtContext mand = YangModelValidationTest.mockStatement( + Mandatory_stmtContext.class, null); + YangModelValidationTest.addChild(ctx, mand); + + try { + valid.enterLeaf_stmt(ctx); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Both Mandatory and Default statement present")); + throw e; + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationModuleTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationModuleTest.java new file mode 100644 index 0000000000..2bdd3e5074 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationModuleTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import static org.junit.Assert.*; +import static org.junit.matchers.JUnitMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +public class YangModelValidationModuleTest { + + private YangModelBasicValidationListener valid; + + @Before + public void setUp() { + valid = new YangModelBasicValidationListener(); + } + + @Test(expected = YangValidationException.class) + public void testRevisionInvalidDateFormat() { + Revision_stmtContext mockedRev = mockModuleWithRevision("badFormat", + "module1"); + + try { + valid.enterRevision_stmt(mockedRev); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Revision:badFormat, invalid date format expected date format is:")); + throw e; + } + } + + @Test + public void testRevisionValidDateFormat() { + Revision_stmtContext mockedRev = mockModuleWithRevision( + YangModelValidationTest.getFormattedDate(), "module1"); + + valid.enterRevision_stmt(mockedRev); + } + + @Test(expected = YangValidationException.class) + public void testNoHeaderStmts() { + Revision_stmtContext rev = mockModuleWithRevision("1999-4-5", "module1"); + + try { + valid.enterModule_stmt((Module_stmtContext) rev.getParent() + .getParent()); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Module-header statement in Module:module1")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testMultipleModulesPerSession() { + Module_stmtContext module1 = (Module_stmtContext) mockModuleWithRevision( + "1999-09-10", "m1").getParent().getParent(); + YangModelValidationTest.addChild(module1, YangModelValidationTest + .mockStatement(Namespace_stmtContext.class, "")); + + Module_stmtContext module2 = (Module_stmtContext) mockModuleWithRevision( + "1999-09-10", "m2").getParent().getParent(); + YangModelValidationTest.addChild(module1, YangModelValidationTest + .mockStatement(Namespace_stmtContext.class, "")); + valid.enterModule_stmt(module1); + + try { + valid.enterModule_stmt(module2); + } catch (YangValidationException e) { + assertThat(e.getMessage(), + containsString("Multiple (sub)modules per file")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testNoNamespace() { + Module_header_stmtsContext header = YangModelValidationTest + .mockStatement(Module_header_stmtsContext.class, null); + Module_stmtContext mod = YangModelValidationTest.mockStatement( + Module_stmtContext.class, "module1"); + YangModelValidationTest.addChild(mod, header); + + try { + valid.enterModule_header_stmts(header); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Namespace statement in Module-header:")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testNoPrefix() { + Module_header_stmtsContext header = YangModelValidationTest + .mockStatement(Module_header_stmtsContext.class, null); + Namespace_stmtContext nmspc = YangModelValidationTest.mockStatement( + Namespace_stmtContext.class, "http://test"); + Module_stmtContext mod = YangModelValidationTest.mockStatement( + Module_stmtContext.class, "module1"); + YangModelValidationTest.addChild(mod, header); + YangModelValidationTest.addChild(header, nmspc); + + try { + valid.enterModule_header_stmts(header); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Prefix statement in Module-header:")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testInvalidYangVersion() { + + Yang_version_stmtContext yangVersion = YangModelValidationTest + .mockStatement(Yang_version_stmtContext.class, "55Unsup"); + + Module_stmtContext mod = YangModelValidationTest.mockStatement( + Module_stmtContext.class, "module1"); + YangModelValidationTest.addChild(mod, yangVersion); + + try { + valid.enterYang_version_stmt(yangVersion); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Unsupported yang version:55Unsup, supported version:" + + BasicValidations.SUPPORTED_YANG_VERSION)); + throw e; + } + } + + @Test + public void testValidYangVersion() { + + Yang_version_stmtContext ctx = mock(Yang_version_stmtContext.class); + doReturn(1).when(ctx).getChildCount(); + YangModelValidationTest.mockName(ctx, "1"); + + valid.enterYang_version_stmt(ctx); + } + + private static Revision_stmtContext mockModuleWithRevision(String date, + String moduleName) { + Revision_stmtContext mockedRev = YangModelValidationTest.mockStatement( + Revision_stmtContext.class, date); + Revision_stmtsContext revs = YangModelValidationTest.mockStatement( + Revision_stmtsContext.class, null); + Module_stmtContext mod = YangModelValidationTest.mockStatement( + Module_stmtContext.class, moduleName); + + YangModelValidationTest.addChild(revs, mockedRev); + YangModelValidationTest.addChild(mod, revs); + return mockedRev; + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationSubModuleTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationSubModuleTest.java new file mode 100644 index 0000000000..fe4f0a2452 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationSubModuleTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import static org.junit.Assert.*; +import static org.junit.matchers.JUnitMatchers.*; +import static org.mockito.Mockito.*; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +public class YangModelValidationSubModuleTest { + + private YangModelBasicValidationListener valid; + + @Before + public void setUp() { + valid = new YangModelBasicValidationListener(); + } + + @Test(expected = YangValidationException.class) + public void testNoRevision() { + + Submodule_stmtContext ctx = YangModelValidationTest.mockStatement( + Submodule_stmtContext.class, "submodule1"); + + try { + valid.enterSubmodule_stmt(ctx); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Submodule-header statement in Submodule:submodule")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testNoBelongsTo() { + Submodule_header_stmtsContext header = mock(Submodule_header_stmtsContext.class); + mockSubmoduleParent(header, "submodule"); + + try { + valid.enterSubmodule_header_stmts(header); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Belongs-to statement in Submodule-header:")); + throw e; + } + } + + @Test(expected = YangValidationException.class) + public void testBelongsToNoPrefix() { + Belongs_to_stmtContext belongsTo = YangModelValidationTest + .mockStatement(Belongs_to_stmtContext.class, "supermodule"); + + mockSubmoduleParent(belongsTo, "submodule"); + + try { + valid.enterBelongs_to_stmt(belongsTo); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Missing Prefix statement in Belongs-to:supermodule")); + throw e; + } + } + + private Submodule_stmtContext mockSubmoduleParent(ParseTree child, + String moduleName) { + Submodule_stmtContext ctx = YangModelValidationTest.mockStatement( + Submodule_stmtContext.class, moduleName); + YangModelValidationTest.addChild(ctx, child); + return ctx; + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationTest.java new file mode 100644 index 0000000000..ffcadf6397 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/validator/YangModelValidationTest.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2013 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.yang.model.validator; + +import static org.hamcrest.core.Is.*; +import static org.junit.Assert.*; +import static org.junit.matchers.JUnitMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; +import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl; +import org.opendaylight.controller.yang.model.parser.util.YangValidationException; + +import com.google.common.collect.Sets; + +public class YangModelValidationTest { + + private YangModelBasicValidationListener valid; + + @Before + public void setUp() { + + valid = new YangModelBasicValidationListener(); + } + + @Test + public void testPrefixes() { + Prefix_stmtContext pref = mockStatement(Prefix_stmtContext.class, + "unique1"); + Module_stmtContext module = mockStatement(Module_stmtContext.class, + "module1"); + addChild(module, pref); + + valid.enterPrefix_stmt(pref); + + pref = mockStatement(Prefix_stmtContext.class, "unique1"); + module = mockStatement(Module_stmtContext.class, "module1"); + addChild(module, pref); + + try { + valid.enterPrefix_stmt(pref); + } catch (Exception e) { + return; + } + + fail("Validation Exception should have occured"); + } + + @Test + public void testNamespace() { + + Namespace_stmtContext namespace = mockStatement( + Namespace_stmtContext.class, "http://test.parsing.uri.com"); + Module_stmtContext module = mockStatement(Module_stmtContext.class, + "module1"); + addChild(module, namespace); + + valid.enterNamespace_stmt(namespace); + + namespace = mockStatement(Namespace_stmtContext.class, "invalid uri"); + module = mockStatement(Module_stmtContext.class, "module1"); + addChild(module, namespace); + + try { + valid.enterNamespace_stmt(namespace); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Namespace:invalid uri cannot be parsed as URI")); + return; + } + + fail("Validation Exception should have occured"); + } + + @Test + public void testImports() { + Import_stmtContext impor = mockImport("unique1", "p1"); + Module_stmtContext mod = mockStatement(Module_stmtContext.class, + "module1"); + addChild(mod, impor); + + valid.enterImport_stmt(impor); + + impor = mockImport("unique1", "p2"); + mod = mockStatement(Module_stmtContext.class, "module1"); + addChild(mod, impor); + + try { + valid.enterImport_stmt(impor); + } catch (YangValidationException e) { + assertThat(e.getMessage(), + containsString("Import:unique1 not unique")); + return; + } + + fail("Validation Exception should have occured"); + } + + @Test + public void testIncludes() { + Include_stmtContext incl = mockInclude("unique1"); + Module_stmtContext mod = mockStatement(Module_stmtContext.class, + "module1"); + addChild(mod, incl); + valid.enterInclude_stmt(incl); + + incl = mockInclude("unique1"); + mod = mockStatement(Module_stmtContext.class, "module1"); + addChild(mod, incl); + + try { + valid.enterInclude_stmt(incl); + } catch (YangValidationException e) { + assertThat(e.getMessage(), + containsString("Include:unique1 not unique in (sub)module")); + return; + } + + fail("Validation Exception should have occured"); + } + + @Test + public void testIdentifierMatching() { + List ids = new ArrayList(); + // valid + ids.add("_ok98-.87.-.8...88-asdAD"); + ids.add("AA.bcd"); + ids.add("a"); + // invalid + ids.add("9aa"); + ids.add("-"); + ids.add("."); + + int thrown = 0; + for (String id : ids) { + try { + BasicValidations.checkIdentifierInternal( + mock(Module_stmtContext.class), id); + } catch (YangValidationException e) { + thrown++; + } + } + + assertThat(thrown, is(3)); + } + + @Test(expected = YangValidationException.class) + public void testAugument() { + Augment_stmtContext augument = mockStatement(Augment_stmtContext.class, + "/a:*abc/a:augument1"); + Module_stmtContext mod1 = mockStatement(Module_stmtContext.class, + "mod1"); + addChild(mod1, augument); + + try { + valid.enterAugment_stmt(augument); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("Schema node id:/a:*abc/a:augument1 not in required format, details:Prefixed id:a:*abc not in required format")); + throw e; + } + } + + @Test + public void testDeviate() { + Deviation_stmtContext ctx = mockStatement(Deviation_stmtContext.class, + "deviations"); + Deviate_add_stmtContext add = mockStatement( + Deviate_add_stmtContext.class, "add"); + Deviate_delete_stmtContext del = mockStatement( + Deviate_delete_stmtContext.class, "delete"); + + addChild(ctx, add); + addChild(ctx, del); + + valid.enterDeviation_stmt(ctx); + + HashSet> types = Sets.newHashSet(); + types.add(Deviate_add_stmtContext.class); + types.add(Deviate_delete_stmtContext.class); + + int count = ValidationUtil.countPresentChildrenOfType(ctx, types); + assertThat(count, is(2)); + } + + @Test(expected = YangValidationException.class) + public void testStatus() throws Exception { + Status_argContext status = mockStatement(Status_argContext.class, + "unknown"); + try { + valid.enterStatus_arg(status); + } catch (YangValidationException e) { + assertThat( + e.getMessage(), + containsString("illegal value for Status statement, only permitted:")); + throw e; + } + } + + private Import_stmtContext mockImport(String name, String prefixName) { + Import_stmtContext impor = mockStatement(Import_stmtContext.class, name); + + Prefix_stmtContext prefix = mockStatement(Prefix_stmtContext.class, + prefixName); + Revision_date_stmtContext revDate = mockStatement( + Revision_date_stmtContext.class, getFormattedDate()); + + addChild(impor, prefix); + addChild(impor, revDate); + return impor; + } + + static String getFormattedDate() { + return YangModelParserListenerImpl.simpleDateFormat.format(new Date()); + } + + private Include_stmtContext mockInclude(String name) { + Include_stmtContext incl = mockStatement(Include_stmtContext.class, + name); + + Revision_date_stmtContext revDate = mockStatement( + Revision_date_stmtContext.class, getFormattedDate()); + + addChild(incl, revDate); + return incl; + } + + static void mockName(ParseTree stmt, String name) { + StringContext nameCtx = mock(StringContext.class); + ParseTree internalName = mock(ParseTree.class); + doReturn(1).when(stmt).getChildCount(); + doReturn(name).when(internalName).getText(); + doReturn(internalName).when(nameCtx).getChild(0); + doReturn(nameCtx).when(stmt).getChild(0); + } + + static T mockStatement(Class stmtType, String name) { + T stmt = stmtType.cast(mock(stmtType)); + + doReturn(0).when(stmt).getChildCount(); + + if (name != null) + mockName(stmt, name); + return stmt; + } + + static void addChild(ParseTree parent, ParseTree child) { + int childCount = parent.getChildCount() + 1; + doReturn(childCount).when(parent).getChildCount(); + doReturn(child).when(parent).getChild(childCount - 1); + doReturn(parent).when(child).getParent(); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractSignedInteger.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractSignedInteger.java index 366df63971..3907cc13e5 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractSignedInteger.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractSignedInteger.java @@ -7,8 +7,10 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -23,7 +25,7 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; * interface which represents SIGNED Integer values defined in Yang language.
* The integer built-in types in Yang are int8, int16, int32, int64. They * represent signed integers of different sizes: - * + * *
    *
  • int8 - represents integer values between -128 and 127, inclusively.
  • *
  • int16 - represents integer values between -32768 and 32767, inclusively.
  • @@ -32,7 +34,7 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; *
  • int64 - represents integer values between -9223372036854775808 and * 9223372036854775807, inclusively.
  • *
- * + * */ public abstract class AbstractSignedInteger implements IntegerTypeDefinition { @@ -51,17 +53,20 @@ public abstract class AbstractSignedInteger implements IntegerTypeDefinition { * @param maxRange * @param units */ - public AbstractSignedInteger(final QName name, final String description, - final Number minRange, final Number maxRange, final String units) { + public AbstractSignedInteger(final List actualPath, + final URI namespace, final Date revision, final QName name, + final String description, final Number minRange, + final Number maxRange, final String units) { this.name = name; this.description = description; - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); this.units = units; this.rangeStatements = new ArrayList(); final String rangeDescription = "Integer values between " + minRange + " and " + maxRange + ", inclusively."; this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange, - maxRange, rangeDescription, "https://tools.ietf.org/html/rfc6020#section-9.2.4")); + maxRange, rangeDescription, + "https://tools.ietf.org/html/rfc6020#section-9.2.4")); } /** @@ -70,11 +75,13 @@ public abstract class AbstractSignedInteger implements IntegerTypeDefinition { * @param rangeStatements * @param units */ - public AbstractSignedInteger(final QName name, final String description, + public AbstractSignedInteger(final List actualPath, + final URI namespace, final Date revision, final QName name, + final String description, final List rangeStatements, final String units) { this.name = name; this.description = description; - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); this.units = units; this.rangeStatements = rangeStatements; } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractUnsignedInteger.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractUnsignedInteger.java index c444ce9fdd..76048519e7 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractUnsignedInteger.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/AbstractUnsignedInteger.java @@ -1,10 +1,12 @@ /** - * + * */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -17,16 +19,16 @@ import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefini /** * The Abstract Integer class defines implementation of IntegerTypeDefinition * interface which represents UNSIGNED Integer values defined in Yang language.
- * The integer built-in types in Yang are uint8, uint16, uint32, and uint64. They - * represent unsigned integers of different sizes: - * + * The integer built-in types in Yang are uint8, uint16, uint32, and uint64. + * They represent unsigned integers of different sizes: + * *
    *
  • uint8 - represents integer values between 0 and 255, inclusively.
  • *
  • uint16 - represents integer values between 0 and 65535, inclusively.
  • - *
  • uint32 - represents integer values between 0 and 4294967295, - inclusively.
  • + *
  • uint32 - represents integer values between 0 and 4294967295, inclusively. + *
  • *
  • uint64 - represents integer values between 0 and 18446744073709551615, - inclusively.
  • + * inclusively. *
* */ @@ -39,7 +41,7 @@ public abstract class AbstractUnsignedInteger implements private final String units; private final List rangeStatements; - + /** * @param name * @param description @@ -47,17 +49,20 @@ public abstract class AbstractUnsignedInteger implements * @param maxRange * @param units */ - public AbstractUnsignedInteger(final QName name, final String description, - final Number minRange, final Number maxRange, final String units) { + public AbstractUnsignedInteger(final List actualPath, + final URI namespace, final Date revision, final QName name, + final String description, final Number minRange, + final Number maxRange, final String units) { this.name = name; this.description = description; - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); this.units = units; this.rangeStatements = new ArrayList(); final String rangeDescription = "Integer values between " + minRange + " and " + maxRange + ", inclusively."; this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange, - maxRange, rangeDescription, "https://tools.ietf.org/html/rfc6020#section-9.2.4")); + maxRange, rangeDescription, + "https://tools.ietf.org/html/rfc6020#section-9.2.4")); } /** @@ -66,15 +71,17 @@ public abstract class AbstractUnsignedInteger implements * @param rangeStatements * @param units */ - public AbstractUnsignedInteger(final QName name, final String description, + public AbstractUnsignedInteger(final List actualPath, + final URI namespace, final Date revision, final QName name, + final String description, final List rangeStatements, final String units) { this.name = name; this.description = description; - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); this.units = units; this.rangeStatements = rangeStatements; } - + @Override public String getUnits() { return units; diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Decimal64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Decimal64.java index a1073c60cf..158865aec9 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Decimal64.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Decimal64.java @@ -8,8 +8,10 @@ package org.opendaylight.controller.yang.model.util; import java.math.BigDecimal; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -21,8 +23,8 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; /** * The default implementation of Decimal Type Definition interface. - * - * + * + * * @see DecimalTypeDefinition */ public class Decimal64 implements DecimalTypeDefinition { @@ -52,14 +54,15 @@ public class Decimal64 implements DecimalTypeDefinition { * inclusively as defined interface {@link DecimalTypeDefinition}
* If the fraction digits are not defined inner the definition boundaries * the constructor will throw {@link IllegalArgumentException} - * + * * @param fractionDigits * integer between 1 and 18 inclusively - * + * * @see DecimalTypeDefinition * @exception IllegalArgumentException */ - public Decimal64(final Integer fractionDigits) { + public Decimal64(final List actualPath, final URI namespace, + final Date revision, final Integer fractionDigits) { super(); if (!((fractionDigits.intValue() > 1) && (fractionDigits.intValue() <= 18))) { throw new IllegalArgumentException( @@ -67,12 +70,12 @@ public class Decimal64 implements DecimalTypeDefinition { } this.fractionDigits = fractionDigits; rangeStatements = defaultRangeStatements(); - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); } /** * Decimal64 Type Constructor.
- * + * * If parameter Range Statements is null or * defined as empty List the constructor automatically assigns * the boundaries as min and max value defined for Decimal64 in * If the fraction digits are not defined inner the definition boundaries * the constructor will throw {@link IllegalArgumentException} - * + * * @param rangeStatements * Range Constraint Statements * @param fractionDigits * integer between 1 and 18 inclusively * @exception IllegalArgumentException */ - public Decimal64(final List rangeStatements, + public Decimal64(final List actualPath, final URI namespace, + final Date revision, final List rangeStatements, Integer fractionDigits) { super(); if (!((fractionDigits.intValue() > 1) && (fractionDigits.intValue() <= 18))) { @@ -103,7 +107,7 @@ public class Decimal64 implements DecimalTypeDefinition { this.rangeStatements = Collections.unmodifiableList(rangeStatements); } this.fractionDigits = fractionDigits; - this.path = BaseTypes.schemaPath(name); + this.path = BaseTypes.schemaPath(actualPath, namespace, revision); } /** @@ -118,7 +122,7 @@ public class Decimal64 implements DecimalTypeDefinition { * inclusively as defined interface {@link DecimalTypeDefinition}
* If the fraction digits are not defined inner the definition boundaries * the constructor will throw {@link IllegalArgumentException} - * + * * @param units * units associated with the type * @param defaultValue @@ -127,10 +131,11 @@ public class Decimal64 implements DecimalTypeDefinition { * Range Constraint Statements * @param fractionDigits * integer between 1 and 18 inclusively - * + * * @exception IllegalArgumentException */ - public Decimal64(final String units, final BigDecimal defaultValue, + public Decimal64(final List actualPath, final URI namespace, + final Date revision, final String units, final BigDecimal defaultValue, final List rangeStatements, final Integer fractionDigits) { super(); @@ -141,7 +146,7 @@ public class Decimal64 implements DecimalTypeDefinition { if (rangeStatements == null || rangeStatements.isEmpty()) { this.rangeStatements = defaultRangeStatements(); - + } else { this.rangeStatements = Collections.unmodifiableList(rangeStatements); } @@ -153,7 +158,7 @@ public class Decimal64 implements DecimalTypeDefinition { /** * Returns unmodifiable List with default definition of Range Statements. - * + * * @return unmodifiable List with default definition of Range Statements. */ private List defaultRangeStatements() { diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int16.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int16.java index 40857d1c32..750dff5c7a 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int16.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int16.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -17,23 +19,25 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; * Implementation of Yang int16 built-in type.
* int16 represents integer values between -32768 and 32767, inclusively. The * Java counterpart of Yang int16 built-in type is {@link Short}. - * + * * @see AbstractSignedInteger */ public class Int16 extends AbstractSignedInteger { private static final QName name = BaseTypes.constructQName("int16"); private Short defaultValue = null; - private static final String description = + private static final String description = "int16 represents integer values between -32768 and 32767, inclusively."; - public Int16() { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Int16(final List actualPath, final URI namespace, + final Date revision) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); } - public Int16(final List rangeStatements, + public Int16(final List actualPath, final URI namespace, + final Date revision, final List rangeStatements, final String units, final Short defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int32.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int32.java index 06e1948d68..da356309a5 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int32.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int32.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -18,35 +20,38 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; * int32 represents integer values between -2147483648 and 2147483647, * inclusively. The Java counterpart of Yang int32 built-in type is * {@link Integer}. - * + * * @see AbstractSignedInteger - * + * */ public class Int32 extends AbstractSignedInteger { private static final QName name = BaseTypes.constructQName("int32"); private Integer defaultValue = null; - private static final String description = + private static final String description = "int32 represents integer values between -2147483648 and 2147483647, inclusively."; - public Int32() { - super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); + public Int32(final List actualPath, final URI namespace, + final Date revision) { + super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); } - public Int32(final Integer defaultValue) { - super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); + public Int32(final List actualPath, final URI namespace, + final Date revision, final Integer defaultValue) { + super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Int32(final List rangeStatements, + public Int32(final List actualPath, final URI namespace, + final Date revision, final List rangeStatements, final String units, final Integer defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @@ -57,7 +62,7 @@ public class Int32 extends AbstractSignedInteger { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue * () diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int64.java index f858539dc3..4b05bc59e7 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int64.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int64.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -15,7 +17,7 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; /** * Implementation of Yang int64 built-in type.
- * int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively. + * int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively. * The Java counterpart of Yang int64 built-in type is * {@link Long}. * @@ -24,27 +26,30 @@ public class Int64 extends AbstractSignedInteger { private static final QName name = BaseTypes.constructQName("int64"); private Long defaultValue = null; - private static final String description = + private static final String description = "int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively."; - public Int64() { - super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); + public Int64(final List actualPath, final URI namespace, + final Date revision) { + super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); } - public Int64(final Long defaultValue) { - super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); + public Int64(final List actualPath, final URI namespace, + final Date revision, final Long defaultValue) { + super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Int64(final List rangeStatements, + public Int64(final List actualPath, final URI namespace, + final Date revision, final List rangeStatements, final String units, final Long defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @Override @@ -54,7 +59,7 @@ public class Int64 extends AbstractSignedInteger { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() */ @Override diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int8.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int8.java index a263fd1909..6a917b252f 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int8.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Int8.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -16,36 +18,39 @@ import org.opendaylight.controller.yang.model.api.type.RangeConstraint; /** * Implementation of Yang int8 built-in type. *
- * int8 represents integer values between -128 and 127, inclusively. The Java counterpart of + * int8 represents integer values between -128 and 127, inclusively. The Java counterpart of * Yang int8 built-in type is {@link Byte}. - * + * * @see AbstractSignedInteger */ public class Int8 extends AbstractSignedInteger { private static final QName name = BaseTypes.constructQName("int8"); private Byte defaultValue = null; - private static final String description = + private static final String description = "represents integer values between -128 and 127, inclusively."; - - public Int8() { - super(name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, ""); + + public Int8(final List actualPath, final URI namespace, + final Date revision) { + super(actualPath, namespace, revision, name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, ""); } - public Int8(final Byte defaultValue) { - super(name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, ""); + public Int8(final List actualPath, final URI namespace, + final Date revision, final Byte defaultValue) { + super(actualPath, namespace, revision, name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Int8(final List rangeStatements, + public Int8(final List actualPath, final URI namespace, + final Date revision, final List rangeStatements, final String units, final Byte defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @Override @@ -55,7 +60,7 @@ public class Int8 extends AbstractSignedInteger { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() */ @Override diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/StringType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/StringType.java index c676d7479a..f58075bf30 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/StringType.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/StringType.java @@ -7,8 +7,10 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -38,9 +40,10 @@ public class StringType implements StringTypeDefinition { /** * Default Constructor. */ - public StringType() { + public StringType(final List actualPath, + final URI namespace, final Date revision) { super(); - path = BaseTypes.schemaPath(name); + path = BaseTypes.schemaPath(actualPath, namespace, revision); final List constraints = new ArrayList(); constraints.add(BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", "")); lengthStatements = Collections.unmodifiableList(constraints); @@ -54,10 +57,11 @@ public class StringType implements StringTypeDefinition { * @param lengthStatements * @param patterns */ - public StringType(final List lengthStatements, + public StringType(final List actualPath, + final URI namespace, final Date revision, final List lengthStatements, final List patterns) { super(); - path = BaseTypes.schemaPath(name); + path = BaseTypes.schemaPath(actualPath, namespace, revision); if(lengthStatements == null || lengthStatements.size() == 0) { final List constraints = new ArrayList(); constraints.add(BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", "")); @@ -76,11 +80,12 @@ public class StringType implements StringTypeDefinition { * @param patterns * @param units */ - public StringType(final String defaultValue, + public StringType(final List actualPath, + final URI namespace, final Date revision, final String defaultValue, final List lengthStatements, final List patterns, final String units) { super(); - path = BaseTypes.schemaPath(name); + path = BaseTypes.schemaPath(actualPath, namespace, revision); this.defaultValue = defaultValue; if(lengthStatements == null || lengthStatements.size() == 0) { final List constraints = new ArrayList(); diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint16.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint16.java index f58c765886..9db4ea9df8 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint16.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint16.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -17,7 +19,7 @@ import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefini * Implementation of Yang uint32 built-in type.
* uint16 represents integer values between 0 and 65535, inclusively. The Java * counterpart of Yang uint32 built-in type is {@link Integer}. - * + * */ public class Uint16 extends AbstractUnsignedInteger { @@ -25,24 +27,27 @@ public class Uint16 extends AbstractUnsignedInteger { private Integer defaultValue = null; private static final String description = "uint16 represents integer values between 0 and 65535, inclusively."; - public Uint16() { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint16(final List actualPath, + final URI namespace, final Date revision) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); } - public Uint16(final Integer defaultValue) { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint16(final List actualPath, + final URI namespace, final Date revision, final Integer defaultValue) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Uint16(final List rangeStatements, + public Uint16(final List actualPath, + final URI namespace, final Date revision, final List rangeStatements, final String units, final Integer defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @@ -53,7 +58,7 @@ public class Uint16 extends AbstractUnsignedInteger { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue * () diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint32.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint32.java index ba2e4ea8d9..75f9b49693 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint32.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint32.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -17,7 +19,7 @@ import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefini * Implementation of Yang uint32 built-in type.
* uint32 represents integer values between 0 and 4294967295, inclusively. The * Java counterpart of Yang uint32 built-in type is {@link Long}. - * + * */ public class Uint32 extends AbstractUnsignedInteger { @@ -25,24 +27,27 @@ public class Uint32 extends AbstractUnsignedInteger { private Long defaultValue = null; private static final String description = "uint32 represents integer values between 0 and 4294967295, inclusively."; - public Uint32() { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint32(final List actualPath, + final URI namespace, final Date revision) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); } - public Uint32(final Long defaultValue) { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint32(final List actualPath, + final URI namespace, final Date revision, final Long defaultValue) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Uint32(final List rangeStatements, + public Uint32(final List actualPath, + final URI namespace, final Date revision, final List rangeStatements, final String units, final Long defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @@ -53,7 +58,7 @@ public class Uint32 extends AbstractUnsignedInteger { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue * () diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint64.java index c247c2a4da..05ea8c9e09 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint64.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint64.java @@ -8,6 +8,8 @@ package org.opendaylight.controller.yang.model.util; import java.math.BigInteger; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -29,18 +31,21 @@ public class Uint64 extends AbstractUnsignedInteger { private static final String description = "uint64 represents integer values between 0 and 18446744073709551615, inclusively."; - public Uint64() { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint64(final List actualPath, + final URI namespace, final Date revision) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); } - public Uint64(final BigInteger defaultValue) { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint64(final List actualPath, + final URI namespace, final Date revision, final BigInteger defaultValue) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Uint64(final List rangeStatements, + public Uint64(final List actualPath, + final URI namespace, final Date revision, final List rangeStatements, final String units, final BigInteger defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint8.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint8.java index 57126a34de..aa1e6cacfb 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint8.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Uint8.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.List; import org.opendaylight.controller.yang.common.QName; @@ -16,36 +18,39 @@ import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefini /** * Implementation of Yang uint8 built-in type. *
- * uint8 represents integer values between 0 and 255, inclusively. The Java counterpart of + * uint8 represents integer values between 0 and 255, inclusively. The Java counterpart of * Yang uint8 built-in type is {@link Short}. - * + * * @see AbstractUnsignedInteger */ public class Uint8 extends AbstractUnsignedInteger { private static final QName name = BaseTypes.constructQName("uint8"); private Short defaultValue = null; - private static final String description = + private static final String description = "uint8 represents integer values between 0 and 255, inclusively."; - public Uint8() { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint8(final List actualPath, + final URI namespace, final Date revision) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); } - public Uint8(final Short defaultValue) { - super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); + public Uint8(final List actualPath, + final URI namespace, final Date revision, final Short defaultValue) { + super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, ""); this.defaultValue = defaultValue; } - public Uint8(final List rangeStatements, + public Uint8(final List actualPath, + final URI namespace, final Date revision, final List rangeStatements, final String units, final Short defaultValue) { - super(name, description, rangeStatements, units); + super(actualPath, namespace, revision, name, description, rangeStatements, units); this.defaultValue = defaultValue; } /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @Override @@ -55,7 +60,7 @@ public class Uint8 extends AbstractUnsignedInteger { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() */ @Override diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/YangTypesConverter.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/YangTypesConverter.java index f04ba66256..f3db85cf9a 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/YangTypesConverter.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/YangTypesConverter.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -18,13 +20,8 @@ import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.controller.yang.model.api.type.BooleanTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; import org.opendaylight.controller.yang.model.api.type.EmptyTypeDefinition; import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.RangeConstraint; -import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition; public class YangTypesConverter { @@ -35,16 +32,8 @@ public class YangTypesConverter { private static final TypeDefinition BITS = new BitsType(); private static final TypeDefinition BOOLEAN_TYPE = new BooleanType(); private static final TypeDefinition EMPTY_TYPE = new EmptyType(); - private static final TypeDefinition INST_ID_TYPE = new InstanceIdentifier(null, true); - private static final TypeDefinition INT8_TYPE = new Int8(); - private static final TypeDefinition INT16_TYPE = new Int16(); - private static final TypeDefinition INT32_TYPE = new Int32(); - private static final TypeDefinition INT64_TYPE = new Int64(); - private static final TypeDefinition STRING_TYPE = new StringType(); - private static final TypeDefinition UINT8_TYPE = new Uint8(); - private static final TypeDefinition UINT16_TYPE = new Uint16(); - private static final TypeDefinition UINT32_TYPE = new Uint32(); - private static final TypeDefinition UINT64_TYPE = new Uint64(); + private static final TypeDefinition INST_ID_TYPE = new InstanceIdentifier( + null, true); static { baseYangTypeMap.put("binary", BINARY); @@ -52,15 +41,6 @@ public class YangTypesConverter { baseYangTypeMap.put("boolean", BOOLEAN_TYPE); baseYangTypeMap.put("empty", EMPTY_TYPE); baseYangTypeMap.put("instance-identifier", INST_ID_TYPE); - baseYangTypeMap.put("int8", INT8_TYPE); - baseYangTypeMap.put("int16", INT16_TYPE); - baseYangTypeMap.put("int32", INT32_TYPE); - baseYangTypeMap.put("int64", INT64_TYPE); - baseYangTypeMap.put("string", STRING_TYPE); - baseYangTypeMap.put("uint8", UINT8_TYPE); - baseYangTypeMap.put("uint16", UINT16_TYPE); - baseYangTypeMap.put("uint32", UINT32_TYPE); - baseYangTypeMap.put("uint64", UINT64_TYPE); baseYangTypes.add("binary"); baseYangTypes.add("bits"); @@ -92,42 +72,36 @@ public class YangTypesConverter { return type; } - public static TypeDefinition javaTypeForBaseYangType(String typeName) { - TypeDefinition type = baseYangTypeMap.get(typeName); - return type; - } + public static TypeDefinition javaTypeForBaseYangType( + List actualPath, URI namespace, Date revision, + String typeName) { - public static TypeDefinition javaTypeForBaseYangSignedIntegerType( - String typeName, List ranges) { - if (typeName.equals("int8")) { - return new Int8(ranges, null, null); - } else if (typeName.equals("int16")) { - return new Int16(ranges, null, null); - } else if (typeName.equals("int32")) { - return new Int32(ranges, null, null); - } else if (typeName.equals("int64")) { - return new Int64(ranges, null, null); + if (typeName.startsWith("int")) { + if (typeName.equals("int8")) { + return new Int8(actualPath, namespace, revision); + } else if (typeName.equals("int16")) { + return new Int16(actualPath, namespace, revision); + } else if (typeName.equals("int32")) { + return new Int32(actualPath, namespace, revision); + } else if (typeName.equals("int64")) { + return new Int64(actualPath, namespace, revision); + } + } else if (typeName.startsWith("uint")) { + if (typeName.equals("uint8")) { + return new Uint8(actualPath, namespace, revision); + } else if (typeName.equals("uint16")) { + return new Uint16(actualPath, namespace, revision); + } else if (typeName.equals("uint32")) { + return new Uint32(actualPath, namespace, revision); + } else if (typeName.equals("uint64")) { + return new Uint64(actualPath, namespace, revision); + } + } else if (typeName.equals("string")) { + return new StringType(actualPath, namespace, revision); } - return null; - } - public static TypeDefinition javaTypeForBaseYangUnsignedIntegerType( - final String typeName, List ranges) { - if (typeName.equals("uint8")) { - return new Uint8(ranges, null, null); - } else if (typeName.equals("uint16")) { - return new Uint16(ranges, null, null); - } else if (typeName.equals("uint32")) { - return new Uint32(ranges, null, null); - } else if (typeName.equals("uint64")) { - return new Uint64(ranges, null, null); - } - return null; - } - - public static TypeDefinition javaTypeForBaseYangDecimal64Type( - List rangeStatements, int fractionDigits) { - return new Decimal64(rangeStatements, fractionDigits); + TypeDefinition type = baseYangTypeMap.get(typeName); + return type; } -} +} diff --git a/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java.rej b/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java.rej deleted file mode 100644 index 7b03d3434e..0000000000 --- a/opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java.rej +++ /dev/null @@ -1,85 +0,0 @@ -*************** -*** 29,35 **** - import org.opendaylight.controller.switchmanager.SwitchConfig; - import org.opendaylight.controller.usermanager.IUserManager; - import org.opendaylight.controller.web.IOneWeb; -- import org.springframework.security.core.context.SecurityContextHolder; - import org.springframework.stereotype.Controller; - import org.springframework.web.bind.annotation.PathVariable; - import org.springframework.web.bind.annotation.RequestMapping; ---- 31,36 ---- - import org.opendaylight.controller.switchmanager.SwitchConfig; - import org.opendaylight.controller.usermanager.IUserManager; - import org.opendaylight.controller.web.IOneWeb; - import org.springframework.stereotype.Controller; - import org.springframework.web.bind.annotation.PathVariable; - import org.springframework.web.bind.annotation.RequestMapping; -*************** -*** 182,189 **** - @RequestMapping(value = "/flow", method = RequestMethod.POST) - @ResponseBody - public String actionFlow(@RequestParam(required = true) String action, -- @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId) { -- if (!authorize(UserLevel.NETWORKADMIN)) { - return "Operation not authorized"; - } - ---- 183,190 ---- - @RequestMapping(value = "/flow", method = RequestMethod.POST) - @ResponseBody - public String actionFlow(@RequestParam(required = true) String action, -+ @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId, HttpServletRequest request) { -+ if (!authorize(UserLevel.NETWORKADMIN, request)) { - return "Operation not authorized"; - } - -*************** -*** 206,213 **** - @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST) - @ResponseBody - public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name, -- @RequestParam(required = true) String action) { -- if (!authorize(UserLevel.NETWORKADMIN)) { return "Operation not authorized"; } - - IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper - .getInstance(IForwardingRulesManager.class, "default", this); ---- 207,214 ---- - @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST) - @ResponseBody - public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name, -+ @RequestParam(required = true) String action, HttpServletRequest request) { -+ if (!authorize(UserLevel.NETWORKADMIN, request)) { return "Operation not authorized"; } - - IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper - .getInstance(IForwardingRulesManager.class, "default", this); -*************** -*** 235,248 **** - * - * @param level - */ -- private boolean authorize(UserLevel level) { - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); - if (userManager == null) { - return false; - } - -- String username = SecurityContextHolder.getContext().getAuthentication().getName(); - UserLevel userLevel = userManager.getUserLevel(username); - if (userLevel.toNumber() <= level.toNumber()) { - return true; ---- 236,249 ---- - * - * @param level - */ -+ private boolean authorize(UserLevel level, HttpServletRequest request) { - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); - if (userManager == null) { - return false; - } - -+ String username = request.getUserPrincipal().getName(); - UserLevel userLevel = userManager.getUserLevel(username); - if (userLevel.toNumber() <= level.toNumber()) { - return true; diff --git a/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp b/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp index a3d9dcff63..863b0a64a0 100644 --- a/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp +++ b/opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp @@ -56,12 +56,12 @@