ISSUE: After controller restart, proactive flows are not installed
[controller.git] / opendaylight / web / devices / src / main / java / org / opendaylight / controller / devices / web / Devices.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.devices.web;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.Set;
17 import java.util.TreeMap;
18 import java.util.concurrent.ConcurrentMap;
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21
22 import org.codehaus.jackson.map.ObjectMapper;
23 import org.opendaylight.controller.usermanager.IUserManager;
24 import org.opendaylight.controller.web.IDaylightWeb;
25 import org.springframework.stereotype.Controller;
26 import org.springframework.web.bind.annotation.RequestMapping;
27 import org.springframework.web.bind.annotation.RequestMethod;
28 import org.springframework.web.bind.annotation.RequestParam;
29 import org.springframework.web.bind.annotation.ResponseBody;
30 import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
31 import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
32 import org.opendaylight.controller.sal.authorization.UserLevel;
33 import org.opendaylight.controller.sal.core.Name;
34 import org.opendaylight.controller.sal.core.Node;
35 import org.opendaylight.controller.sal.core.NodeConnector;
36 import org.opendaylight.controller.sal.core.Tier;
37 import org.opendaylight.controller.sal.utils.GlobalConstants;
38 import org.opendaylight.controller.sal.utils.HexEncode;
39 import org.opendaylight.controller.sal.utils.ServiceHelper;
40 import org.opendaylight.controller.sal.utils.Status;
41 import org.opendaylight.controller.sal.utils.TierHelper;
42 import org.opendaylight.controller.switchmanager.ISwitchManager;
43 import org.opendaylight.controller.switchmanager.SpanConfig;
44 import org.opendaylight.controller.switchmanager.SubnetConfig;
45 import org.opendaylight.controller.switchmanager.Switch;
46 import org.opendaylight.controller.switchmanager.SwitchConfig;
47
48 import com.google.gson.Gson;
49
50 @Controller
51 @RequestMapping("/")
52 public class Devices implements IDaylightWeb {
53     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
54     private final String WEB_NAME = "Devices";
55     private final String WEB_ID = "devices";
56     private final short WEB_ORDER = 1;
57     private final String containerName = GlobalConstants.DEFAULT.toString();
58
59     public Devices() {
60         ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
61     }
62
63     @Override
64     public String getWebName() {
65         return WEB_NAME;
66     }
67
68     @Override
69     public String getWebId() {
70         return WEB_ID;
71     }
72
73     @Override
74     public short getWebOrder() {
75         return WEB_ORDER;
76     }
77
78     @Override
79     public boolean isAuthorized(UserLevel userLevel) {
80         return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
81     }
82
83     @RequestMapping(value = "/nodesLearnt", method = RequestMethod.GET)
84     @ResponseBody
85     public DevicesJsonBean getNodesLearnt() {
86         Gson gson = new Gson();
87         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
88                 .getInstance(ISwitchManager.class, containerName, this);
89         List<Map<String, String>> nodeData = new ArrayList<Map<String, String>>();
90         for (Switch device : switchManager.getNetworkDevices()) {
91             HashMap<String, String> nodeDatum = new HashMap<String, String>();
92             Node node = device.getNode();
93             Tier tier = (Tier) switchManager.getNodeProp(node,
94                     Tier.TierPropName);
95
96             nodeDatum.put("containerName", containerName);
97             nodeDatum.put("nodeName", switchManager.getNodeDescription(node));
98             nodeDatum.put("nodeId", node.toString());//.getNodeIDString());
99             int tierNumber = (tier == null) ? TierHelper.unknownTierNumber
100                     : tier.getValue();
101             nodeDatum.put("tierName", TierHelper.getTierName(tierNumber)
102                     + " (Tier-" + tierNumber + ")");
103             nodeDatum.put("tier", tierNumber + "");
104             SwitchConfig sc = switchManager.getSwitchConfig(device.getNode()
105                     .getNodeIDString());
106             String modeStr = (sc != null) ? sc.getMode() : "0";
107             nodeDatum.put("mode", modeStr);
108
109             nodeDatum.put("json", gson.toJson(nodeDatum));
110             nodeDatum.put("mac",
111                     HexEncode.bytesToHexString(device.getDataLayerAddress()));
112             StringBuffer sb1 = new StringBuffer();
113             Set<NodeConnector> nodeConnectorSet = device.getNodeConnectors();
114             String nodeConnectorName;
115             String nodeConnectorNumberToStr;
116             if (nodeConnectorSet != null && nodeConnectorSet.size() > 0) {
117                 Map<Short, String> portList = new HashMap<Short, String>();
118                 for (NodeConnector nodeConnector : nodeConnectorSet) {
119                     nodeConnectorNumberToStr = nodeConnector.getID().toString();
120                     Name ncName = ((Name) switchManager.getNodeConnectorProp(
121                             nodeConnector, Name.NamePropName));
122                     nodeConnectorName = (ncName != null) ? ncName.getValue()
123                             : "";
124                     portList.put(Short.parseShort(nodeConnectorNumberToStr),
125                             nodeConnectorName);
126                 }
127                 Map<Short, String> sortedPortList = new TreeMap<Short, String>(
128                         portList);
129                 for (Entry<Short, String> e : sortedPortList.entrySet()) {
130                     sb1.append(e.getValue() + "(" + e.getKey() + ")");
131                     sb1.append("<br>");
132                 }
133             }
134             nodeDatum.put("ports", sb1.toString());
135             nodeData.add(nodeDatum);
136         }
137         DevicesJsonBean result = new DevicesJsonBean();
138         result.setNodeData(nodeData);
139         List<String> columnNames = new ArrayList<String>();
140         columnNames.add("Node ID");
141         columnNames.add("Node Name");
142         columnNames.add("Tier");
143         columnNames.add("Mac Address");
144         columnNames.add("Ports");
145
146         result.setColumnNames(columnNames);
147         return result;
148     }
149
150     @RequestMapping(value = "/tiers", method = RequestMethod.GET)
151     @ResponseBody
152     public List<String> getTiers() {
153         return TierHelper.getTiers();
154     }
155
156     @RequestMapping(value = "/nodesLearnt/update", method = RequestMethod.GET)
157     @ResponseBody
158     public StatusJsonBean updateLearntNode(
159             @RequestParam("nodeName") String nodeName,
160             @RequestParam("nodeId") String nodeId,
161             @RequestParam("tier") String tier,
162             @RequestParam("operationMode") String operationMode,
163             HttpServletRequest request) {
164         if (!authorize(UserLevel.NETWORKADMIN, request)) {
165             return unauthorizedMessage();
166         }
167
168         StatusJsonBean resultBean = new StatusJsonBean();
169         try {
170             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
171                     .getInstance(ISwitchManager.class, containerName, this);
172             SwitchConfig cfg = new SwitchConfig(nodeId, nodeName, tier,
173                     operationMode);
174             switchManager.updateSwitchConfig(cfg);
175             resultBean.setStatus(true);
176             resultBean.setMessage("Updated node information successfully");
177         } catch (Exception e) {
178             resultBean.setStatus(false);
179             resultBean.setMessage("Error updating node information. "
180                     + e.getMessage());
181         }
182         return resultBean;
183     }
184
185     @RequestMapping(value = "/staticRoutes", method = RequestMethod.GET)
186     @ResponseBody
187     public DevicesJsonBean getStaticRoutes() {
188         Gson gson = new Gson();
189         IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
190                 .getInstance(IForwardingStaticRouting.class, containerName,
191                         this);
192         List<Map<String, String>> staticRoutes = new ArrayList<Map<String, String>>();
193         ConcurrentMap<String, StaticRouteConfig> routeConfigs = staticRouting
194                 .getStaticRouteConfigs();
195         if (routeConfigs == null) {
196             return null;
197         }
198         for (StaticRouteConfig conf : routeConfigs.values()) {
199             Map<String, String> staticRoute = new HashMap<String, String>();
200             staticRoute.put("name", conf.getName());
201             staticRoute.put("staticRoute", conf.getStaticRoute());
202             staticRoute.put("nextHopType", conf.getNextHopType());
203             staticRoute.put("nextHop", conf.getNextHop());
204             staticRoute.put("json", gson.toJson(conf));
205             staticRoutes.add(staticRoute);
206         }
207         DevicesJsonBean result = new DevicesJsonBean();
208         result.setColumnNames(StaticRouteConfig.getGuiFieldsNames());
209         result.setNodeData(staticRoutes);
210         return result;
211     }
212
213     @RequestMapping(value = "/staticRoute/add", method = RequestMethod.GET)
214     @ResponseBody
215     public StatusJsonBean addStaticRoute(
216             @RequestParam("routeName") String routeName,
217             @RequestParam("staticRoute") String staticRoute,
218             @RequestParam("nextHop") String nextHop, HttpServletRequest request) {
219         if (!authorize(UserLevel.NETWORKADMIN, request)) {
220             return unauthorizedMessage();
221         }
222
223         StatusJsonBean result = new StatusJsonBean();
224         try {
225             IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
226                     .getInstance(IForwardingStaticRouting.class, containerName,
227                             this);
228             StaticRouteConfig config = new StaticRouteConfig();
229             config.setName(routeName);
230             config.setStaticRoute(staticRoute);
231             config.setNextHop(nextHop);
232             Status addStaticRouteResult = staticRouting.addStaticRoute(config);
233             if (addStaticRouteResult.isSuccess()) {
234                 result.setStatus(true);
235                 result.setMessage("Static Route saved successfully");
236             } else {
237                 result.setStatus(false);
238                 result.setMessage(addStaticRouteResult.getDescription());
239             }
240         } catch (Exception e) {
241             result.setStatus(false);
242             result.setMessage("Error - " + e.getMessage());
243         }
244         return result;
245     }
246
247     @RequestMapping(value = "/staticRoute/delete", method = RequestMethod.GET)
248     @ResponseBody
249     public StatusJsonBean deleteStaticRoute(
250             @RequestParam("routesToDelete") String routesToDelete,
251             HttpServletRequest request) {
252         if (!authorize(UserLevel.NETWORKADMIN, request)) {
253             return unauthorizedMessage();
254         }
255
256         StatusJsonBean resultBean = new StatusJsonBean();
257         try {
258             IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper
259                     .getInstance(IForwardingStaticRouting.class, containerName,
260                             this);
261             String[] routes = routesToDelete.split(",");
262             Status result;
263             resultBean.setStatus(true);
264             resultBean
265                     .setMessage("Successfully deleted selected static routes");
266             for (String route : routes) {
267                 result = staticRouting.removeStaticRoute(route);
268                 if (!result.isSuccess()) {
269                     resultBean.setStatus(false);
270                     resultBean.setMessage(result.getDescription());
271                     break;
272                 }
273             }
274         } catch (Exception e) {
275             resultBean.setStatus(false);
276             resultBean
277                     .setMessage("Error occurred while deleting static routes. "
278                             + e.getMessage());
279         }
280         return resultBean;
281     }
282
283     @RequestMapping(value = "/subnets", method = RequestMethod.GET)
284     @ResponseBody
285     public DevicesJsonBean getSubnetGateways() {
286         Gson gson = new Gson();
287         List<Map<String, String>> subnets = new ArrayList<Map<String, String>>();
288         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
289                 .getInstance(ISwitchManager.class, containerName, this);
290         for (SubnetConfig conf : switchManager.getSubnetsConfigList()) {
291             Map<String, String> subnet = new HashMap<String, String>();
292             subnet.put("name", conf.getName());
293             subnet.put("subnet", conf.getSubnet());
294             subnet.put("json", gson.toJson(conf));
295             subnets.add(subnet);
296         }
297         DevicesJsonBean result = new DevicesJsonBean();
298         result.setColumnNames(SubnetConfig.getGuiFieldsNames());
299         result.setNodeData(subnets);
300         return result;
301     }
302
303     @RequestMapping(value = "/subnetGateway/add", method = RequestMethod.GET)
304     @ResponseBody
305     public StatusJsonBean addSubnetGateways(
306             @RequestParam("gatewayName") String gatewayName,
307             @RequestParam("gatewayIPAddress") String gatewayIPAddress,
308             HttpServletRequest request) {
309         if (!authorize(UserLevel.NETWORKADMIN, request)) {
310             return unauthorizedMessage();
311         }
312
313         StatusJsonBean resultBean = new StatusJsonBean();
314         try {
315             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
316                     .getInstance(ISwitchManager.class, containerName, this);
317             SubnetConfig cfgObject = new SubnetConfig(gatewayName,
318                     gatewayIPAddress, new ArrayList<String>());
319             Status result = switchManager.addSubnet(cfgObject);
320             if (result.isSuccess()) {
321                 resultBean.setStatus(true);
322                 resultBean.setMessage("Added gateway address successfully");
323             } else {
324                 resultBean.setStatus(false);
325                 resultBean.setMessage(result.getDescription());
326             }
327         } catch (Exception e) {
328             resultBean.setStatus(false);
329             resultBean.setMessage(e.getMessage());
330         }
331         return resultBean;
332     }
333
334     @RequestMapping(value = "/subnetGateway/delete", method = RequestMethod.GET)
335     @ResponseBody
336     public StatusJsonBean deleteSubnetGateways(
337             @RequestParam("gatewaysToDelete") String gatewaysToDelete,
338             HttpServletRequest request) {
339         if (!authorize(UserLevel.NETWORKADMIN, request)) {
340             return unauthorizedMessage();
341         }
342
343         StatusJsonBean resultBean = new StatusJsonBean();
344         try {
345             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
346                     .getInstance(ISwitchManager.class, containerName, this);
347             String[] subnets = gatewaysToDelete.split(",");
348             resultBean.setStatus(true);
349             resultBean.setMessage("Added gateway address successfully");
350             for (String subnet : subnets) {
351                 Status result = switchManager.removeSubnet(subnet);
352                 if (!result.isSuccess()) {
353                     resultBean.setStatus(false);
354                     resultBean.setMessage(result.getDescription());
355                     break;
356                 }
357             }
358         } catch (Exception e) {
359             resultBean.setStatus(false);
360             resultBean.setMessage(e.getMessage());
361         }
362         return resultBean;
363     }
364
365     @RequestMapping(value = "/subnetGateway/ports/add", method = RequestMethod.GET)
366     @ResponseBody
367     public StatusJsonBean addSubnetGatewayPort(
368             @RequestParam("portsName") String portsName,
369             @RequestParam("ports") String ports,
370             @RequestParam("nodeId") String nodeId, HttpServletRequest request) {
371         if (!authorize(UserLevel.NETWORKADMIN, request)) {
372             return unauthorizedMessage();
373         }
374
375         StatusJsonBean resultBean = new StatusJsonBean();
376         try {
377             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
378                     .getInstance(ISwitchManager.class, containerName, this);
379             Status result = switchManager.addPortsToSubnet(portsName, nodeId
380                     + "/" + ports);
381
382             if (result.isSuccess()) {
383                 resultBean.setStatus(true);
384                 resultBean
385                         .setMessage("Added ports to subnet gateway address successfully");
386             } else {
387                 resultBean.setStatus(false);
388                 resultBean.setMessage(result.getDescription());
389             }
390         } catch (Exception e) {
391             resultBean.setStatus(false);
392             resultBean.setMessage(e.getMessage());
393         }
394         return resultBean;
395     }
396
397     @RequestMapping(value = "/subnetGateway/ports/delete", method = RequestMethod.GET)
398     @ResponseBody
399     public StatusJsonBean deleteSubnetGatewayPort(
400             @RequestParam("gatewayName") String gatewayName,
401             @RequestParam("nodePort") String nodePort,
402             HttpServletRequest request) {
403         if (!authorize(UserLevel.NETWORKADMIN, request)) {
404             return unauthorizedMessage();
405         }
406
407         StatusJsonBean resultBean = new StatusJsonBean();
408         try {
409             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
410                     .getInstance(ISwitchManager.class, containerName, this);
411             Status result = switchManager.removePortsFromSubnet(gatewayName,
412                     nodePort);
413
414             if (result.isSuccess()) {
415                 resultBean.setStatus(true);
416                 resultBean
417                         .setMessage("Deleted port from subnet gateway address successfully");
418             } else {
419                 resultBean.setStatus(false);
420                 resultBean.setMessage(result.getDescription());
421             }
422         } catch (Exception e) {
423             resultBean.setStatus(false);
424             resultBean.setMessage(e.getMessage());
425         }
426         return resultBean;
427     }
428
429     @RequestMapping(value = "/spanPorts", method = RequestMethod.GET)
430     @ResponseBody
431     public DevicesJsonBean getSpanPorts() {
432         Gson gson = new Gson();
433         List<String> spanConfigs_json = new ArrayList<String>();
434         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
435                 .getInstance(ISwitchManager.class, containerName, this);
436         for (SpanConfig conf : switchManager.getSpanConfigList()) {
437             spanConfigs_json.add(gson.toJson(conf));
438         }
439         ObjectMapper mapper = new ObjectMapper();
440         List<Map<String, String>> spanConfigs = new ArrayList<Map<String, String>>();
441         for (String config_json : spanConfigs_json) {
442             try {
443                 @SuppressWarnings("unchecked")
444                 Map<String, String> config_data = mapper.readValue(config_json,
445                         HashMap.class);
446                 Map<String, String> config = new HashMap<String, String>();
447                 for (String name : config_data.keySet()) {
448                     config.put(name, config_data.get(name));
449                     // Add switch name value (non-configuration field)
450                     config.put("nodeName",
451                             getNodeDesc(config_data.get("nodeId")));
452                 }
453                 config.put("json", config_json);
454                 spanConfigs.add(config);
455             } catch (Exception e) {
456                 // TODO: Handle the exception.
457             }
458         }
459         DevicesJsonBean result = new DevicesJsonBean();
460         result.setColumnNames(SpanConfig.getGuiFieldsNames());
461         result.setNodeData(spanConfigs);
462         return result;
463     }
464
465     @RequestMapping(value = "/nodeports")
466     @ResponseBody
467     public Map<String, Object> getNodePorts() {
468         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
469                 .getInstance(ISwitchManager.class, containerName, this);
470         if (switchManager == null)
471             return null;
472
473         Map<String, Object> nodes = new HashMap<String, Object>();
474         Map<Short, String> port;
475
476         for (Switch node : switchManager.getNetworkDevices()) {
477             port = new HashMap<Short, String>(); // new port
478             Set<NodeConnector> nodeConnectorSet = node.getNodeConnectors();
479
480             if (nodeConnectorSet != null)
481                 for (NodeConnector nodeConnector : nodeConnectorSet) {
482                     String nodeConnectorName = ((Name) switchManager
483                             .getNodeConnectorProp(nodeConnector,
484                                     Name.NamePropName)).getValue();
485                     port.put((Short) nodeConnector.getID(), nodeConnectorName
486                             + "(" + nodeConnector.getID() + ")");
487                 }
488
489             nodes.put(node.getNode().toString(), port);
490         }
491
492         return nodes;
493     }
494
495     @RequestMapping(value = "/spanPorts/add", method = RequestMethod.GET)
496     @ResponseBody
497     public StatusJsonBean addSpanPort(
498             @RequestParam("jsonData") String jsonData,
499             HttpServletRequest request) {
500         if (!authorize(UserLevel.NETWORKADMIN, request)) {
501             return unauthorizedMessage();
502         }
503
504         StatusJsonBean resultBean = new StatusJsonBean();
505         try {
506             Gson gson = new Gson();
507             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
508                     .getInstance(ISwitchManager.class, containerName, this);
509             SpanConfig cfgObject = gson.fromJson(jsonData, SpanConfig.class);
510             Status result = switchManager.addSpanConfig(cfgObject);
511             if (result.isSuccess()) {
512                 resultBean.setStatus(true);
513                 resultBean.setMessage("SPAN Port added successfully");
514             } else {
515                 resultBean.setStatus(false);
516                 resultBean.setMessage(result.getDescription());
517             }
518         } catch (Exception e) {
519             resultBean.setStatus(false);
520             resultBean.setMessage("Error occurred while adding span port. "
521                     + e.getMessage());
522         }
523         return resultBean;
524     }
525
526     @RequestMapping(value = "/spanPorts/delete", method = RequestMethod.GET)
527     @ResponseBody
528     public StatusJsonBean deleteSpanPorts(
529             @RequestParam("spanPortsToDelete") String spanPortsToDelete,
530             HttpServletRequest request) {
531         if (!authorize(UserLevel.NETWORKADMIN, request)) {
532             return unauthorizedMessage();
533         }
534
535         StatusJsonBean resultBean = new StatusJsonBean();
536         try {
537             Gson gson = new Gson();
538             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
539                     .getInstance(ISwitchManager.class, containerName, this);
540             String[] spans = spanPortsToDelete.split("###");
541             resultBean.setStatus(true);
542             resultBean.setMessage("SPAN Port(s) deleted successfully");
543             for (String span : spans) {
544                 if (!span.isEmpty()) {
545                     SpanConfig cfgObject = gson
546                             .fromJson(span, SpanConfig.class);
547                     Status result = switchManager.removeSpanConfig(cfgObject);
548                     if (!result.isSuccess()) {
549                         resultBean.setStatus(false);
550                         resultBean.setMessage(result.getDescription());
551                         break;
552                     }
553                 }
554             }
555         } catch (Exception e) {
556             resultBean.setStatus(false);
557             resultBean.setMessage("Error occurred while deleting span port. "
558                     + e.getMessage());
559         }
560         return resultBean;
561     }
562
563     private String getNodeDesc(String nodeId) {
564         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
565                 .getInstance(ISwitchManager.class, containerName, this);
566         String description = "";
567         if (switchManager != null) {
568             description = switchManager.getNodeDescription(Node
569                     .fromString(nodeId));
570         }
571         return (description.isEmpty() || description.equalsIgnoreCase("none")) ? nodeId
572                 : description;
573     }
574
575     /**
576      * Is the operation permitted for the given level
577      * 
578      * @param level
579      */
580     private boolean authorize(UserLevel level, HttpServletRequest request) {
581         IUserManager userManager = (IUserManager) ServiceHelper
582                 .getGlobalInstance(IUserManager.class, this);
583         if (userManager == null) {
584             return false;
585         }
586
587         String username = request.getUserPrincipal().getName();
588         UserLevel userLevel = userManager.getUserLevel(username);
589         if (userLevel.toNumber() <= level.toNumber()) {
590             return true;
591         }
592         return false;
593     }
594
595     private StatusJsonBean unauthorizedMessage() {
596         StatusJsonBean message = new StatusJsonBean();
597         message.setStatus(false);
598         message.setMessage("Operation not authorized");
599         return message;
600     }
601
602     @RequestMapping(value = "login")
603     public String login(final HttpServletRequest request,
604             final HttpServletResponse response) {
605         // response.setHeader("X-Page-Location", "/login");
606         /*
607          * IUserManager userManager = (IUserManager) ServiceHelper
608          * .getGlobalInstance(IUserManager.class, this); if (userManager ==
609          * null) { return "User Manager is not available"; }
610          * 
611          * String username = request.getUserPrincipal().getName();
612          * 
613          * 
614          * model.addAttribute("username", username); model.addAttribute("role",
615          * userManager.getUserLevel(username).toNumber());
616          */
617         return "forward:" + "/";
618     }
619
620 }