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 5db7d32745f12b3bd8e264222291ae8d4cf766c6..0304af493d9fe64abab2df516bc5b3c2e63c098c 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 57f3e8eb3605195f516aec818ee6c4200fec9186..19b045b217a3a5877a4d3e00cb58840e23f13f7e 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 ebe36a9d78aecfd45525560530508e2bd5110aa6..668efbc7ee3868b2ea3b8e1c22a3ce9c9b305e78 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 824d2e9b856962cab065dc4b5cb0ee381a14d223..6916be679877fadb2423912e67bdb243f4d0fb3e 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 2a2dbf5b4d1b0dc38e5c87bb4463d53eefd9ee21..0f1eabb85929dde53cecacf939b69c4b1e651edb 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 9c7126274579b0609370ccec088b40343cde158f..90fd49772a71f0027811817cd3a07671db19f0d1 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;
         }
     },