Merge "1. Controller switchEvents queue should be priority based. The queue holds...
authorChi-Vien Ly <chivly@cisco.com>
Thu, 22 Aug 2013 03:53:25 +0000 (03:53 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 22 Aug 2013 03:53:25 +0000 (03:53 +0000)
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/RestMessages.java
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/BadRequestException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplemented.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplementedException.java [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/js/page.js
opendaylight/web/flows/src/main/resources/js/page.js
opendaylight/web/root/src/main/resources/js/lib.js

index 5db7d32..0304af4 100644 (file)
@@ -72,7 +72,7 @@ public class FlowConfig implements Serializable {
     private static final long serialVersionUID = 1L;
     private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
     private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
-    private static final String STATICFLOWGROUP = "__StaticFlows__";
+    public static final String STATICFLOWGROUP = "__StaticFlows__";
     public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
     public static final String INTERNALSTATICFLOWBEGIN = "__";
     public static final String INTERNALSTATICFLOWEND = "__";
index 57f3e8e..19b045b 100644 (file)
@@ -91,6 +91,7 @@ public class ForwardingRulesManager implements IForwardingRulesManager, PortGrou
     private static final String NODEDOWN = "Node is Down";
     private static final String SUCCESS = StatusCode.SUCCESS.toString();
     private static final Logger log = LoggerFactory.getLogger(ForwardingRulesManager.class);
+    private static final String PORTREMOVED = "Port removed";
     private String frmFileName;
     private String portGroupFileName;
     private ConcurrentMap<Integer, FlowConfig> staticFlows;
@@ -1926,6 +1927,32 @@ public class ForwardingRulesManager implements IForwardingRulesManager, PortGrou
         }
     }
 
+    private boolean doesFlowContainNodeConnector(Flow flow, NodeConnector nc) {
+        if (nc == null) {
+            return false;
+        }
+
+        Match match = flow.getMatch();
+        if (match.isPresent(MatchType.IN_PORT)) {
+            NodeConnector matchPort = (NodeConnector) match.getField(MatchType.IN_PORT).getValue();
+            if (matchPort.equals(nc)) {
+                return true;
+            }
+        }
+        List<Action> actionsList = flow.getActions();
+        if (actionsList != null) {
+            for (Action action : actionsList) {
+                if (action instanceof Output) {
+                    NodeConnector actionPort = ((Output) action).getPort();
+                    if (actionPort.equals(nc)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     public void notifyNode(Node node, UpdateType type, Map<String, Property> propMap) {
         this.pendingEvents.offer(new NodeUpdateEvent(type, node));
@@ -2269,10 +2296,66 @@ public class ForwardingRulesManager implements IForwardingRulesManager, PortGrou
     }
 
     @Override
-    public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType t) {
+    public void nodeConnectorUpdated(String containerName, NodeConnector nc, UpdateType t) {
         if (!container.getName().equals(containerName)) {
             return;
         }
+
+        boolean updateStaticFlowCluster = false;
+
+        switch (t) {
+        case REMOVED:
+
+            List<FlowEntryInstall> nodeFlowEntries = nodeFlows.get(nc.getNode());
+            if (nodeFlowEntries == null) {
+                return;
+            }
+            for (FlowEntryInstall fei : new ArrayList<FlowEntryInstall>(nodeFlowEntries)) {
+                if (doesFlowContainNodeConnector(fei.getInstall().getFlow(), nc)) {
+                    Status status = this.removeEntryInternal(fei, true);
+                    if (!status.isSuccess()) {
+                        continue;
+                    }
+                    /*
+                     * If the flow entry is a static flow, then update its
+                     * configuration
+                     */
+                    if (fei.getGroupName().equals(FlowConfig.STATICFLOWGROUP)) {
+                        FlowConfig flowConfig = getStaticFlow(fei.getFlowName(), fei.getNode());
+                        if (flowConfig != null) {
+                            flowConfig.setStatus(PORTREMOVED);
+                            updateStaticFlowCluster = true;
+                        }
+                    }
+                }
+            }
+            if (updateStaticFlowCluster) {
+                refreshClusterStaticFlowsStatus(nc.getNode());
+            }
+            break;
+        case ADDED:
+            List<FlowConfig> flowConfigForNode = getStaticFlows(nc.getNode());
+            for (FlowConfig flowConfig : flowConfigForNode) {
+                if (doesFlowContainNodeConnector(flowConfig.getFlow(), nc)) {
+                    if (flowConfig.installInHw()) {
+                        Status status = this.installFlowEntry(flowConfig.getFlowEntry());
+                        if (!status.isSuccess()) {
+                            flowConfig.setStatus(status.getDescription());
+                        } else {
+                            flowConfig.setStatus(SUCCESS);
+                        }
+                        updateStaticFlowCluster = true;
+                    }
+                }
+            }
+            if (updateStaticFlowCluster) {
+                refreshClusterStaticFlowsStatus(nc.getNode());
+            }
+            break;
+        case CHANGED:
+            break;
+        default:
+        }
     }
 
     @Override
index ebe36a9..668efbc 100644 (file)
@@ -9,17 +9,13 @@
 package org.opendaylight.controller.northbound.commons;
 
 public enum RestMessages {
-    SUCCESS("Success"), NOCONTAINER("Container does not exist"), NOFLOWSPEC(
-            "Flow Spec does not exist"), NOSUBNET("Subnet does not exist"), NOSTATICROUTE(
-            "Static Route does not exist"), NOHOST("Host does not exist"), NOFLOW(
-            "Flow does not exist"), NONODE("Node does not exist"), NOPOLICY(
-            "Policy does not exist"), NORESOURCE("Resource does not exist"), RESOURCECONFLICT(
-            "Operation failed due to Resource Conflict"), NODEFAULT(
-            "Container default is not a custom container"), DEFAULTDISABLED(
+    SUCCESS("Success"), NOCONTAINER("Container does not exist"), NOSUBNET("Subnet does not exist"), NOSTATICROUTE(
+            "Static Route does not exist"), NOHOST("Host does not exist"), NOFLOW("Flow does not exist"), NONODE(
+            "Node does not exist"), NOPOLICY("Policy does not exist"), NORESOURCE("Resource does not exist"), RESOURCECONFLICT(
+            "Operation failed due to Resource Conflict"), NODEFAULT("Container default is not a custom container"), DEFAULTDISABLED(
             "Container(s) are configured. Container default is not operational"), NOTALLOWEDONDEFAULT(
-            "Container default is a static resource, no modification allowed on it"), UNKNOWNACTION(
-            "Unknown action"), INVALIDJSON("JSON message is invalid"), INVALIDADDRESS(
-            "invalid InetAddress"), AVAILABLESOON(
+            "Container default is a static resource, no modification allowed on it"), UNKNOWNACTION("Unknown action"), INVALIDJSON(
+            "JSON message is invalid"), INVALIDADDRESS("invalid InetAddress"), AVAILABLESOON(
             "Resource is not implemented yet"), INTERNALERROR("Internal Error"), SERVICEUNAVAILABLE(
             "Service is not available. Could be down for maintanence"), INVALIDDATA(
             "Data is invalid or conflicts with URI");
@@ -30,6 +26,7 @@ public enum RestMessages {
         message = msg;
     }
 
+    @Override
     public String toString() {
         return message;
     }
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/BadRequestException.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/BadRequestException.java
new file mode 100644 (file)
index 0000000..c1b832d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.northbound.commons.exception;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Status Code 400 (Bad Request)
+ *
+ * The request could not be understood by the server due to malformed syntax.
+ * The client SHOULD NOT repeat the request without modifications.
+ */
+public class BadRequestException extends WebApplicationException {
+    private static final long serialVersionUID = 1L;
+
+    public BadRequestException(String string) {
+        super(Response.status(Response.Status.BAD_REQUEST).entity(string).type(MediaType.TEXT_PLAIN).build());
+    }
+}
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplemented.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplemented.java
new file mode 100644 (file)
index 0000000..16d0cd6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.northbound.commons.exception;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * Implementation of StatusType for error 501 as in:
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6
+ */
+public class NotImplemented implements Response.StatusType {
+    @Override
+    public int getStatusCode() {
+        return 501;
+    }
+
+    @Override
+    public String getReasonPhrase() {
+        return "Not Implemented";
+    }
+
+    @Override
+    public Response.Status.Family getFamily() {
+        return Response.Status.Family.SERVER_ERROR;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplementedException.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotImplementedException.java
new file mode 100644 (file)
index 0000000..5c931d2
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.northbound.commons.exception;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Status Code 501 (Not Implemented)
+ *
+ * The server does not support the functionality required to fulfill the
+ * request. This is the appropriate response when the server does not recognize
+ * the request method and is not capable of supporting it for any resource.
+ */
+public class NotImplementedException extends WebApplicationException {
+    private static final long serialVersionUID = 1L;
+
+    public NotImplementedException(String string) {
+        super(Response.status(new NotImplemented()).entity(string).type(MediaType.TEXT_PLAIN).build());
+    }
+}
index 824d2e9..6916be6 100644 (file)
@@ -74,6 +74,7 @@ one.f.switchmanager.nodesLearnt = {
         },
         modal: {
             modal: "one_f_switchmanager_nodesLearnt_id_modal_modal",
+            configure: "one_f_switchmanager_nodesLearnt_id_modal_configure",
             ports: "one_f_switchmanager_nodesLearnt_id_modal_ports",
             save: "one_f_switchmanager_nodesLearnt_id_modal_save",
             datagrid: "one_f_switchmanager_nodesLearnt_id_modal_datagrid",
@@ -137,7 +138,7 @@ one.f.switchmanager.nodesLearnt = {
                         h3 = 'Node Information';
                     }
                     
-                    var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.modal, h3, "", footer);
+                    var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.configure, h3, "", footer);
                     // bind save button
                     $('#' + one.f.switchmanager.nodesLearnt.id.modal.save, $modal).click(function() {
                         one.f.switchmanager.nodesLearnt.modal.save($modal);
@@ -166,7 +167,8 @@ one.f.switchmanager.nodesLearnt = {
                     searchable: true,
                     filterable: false,
                     pagination: true,
-                    flexibleRowsPerPage: true
+                    flexibleRowsPerPage: true,
+                    popout: true
                     }, "table-striped table-condensed");
                 one.lib.modal.inject.body($modal, $gridHTML);
                 $modal.on("shown", function() {
@@ -222,7 +224,8 @@ one.f.switchmanager.nodesLearnt = {
                         searchable: true,
                         filterable: false,
                         pagination: true,
-                        flexibleRowsPerPage: true
+                        flexibleRowsPerPage: true,
+                        popout: true
                         }, "table-striped table-condensed");
                 one.lib.modal.inject.body($modal, $gridHTML);
                 // attach to shown event of modal 
index 2a2dbf5..0f1eabb 100644 (file)
@@ -343,11 +343,13 @@ one.f.flows = {
                     $tr = $(tr);
                     $span = $("td span", $tr);
                     var flowstatus = $span.data("flowstatus");
-                    var installInHw = $span.data("installinhw").toString();
-                    if(installInHw == "true" && flowstatus == "Success") {
-                        $tr.addClass("success");
-                    } else {
-                        $tr.addClass("warning");
+                    if($span.data("installinhw") != null) {
+                        var installInHw = $span.data("installinhw").toString();
+                        if(installInHw == "true" && flowstatus == "Success") {
+                            $tr.addClass("success");
+                        } else {
+                            $tr.addClass("warning");
+                        }
                     }
                     // attach mouseover to show pointer cursor
                     $tr.mouseover(function() {
index 9c71262..90fd497 100644 (file)
@@ -99,7 +99,7 @@ one.lib.dashlet = {
                 $headerth.append(one.lib.dashlet.datagrid._searchable());
             }
             if(options.flexibleRowsPerPage == true) {
-                $footerth.append(one.lib.dashlet.datagrid._rowsPerPage());
+                $footerth.append(one.lib.dashlet.datagrid._rowsPerPage(options.popout));
             }
             if(options.pagination == true) {
                 $footerth.append(one.lib.dashlet.datagrid._pagination());
@@ -120,8 +120,12 @@ one.lib.dashlet = {
             var html = '<div class="datagrid-footer-right" style="display:none;"><div class="grid-pager"><button type="button" class="btn grid-prevpage"><i class="icon-chevron-left"></i></button><span>Page</span> <div style="display:inline-block;"><input type="text" name="pagenumber" style="width:25px;margin-bottom:-10px;vertical-align:middle;margin-right:5px;"></div><span>of <span class="grid-pages"></span></span><button type="button" class="btn grid-nextpage"><i class="icon-chevron-right"></i></button></div></div>';
             return html;
         },
-        _rowsPerPage: function() {
-            var html = '<div class="datagrid-footer-left" style="display:none;"><div class="grid-controls"><span><span class="grid-start"></span>-<span class="grid-end"></span> of <span class="grid-count"></span></span><div class="select grid-pagesize" data-resize="auto" style="visibility:hidden;"><button type="button" data-toggle="dropdown" class="btn dropdown-toggle"><span class="dropdown-label"></span><span class="caret"></span></button><ul class="dropdown-menu"><li data-value="5" data-selected="true"><a href="#">5</a></li><li data-value="10"><a href="#">10</a></li><li data-value="20"><a href="#">20</a></li><li data-value="50"><a href="#">50</a></li><li data-value="100"><a href="#">100</a></li></ul></div><span style="display:none;">Per Page</span></div></div>';
+        _rowsPerPage: function(popout) {
+            if(popout) {
+                var html = '<div class="datagrid-footer-left" style="display:none;"><div class="grid-controls"><span><span class="grid-start"></span>-<span class="grid-end"></span> of <span class="grid-count"></span></span><div class="select grid-pagesize" data-resize="auto" style="visibility:hidden;"><button type="button" data-toggle="dropdown" class="btn dropdown-toggle"><span class="dropdown-label"></span><span class="caret"></span></button><ul class="dropdown-menu"><li data-value="10" data-selected="true"><a href="#">5</a></li><li data-value="10"><a href="#">10</a></li><li data-value="20"><a href="#">20</a></li><li data-value="50"><a href="#">50</a></li><li data-value="100"><a href="#">100</a></li></ul></div><span style="display:none;">Per Page</span></div></div>';
+            } else {
+                var html = '<div class="datagrid-footer-left" style="display:none;"><div class="grid-controls"><span><span class="grid-start"></span>-<span class="grid-end"></span> of <span class="grid-count"></span></span><div class="select grid-pagesize" data-resize="auto" style="visibility:hidden;"><button type="button" data-toggle="dropdown" class="btn dropdown-toggle"><span class="dropdown-label"></span><span class="caret"></span></button><ul class="dropdown-menu"><li data-value="5" data-selected="true"><a href="#">5</a></li><li data-value="10"><a href="#">10</a></li><li data-value="20"><a href="#">20</a></li><li data-value="50"><a href="#">50</a></li><li data-value="100"><a href="#">100</a></li></ul></div><span style="display:none;">Per Page</span></div></div>';
+            }
             return html;
         }
     },