Implemented OVS list bridge functionality and Junit
[ovsdb.git] / ovsdb / src / main / java / org / opendaylight / ovsdb / internal / ConfigurationService.java
1 package org.opendaylight.ovsdb.internal;
2
3 import java.net.InetAddress;
4 import java.net.UnknownHostException;
5 import java.util.*;
6
7 import org.eclipse.osgi.framework.console.CommandInterpreter;
8 import org.eclipse.osgi.framework.console.CommandProvider;
9 import org.opendaylight.ovsdb.database.OVSBridge;
10 import org.opendaylight.ovsdb.database.OVSInstance;
11 import org.opendaylight.ovsdb.database.OvsdbType;
12 import org.opendaylight.controller.sal.connection.ConnectionConstants;
13 import org.opendaylight.controller.sal.core.Node;
14 import org.opendaylight.controller.sal.core.NodeConnector;
15 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
16 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
17 import org.opendaylight.controller.sal.utils.Status;
18 import org.opendaylight.controller.sal.utils.StatusCode;
19 import org.osgi.framework.BundleContext;
20 import org.osgi.framework.FrameworkUtil;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 public class ConfigurationService implements IPluginInBridgeDomainConfigService, CommandProvider
25 {
26     private static final Logger logger = LoggerFactory
27             .getLogger(ConfigurationService.class);
28
29     IConnectionServiceInternal connectionService;
30     boolean forceConnect = false;
31
32     void init() {
33     }
34
35     /**
36      * Function called by the dependency manager when at least one dependency
37      * become unsatisfied or when the component is shutting down because for
38      * example bundle is being stopped.
39      *
40      */
41     void destroy() {
42     }
43
44     /**
45      * Function called by dependency manager after "init ()" is called and after
46      * the services provided by the class are registered in the service registry
47      *
48      */
49     void start() {
50         registerWithOSGIConsole();
51     }
52
53     private void registerWithOSGIConsole() {
54         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
55                 .getBundleContext();
56         bundleContext.registerService(CommandProvider.class.getName(), this,
57                 null);
58     }
59
60     /**
61      * Function called by the dependency manager before the services exported by
62      * the component are unregistered, this will be followed by a "destroy ()"
63      * calls
64      *
65      */
66     void stop() {
67     }
68
69     public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
70         this.connectionService = connectionService;
71     }
72
73     public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
74         if (this.connectionService == connectionService) {
75             this.connectionService = null;
76         }
77     }
78
79     private Connection getConnection (Node node) {
80
81         Connection connection = connectionService.getConnection(node);
82         if (connection == null || connection.getSocket() == null) {
83             return null;
84         }
85
86         /*
87          * This is possible only when the connection is disconnected due to any reason.
88          * But, we have to implement ECHO handling else, it results in timeout and the
89          * connection being partially closed from the server side and the client Socket
90          * seems to be up. Hence forcing the issue for now till we implement the ECHO.
91          */
92         if (connection.getSocket().isClosed() || forceConnect) {
93             String address = connection.getSocket().getInetAddress().getHostAddress();
94             Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
95             params.put(ConnectionConstants.ADDRESS, address);
96             params.put(ConnectionConstants.PORT, connection.getSocket().getPort()+"");
97             node = connectionService.connect(connection.getIdentifier(), params);
98             connection = connectionService.getConnection(node);
99         }
100         if (connection == null || connection.getSocket() == null || connection.getSocket().isClosed()) {
101             return null;
102         }
103         return connection;
104     }
105     /**
106      * Add a new bridge
107      * @param node Node serving this configuration service
108      * @param bridgeConnectorIdentifier String representation of a Bridge Connector
109      * @return Bridge Connector configurations
110      */
111     @Override
112     public Status createBridgeDomain(Node node, String bridgeIdentifier,
113             Map<ConfigConstants, Object> configs) throws Throwable {
114         try{
115             if (connectionService == null) {
116                 logger.error("Couldn't refer to the ConnectionService");
117                 return new Status(StatusCode.NOSERVICE);
118             }
119
120             Connection connection = this.getConnection(node);
121             if (connection == null || connection.getSocket() == null) {
122                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
123             }
124
125             if (connection != null) {
126                 String newBridge = "new_bridge";
127                 String newInterface = "new_interface";
128                 String newPort = "new_port";
129                 String newSwitch = "new_switch";
130
131                 Object addSwitchRequest;
132
133                 OVSInstance instance = OVSInstance.monitorOVS(connection);
134
135                 if(instance != null){
136                     List<String> bridgeUuidPair = new ArrayList<String>();
137                     bridgeUuidPair.add("named-uuid");
138                     bridgeUuidPair.add(newBridge);
139
140                     List<Object> mutation = new ArrayList<Object>();
141                     mutation.add("bridges");
142                     mutation.add("insert");
143                     mutation.add(bridgeUuidPair);
144
145                     List<Object> mutations = new ArrayList<Object>();
146                     mutations.add(mutation);
147
148                     List<String> ovsUuidPair = new ArrayList<String>();
149                     ovsUuidPair.add("uuid");
150                     ovsUuidPair.add(instance.getUuid());
151
152                     List<Object> whereInner = new ArrayList<Object>();
153                     whereInner.add("_uuid");
154                     whereInner.add("==");
155                     whereInner.add(ovsUuidPair);
156
157                     List<Object> where = new ArrayList<Object>();
158                     where.add(whereInner);
159
160                     addSwitchRequest = new MutateRequest("Open_vSwitch", where, mutations);
161                 }
162                 else{
163                     Map<String, Object> vswitchRow = new HashMap<String, Object>();
164                     ArrayList<String> bridges = new ArrayList<String>();
165                     bridges.add("named-uuid");
166                     bridges.add(newBridge);
167                     vswitchRow.put("bridges", bridges);
168                     addSwitchRequest = new InsertRequest("insert", "Open_vSwitch", newSwitch, vswitchRow);
169                 }
170
171                 Map<String, Object> bridgeRow = new HashMap<String, Object>();
172                 bridgeRow.put("name", bridgeIdentifier);
173                 ArrayList<String> ports = new ArrayList<String>();
174                 ports.add("named-uuid");
175                 ports.add(newPort);
176                 bridgeRow.put("ports", ports);
177                 InsertRequest addBridgeRequest = new InsertRequest("insert", "Bridge", newBridge, bridgeRow);
178
179                 Map<String, Object> portRow = new HashMap<String, Object>();
180                 portRow.put("name", bridgeIdentifier);
181                 ArrayList<String> interfaces = new ArrayList<String>();
182                 interfaces.add("named-uuid");
183                 interfaces.add(newInterface);
184                 portRow.put("interfaces", interfaces);
185                 InsertRequest addPortRequest = new InsertRequest("insert", "Port", newPort, portRow);
186
187                 Map<String, Object> interfaceRow = new HashMap<String, Object>();
188                 interfaceRow.put("name", bridgeIdentifier);
189                 interfaceRow.put("type", "internal");
190                 InsertRequest addIntfRequest = new InsertRequest("insert", "Interface", newInterface, interfaceRow);
191
192                 Object[] params = {"Open_vSwitch", addSwitchRequest, addIntfRequest, addPortRequest, addBridgeRequest};
193                 OvsdbMessage msg = new OvsdbMessage("transact", params);
194
195                 connection.sendMessage(msg);
196             }
197         }catch(Exception e){
198             e.printStackTrace();
199         }
200         return new Status(StatusCode.SUCCESS);
201     }
202
203     /**
204      * Create a Port Attached to a Bridge
205      * Ex. ovs-vsctl add-port br0 vif0
206      * @param node Node serving this configuration service
207      * @param bridgeDomainIdentifier String representation of a Bridge Domain
208      * @param portIdentifier String representation of a user defined Port Name
209      */
210     @Override
211     public Status addPort(Node node, String bridgeIdentifier, String portIdentifier, Map<ConfigConstants, Object> configs) {
212         try{
213             if (connectionService == null) {
214                 logger.error("Couldn't refer to the ConnectionService");
215                 return new Status(StatusCode.NOSERVICE);
216             }
217             Connection connection = this.getConnection(node);
218             if (connection == null || connection.getSocket() == null) {
219                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
220             }
221
222             if (connection != null) {
223                 String newInterface = "new_interface";
224                 String newPort = "new_port";
225
226                 Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
227
228                 OVSBridge bridge = existingBridges.get(bridgeIdentifier);
229
230                 List<String> portUuidPair = new ArrayList<String>();
231                 portUuidPair.add("named-uuid");
232                 portUuidPair.add(newPort);
233
234                 List<Object> mutation = new ArrayList<Object>();
235                 mutation.add("ports");
236                 mutation.add("insert");
237                 mutation.add(portUuidPair);
238                 List<Object> mutations = new ArrayList<Object>();
239                 mutations.add(mutation);
240
241                 List<String> bridgeUuidPair = new ArrayList<String>();
242                 bridgeUuidPair.add("uuid");
243                 bridgeUuidPair.add(bridge.getUuid());
244
245                 List<Object> whereInner = new ArrayList<Object>();
246                 whereInner.add("_uuid");
247                 whereInner.add("==");
248                 whereInner.add(bridgeUuidPair);
249
250                 List<Object> where = new ArrayList<Object>();
251                 where.add(whereInner);
252
253                 MutateRequest mutateBridgeRequest = new MutateRequest("Bridge", where, mutations);
254
255                 Map<String, Object> portRow = new HashMap<String, Object>();
256                 portRow.put("name", portIdentifier);
257                 String portType = null;
258                 if (configs != null) {
259                     portType = (String)configs.get(ConfigConstants.TYPE);
260                     if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
261                         try {
262                         portRow.put("tag", Integer.parseInt((String)configs.get(ConfigConstants.VLAN)));
263                         } catch (Exception e) {
264                         }
265                     }
266                 }
267                 ArrayList<String> interfaces = new ArrayList<String>();
268                 interfaces.add("named-uuid");
269                 interfaces.add(newInterface);
270                 portRow.put("interfaces", interfaces);
271                 InsertRequest addPortRequest = new InsertRequest("insert", "Port", newPort, portRow);
272
273                 Map<String, Object> interfaceRow = new HashMap<String, Object>();
274                 interfaceRow.put("name", portIdentifier);
275                 //Tunnel specific
276
277                 if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
278                     interfaceRow.put("type", configs.get(ConfigConstants.TUNNEL_TYPE));
279                     ArrayList<Object> intopt = new ArrayList<Object>();
280                     interfaceRow.put("options", intopt);
281                     ArrayList<Object> intoptmap = new ArrayList<Object>();
282                     ArrayList<String> intoptep = new ArrayList<String>();
283                     intopt.add("map");
284                     intopt.add(intoptmap);
285                     intoptmap.add(intoptep);
286                     intoptep.add("remote_ip");
287                     intoptep.add((String)configs.get(ConfigConstants.DEST_IP));
288                 }
289                 InsertRequest addIntfRequest = new InsertRequest("insert", "Interface", newInterface, interfaceRow);
290
291                 Object[] params = {"Open_vSwitch", mutateBridgeRequest, addIntfRequest, addPortRequest};
292                 OvsdbMessage msg = new OvsdbMessage("transact", params);
293
294                 connection.sendMessage(msg);
295             }
296         }catch(Exception e){
297             e.printStackTrace();
298         }
299         return new Status(StatusCode.SUCCESS);
300     }
301     /**
302      * Implements the OVS Connection for Managers
303      *
304      * @param node Node serving this configuration service
305      * @param String with IP and connection types
306      */
307     @SuppressWarnings("unchecked")
308     public boolean setManager(Node node, String managerip) throws Throwable{
309         try{
310             if (connectionService == null) {
311                 logger.error("Couldn't refer to the ConnectionService");
312                 return false;
313             }
314             Connection connection = this.getConnection(node);
315             if (connection == null || connection.getSocket() == null) {
316                 return false;
317             }
318
319             if (connection != null) {
320                 String newmanager = "new_manager";
321
322                 OVSInstance instance = OVSInstance.monitorOVS(connection);
323
324                 Map ovsoutter = new LinkedHashMap();
325                 Map ovsinner = new LinkedHashMap();
326                 ArrayList ovsalist1 = new ArrayList();
327                 ArrayList ovsalist2 = new ArrayList();
328                 ArrayList ovsalist3 = new ArrayList();
329                 ArrayList ovsalist4 = new ArrayList();
330
331                 //OVS Table Update
332                 ovsoutter.put("where", ovsalist1);
333                 ovsalist1.add(ovsalist2);
334                 ovsalist2.add("_uuid");
335                 ovsalist2.add("==");
336                 ovsalist2.add(ovsalist3);
337                 ovsalist3.add("uuid");
338                 ovsalist3.add(instance.getUuid());
339                 ovsoutter.put("op", "update");
340                 ovsoutter.put("table", "Open_vSwitch");
341                 ovsoutter.put("row", ovsinner);
342                 ovsinner.put("manager_options", ovsalist4);
343                 ovsalist4.add("named-uuid");
344                 ovsalist4.add(newmanager);
345
346                 Map mgroutside = new LinkedHashMap();
347                 Map mgrinside = new LinkedHashMap();
348
349                 //Manager Table Insert
350                 mgroutside.put("uuid-name", newmanager);
351                 mgroutside.put("op", "insert");
352                 mgroutside.put("table","Manager");
353                 mgroutside.put("row", mgrinside);
354                 mgrinside.put("target", managerip);
355
356                 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
357                 OvsdbMessage msg = new OvsdbMessage("transact", params);
358
359                 connection.sendMessage(msg);
360
361             }
362         }catch(Exception e){
363             e.printStackTrace();
364         }
365         return true;
366     }
367
368     @Override
369     public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
370             Map<ConfigConstants, Object> configs) {
371         String mgmt = (String)configs.get(ConfigConstants.MGMT);
372         if (mgmt != null) {
373             try {
374                 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
375             } catch (Throwable e) {
376                 // TODO Auto-generated catch block
377                 e.printStackTrace();
378                 return new Status(StatusCode.INTERNALERROR);
379             }
380         }
381         return new Status(StatusCode.BADREQUEST);
382     }
383
384     @Override
385     public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
386             Map<ConfigConstants, Object> configs) {
387         // TODO Auto-generated method stub
388         return null;
389     }
390
391     @Override
392     public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
393         // TODO Auto-generated method stub
394         return null;
395     }
396
397     @Override
398     public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
399         // TODO Auto-generated method stub
400         return null;
401     }
402
403     @Override
404     public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
405             String portIdentifier) {
406         // TODO Auto-generated method stub
407         return null;
408     }
409
410     @Override
411     public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
412             Map<ConfigConstants, Object> configs) {
413         // TODO Auto-generated method stub
414         return null;
415     }
416
417     @Override
418     public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
419             Map<ConfigConstants, Object> configs) {
420         // TODO Auto-generated method stub
421         return null;
422     }
423
424     @Override
425     public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
426         // TODO Auto-generated method stub
427         return null;
428     }
429
430     @Override
431     public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
432         // TODO Auto-generated method stub
433         return null;
434     }
435
436     @Override
437     public List<String> getBridgeDomains(Node node) {
438
439         Connection connection = connectionService.getConnection(node);
440         Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
441         List<String> bridgeDomains = new ArrayList<String>(existingBridges.keySet());
442         return bridgeDomains;
443     }
444
445     @Override
446     public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
447         return null;
448     }
449
450     public void _ovsconnect (CommandInterpreter ci) {
451         String bridgeName = ci.nextArgument();
452         if (bridgeName == null) {
453             ci.println("Please enter Bridge Name");
454             return;
455         }
456
457         String ovsdbserver = ci.nextArgument();
458         if (ovsdbserver == null) {
459             ci.println("Please enter valid IP-Address");
460             return;
461         }
462         try {
463             InetAddress.getByName(ovsdbserver);
464         }  catch (Exception e) {
465             e.printStackTrace();
466             ci.println("Please enter valid IP-Address");
467             return;
468         }
469         String port = ci.nextArgument();
470         if (port == null) {
471             port = "6634";
472         }
473
474         ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
475         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
476         params.put(ConnectionConstants.ADDRESS, ovsdbserver);
477         params.put(ConnectionConstants.PORT, port);
478         Node node = connectionService.connect(bridgeName, params);
479         if (node != null) ci.println("Node Name: "+node.toString());
480         else ci.println("Could not connect to Node");
481     }
482
483     public void _addBridge (CommandInterpreter ci) {
484         String nodeName = ci.nextArgument();
485         if (nodeName == null) {
486             ci.println("Please enter Node Name");
487             return;
488         }
489
490         String bridgeName = ci.nextArgument();
491         if (bridgeName == null) {
492             ci.println("Please enter Bridge Name");
493             return;
494         }
495         Status status;
496         try {
497             status = this.createBridgeDomain(Node.fromString(nodeName), bridgeName, null);
498             ci.println("Bridge creation status : "+status.toString());
499         } catch (Throwable e) {
500             // TODO Auto-generated catch block
501             e.printStackTrace();
502             ci.println("Failed to create Bridge "+bridgeName);
503         }
504     }
505
506     public void _addPort (CommandInterpreter ci) {
507         String nodeName = ci.nextArgument();
508         if (nodeName == null) {
509             ci.println("Please enter Node Name");
510             return;
511         }
512
513         String bridgeName = ci.nextArgument();
514         if (bridgeName == null) {
515             ci.println("Please enter Bridge Name");
516             return;
517         }
518
519         String portName = ci.nextArgument();
520         if (portName == null) {
521             ci.println("Please enter Port Name");
522             return;
523         }
524
525         Status status;
526         try {
527             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, null);
528             ci.println("Port creation status : "+status.toString());
529         } catch (Throwable e) {
530             // TODO Auto-generated catch block
531             e.printStackTrace();
532             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
533         }
534     }
535
536     public void _addPortVlan (CommandInterpreter ci) {
537         String nodeName = ci.nextArgument();
538         if (nodeName == null) {
539             ci.println("Please enter Node Name");
540             return;
541         }
542
543         String bridgeName = ci.nextArgument();
544         if (bridgeName == null) {
545             ci.println("Please enter Bridge Name");
546             return;
547         }
548
549         String portName = ci.nextArgument();
550         if (portName == null) {
551             ci.println("Please enter Port Name");
552             return;
553         }
554
555         String vlan = ci.nextArgument();
556         if (vlan == null) {
557             ci.println("Please enter Valid Vlan");
558             return;
559         } else {
560             try {
561             Integer.parseInt(vlan);
562             } catch (Exception e) {
563                 ci.println("Please enter Valid Vlan");
564                 return;
565             }
566         }
567
568         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
569         configs.put(ConfigConstants.TYPE, "VLAN");
570         configs.put(ConfigConstants.VLAN, vlan);
571
572         Status status;
573         try {
574             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
575             ci.println("Port creation status : "+status.toString());
576         } catch (Throwable e) {
577             // TODO Auto-generated catch block
578             e.printStackTrace();
579             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
580         }
581     }
582
583     public void _addTunnel (CommandInterpreter ci) {
584         String nodeName = ci.nextArgument();
585         if (nodeName == null) {
586             ci.println("Please enter Node Name");
587             return;
588         }
589
590         String bridgeName = ci.nextArgument();
591         if (bridgeName == null) {
592             ci.println("Please enter Bridge Name");
593             return;
594         }
595
596         String portName = ci.nextArgument();
597         if (portName == null) {
598             ci.println("Please enter Port Name");
599             return;
600         }
601
602         String tunnelType = ci.nextArgument();
603         if (tunnelType == null) {
604             ci.println("Please enter Tunnel Type");
605             return;
606         }
607
608         String remoteIp = ci.nextArgument();
609         if (remoteIp == null) {
610             ci.println("Please enter valid Remote IP Address");
611             return;
612         }
613
614         try {
615             InetAddress.getByName(remoteIp);
616         }  catch (Exception e) {
617             e.printStackTrace();
618             ci.println("Please enter valid Remote IP Address");
619             return;
620         }
621
622         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
623         configs.put(ConfigConstants.TYPE, "TUNNEL");
624         configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
625         configs.put(ConfigConstants.DEST_IP, remoteIp);
626
627         Status status;
628         try {
629             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
630             ci.println("Port creation status : "+status.toString());
631         } catch (Throwable e) {
632             // TODO Auto-generated catch block
633             e.printStackTrace();
634             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
635         }
636     }
637
638     public void _forceConnect (CommandInterpreter ci) {
639         String force = ci.nextArgument();
640         if (force.equalsIgnoreCase("YES")) forceConnect = true;
641         else if (force.equalsIgnoreCase("NO")) forceConnect = false;
642         else ci.println("Please enter YES or NO.");
643         ci.println("Current ForceConnect State : "+forceConnect);
644         return;
645     }
646
647     @Override
648     public String getHelp() {
649         StringBuffer help = new StringBuffer();
650         help.append("---OVSDB CLI---\n");
651         help.append("\t ovsconnect <ConnectionName> <ip-address>                        - Connect to OVSDB\n");
652         help.append("\t addBridge <Node> <BridgeName>                                   - Add Bridge\n");
653         help.append("\t addPort <Node> <BridgeName> <PortName>                          - Add Port\n");
654         help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan>               - Add Port, Vlan\n");
655         help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip>      - Add Tunnel\n");
656         help.append("\t forceConnect <yes|no>   - Force a new OVSDB Connection for every command (Workaround)");
657         return help.toString();
658     }
659 }