From c11dff1f548652d147d25966033a1cd31416afc9 Mon Sep 17 00:00:00 2001 From: Andrew Kim Date: Thu, 5 Sep 2013 15:15:18 -0500 Subject: [PATCH] Add Cluster Menu Change-Id: Ie795953393493a41dd05a0a8a7de03ddb5278729 Signed-off-by: Andrew Kim --- opendaylight/web/root/pom.xml | 18 ++ .../controller/web/ClusterNodeBean.java | 50 ++++ .../controller/web/DaylightWebAdmin.java | 128 +++++++-- .../opendaylight/controller/web/NodeBean.java | 21 ++ .../src/main/resources/WEB-INF/jsp/main.jsp | 10 +- .../web/root/src/main/resources/css/one.less | 4 + .../resources/img/topology_view_1033_16.png | Bin 0 -> 687 bytes .../web/root/src/main/resources/js/lib.js | 11 + .../web/root/src/main/resources/js/open.js | 269 +++++++++++++----- 9 files changed, 403 insertions(+), 108 deletions(-) create mode 100644 opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ClusterNodeBean.java create mode 100644 opendaylight/web/root/src/main/java/org/opendaylight/controller/web/NodeBean.java create mode 100644 opendaylight/web/root/src/main/resources/img/topology_view_1033_16.png diff --git a/opendaylight/web/root/pom.xml b/opendaylight/web/root/pom.xml index 6000efadc7..bc5c73a7d8 100644 --- a/opendaylight/web/root/pom.xml +++ b/opendaylight/web/root/pom.xml @@ -34,6 +34,9 @@ org.opendaylight.controller.sal.utils, org.opendaylight.controller.usermanager, org.opendaylight.controller.containermanager, + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.connectionmanager, + org.opendaylight.controller.switchmanager, com.google.gson, javax.annotation, javax.naming, @@ -92,6 +95,16 @@ + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + connectionmanager + 0.1.0-SNAPSHOT + org.opendaylight.controller configuration @@ -112,6 +125,11 @@ containermanager 0.4.0-SNAPSHOT + + org.opendaylight.controller + switchmanager + 0.5.0-SNAPSHOT + junit junit diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ClusterNodeBean.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ClusterNodeBean.java new file mode 100644 index 0000000000..5e4f22afe2 --- /dev/null +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ClusterNodeBean.java @@ -0,0 +1,50 @@ +package org.opendaylight.controller.web; + +import java.net.InetAddress; + +/** + * Information about a clustered controller to send to the UI frontend + * @author andrekim + */ +public class ClusterNodeBean { + private final byte[] address; + private final String name; + private final Boolean me; + private final Boolean coordinator; + + public static class Builder { + // required params + private final byte[] address; + private final String name; + + // optional params + private Boolean me = null; + private Boolean coordinator = null; + + public Builder(InetAddress address) { + this.address = address.getAddress(); + this.name = address.getHostAddress(); + } + + public Builder highlightMe() { + this.me = true; + return this; + } + + public Builder iAmCoordinator() { + this.coordinator = true; + return this; + } + + public ClusterNodeBean build() { + return new ClusterNodeBean(this); + } + } + + private ClusterNodeBean(Builder builder) { + this.address = builder.address; + this.name = builder.name; + this.me = builder.me; + this.coordinator = builder.coordinator; + } +} \ No newline at end of file diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java index 524cb62b3a..d9aa03ea62 100644 --- a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java @@ -8,14 +8,24 @@ package org.opendaylight.controller.web; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.List; +import java.util.Set; import javax.servlet.http.HttpServletRequest; +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.connectionmanager.IConnectionManager; import org.opendaylight.controller.sal.authorization.UserLevel; +import org.opendaylight.controller.sal.core.Description; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; +import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.usermanager.IUserManager; import org.opendaylight.controller.usermanager.UserConfig; import org.springframework.stereotype.Controller; @@ -30,14 +40,95 @@ import com.google.gson.Gson; @Controller @RequestMapping("/admin") public class DaylightWebAdmin { + Gson gson = new Gson(); + /** + * Returns list of clustered controllers. Highlights "this" controller and + * if controller is coordinator + * @return List + */ + @RequestMapping("/cluster") + @ResponseBody + public String getClusteredControllers() { + IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance( + IClusterGlobalServices.class, this); + if (clusterServices == null) { + return null; + } + + List clusters = new ArrayList(); + + List controllers = clusterServices.getClusteredControllers(); + for (InetAddress controller : controllers) { + ClusterNodeBean.Builder clusterBeanBuilder = new ClusterNodeBean.Builder(controller); + if (controller.equals(clusterServices.getMyAddress())) { + clusterBeanBuilder.highlightMe(); + } + if (clusterServices.amICoordinator()) { + clusterBeanBuilder.iAmCoordinator(); + } + + clusters.add(clusterBeanBuilder.build()); + } + + return gson.toJson(clusters); + } + + /** + * Return nodes connected to controller {controller} + * @param cluster + * - byte[] of the address of the controller + * @return List + */ + @RequestMapping("/cluster/controller/{controller}") + @ResponseBody + public String getNodesConnectedToController(@PathVariable("controller") String cluster) { + IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance( + IClusterGlobalServices.class, this); + if (clusterServices == null) { + return null; + } + IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance( + IConnectionManager.class, this); + if (connectionManager == null) { + return null; + } + ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, + GlobalConstants.DEFAULT.toString(), this); + if (switchManager == null) { + return null; + } + + byte[] address = gson.fromJson(cluster, byte[].class); + InetAddress clusterAddress = null; + try { + clusterAddress = InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + return null; + } + InetAddress thisCluster = clusterServices.getMyAddress(); + + List result = new ArrayList(); + + Set nodes = connectionManager.getNodes(thisCluster); + for (Node node : nodes) { + Description description = (Description) switchManager.getNodeProp(node, Description.propertyName); + NodeBean nodeBean; + if (description == null || description.getValue().equals("None")) { + nodeBean = new NodeBean(node); + } else { + nodeBean = new NodeBean(node, description.getValue()); + } + result.add(nodeBean); + } + return gson.toJson(result); + } @RequestMapping("/users") @ResponseBody public List getUsers() { - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); + IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { return null; } @@ -52,13 +143,10 @@ public class DaylightWebAdmin { */ @RequestMapping(value = "/users", method = RequestMethod.POST) @ResponseBody - public String saveLocalUserConfig( - @RequestParam(required = true) String json, - @RequestParam(required = true) String action, - HttpServletRequest request) { + public String saveLocalUserConfig(@RequestParam(required = true) String json, + @RequestParam(required = true) String action, HttpServletRequest request) { - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); + IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { return "Internal Error"; } @@ -70,10 +158,9 @@ public class DaylightWebAdmin { Gson gson = new Gson(); UserConfig config = gson.fromJson(json, UserConfig.class); - Status result = (action.equals("add")) ? userManager - .addLocalUser(config) : userManager.removeLocalUser(config); - if(result.getCode().equals(StatusCode.SUCCESS)) { - String userAction=(action.equals("add")) ? "added":"removed"; + Status result = (action.equals("add")) ? userManager.addLocalUser(config) : userManager.removeLocalUser(config); + if (result.isSuccess()) { + String userAction = (action.equals("add")) ? "added" : "removed"; DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser()); return "Success"; } @@ -82,16 +169,14 @@ public class DaylightWebAdmin { @RequestMapping(value = "/users/{username}", method = RequestMethod.POST) @ResponseBody - public String removeLocalUser(@PathVariable("username") String userName, - HttpServletRequest request) { + public String removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) { String username = request.getUserPrincipal().getName(); if (username.equals(userName)) { return "Invalid Request: User cannot delete itself"; } - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); + IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { return "Internal Error"; } @@ -101,7 +186,7 @@ public class DaylightWebAdmin { } Status result = userManager.removeLocalUser(userName); - if(result.getCode().equals(StatusCode.SUCCESS)) { + if (result.isSuccess()) { DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName); return "Success"; } @@ -112,8 +197,7 @@ public class DaylightWebAdmin { @ResponseBody public Status changePassword(@PathVariable("username") String username, HttpServletRequest request, @RequestParam("currentPassword") String currentPassword, @RequestParam("newPassword") String newPassword) { - IUserManager userManager = (IUserManager) ServiceHelper - .getGlobalInstance(IUserManager.class, this); + IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { return new Status(StatusCode.GONE, "User Manager not found"); } @@ -127,7 +211,7 @@ public class DaylightWebAdmin { } Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword); - if(status.isSuccess()){ + if (status.isSuccess()) { DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username); } return status; @@ -135,11 +219,9 @@ public class DaylightWebAdmin { /** * Is the operation permitted for the given level - * * @param level */ - private boolean authorize(IUserManager userManager, UserLevel level, - HttpServletRequest request) { + private boolean authorize(IUserManager userManager, UserLevel level, HttpServletRequest request) { String username = request.getUserPrincipal().getName(); UserLevel userLevel = userManager.getUserLevel(username); return userLevel.toNumber() <= level.toNumber(); diff --git a/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/NodeBean.java b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/NodeBean.java new file mode 100644 index 0000000000..21d931051b --- /dev/null +++ b/opendaylight/web/root/src/main/java/org/opendaylight/controller/web/NodeBean.java @@ -0,0 +1,21 @@ +package org.opendaylight.controller.web; + +import org.opendaylight.controller.sal.core.Node; + +/** + * Information about a node connected to a controller to send to the UI frontend + * @author andrekim + */ +public class NodeBean { + private final String node; + private final String description; + + public NodeBean(Node node) { + this(node, node.toString()); + } + + public NodeBean(Node node, String description) { + this.node = node.toString(); + this.description = description; + } +} 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 c7c3ef16c3..c795a5d56b 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 @@ -71,12 +71,10 @@
${username} diff --git a/opendaylight/web/root/src/main/resources/css/one.less b/opendaylight/web/root/src/main/resources/css/one.less index 6ec818c18c..db9d7632d5 100644 --- a/opendaylight/web/root/src/main/resources/css/one.less +++ b/opendaylight/web/root/src/main/resources/css/one.less @@ -88,6 +88,10 @@ .icon; background-image: url('../img/user_group_0107_16.png'); } + .icon-cluster { + .icon; + background-image: url('../img/topology_view_1033_16.png'); + } .icon-save { .icon; background-image: url('../img/save_as_0106_16.png'); diff --git a/opendaylight/web/root/src/main/resources/img/topology_view_1033_16.png b/opendaylight/web/root/src/main/resources/img/topology_view_1033_16.png new file mode 100644 index 0000000000000000000000000000000000000000..1a132542c9ec4e060d4246091ac7fdf1b20a4e38 GIT binary patch literal 687 zcmV;g0#N;lP)oC2M<450i-yvsbj)r022$_%|9Q$F?|30 zoq>^w^(!uQEO-p)J$T~r5++WLpDY~QeYn&yfWiP5K5+8N|J56|e#NJTrS!7C?e#qm z4)KU`{g>4j3+mRr2nno(jQnaZgc&s17`Yf0zTshr|NjLf3{wB#)U$&>zWip?aFP#X zh+Hc9XXpL$|C?`@{tuob@(*nC0tSh%QyISe|MmVq2!EaoWG`Ug2gwD^7WsSNQT_iN z_saf9EtCAq1PtbPzkabWy#M@xft!V$vAKKd|Hltmp0jCKasPRLp5gz?at2NlH|{47 znLkuC_WTv#;$r&n^*zInpNv2+F#Kkb(iJUSaca>Lc45}vVn)J^$~R@dioW?%4h(t; zX13i73~WL`hd*Et6#4t%)4flDLb?LdyC3aa^5Nr$KhnCQ&5YO*($D!EKA+zI+$`i6 z3grD|_;6qy0|!61J$KTVLqtVm!=r{{?)C=1^!NKRF#TuvbwXn`CWuCx=AkSZHH z1b+Vd^ZLw{N5O(czuEbVfAe0y|1JV3^%5k9t{(0MSla*c@&luV?1wEY>cf1I6~;F% zUVZS1LDU`tf1eZ!jUJeS!af7}!64 zW#HiB{e*4+2S4u>ko?E{Z&30EvH`t&&c0ySapBERMi$mSY