Update the config version of teh ovsdb when adding a bridge
[netvirt.git] / ovsdb / src / main / java / org / opendaylight / ovsdb / plugin / ConfigurationService.java
1 package org.opendaylight.ovsdb.plugin;
2
3 import java.math.BigInteger;
4 import java.net.InetAddress;
5 import java.net.NetworkInterface;
6 import java.net.SocketException;
7 import java.util.*;
8
9 import org.eclipse.osgi.framework.console.CommandInterpreter;
10 import org.eclipse.osgi.framework.console.CommandProvider;
11 import org.opendaylight.ovsdb.lib.database.OVSBridge;
12 import org.opendaylight.ovsdb.lib.database.OVSInstance;
13 import org.opendaylight.ovsdb.lib.database.OvsdbType;
14 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
15 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
16 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
17 import org.opendaylight.ovsdb.lib.message.operations.Operation;
18 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
19 import org.opendaylight.ovsdb.lib.notation.Condition;
20 import org.opendaylight.ovsdb.lib.notation.Function;
21 import org.opendaylight.ovsdb.lib.notation.Mutation;
22 import org.opendaylight.ovsdb.lib.notation.Mutator;
23 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
24 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.table.Bridge;
27 import org.opendaylight.ovsdb.lib.table.Controller;
28 import org.opendaylight.ovsdb.lib.table.Interface;
29 import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
30 import org.opendaylight.ovsdb.lib.table.Port;
31 import org.opendaylight.ovsdb.lib.table.internal.Table;
32 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
33 import org.opendaylight.controller.sal.connection.ConnectionConstants;
34 import org.opendaylight.controller.sal.core.Node;
35 import org.opendaylight.controller.sal.core.NodeConnector;
36 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
37 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
38 import org.opendaylight.controller.sal.utils.NetUtils;
39 import org.opendaylight.controller.sal.utils.Status;
40 import org.opendaylight.controller.sal.utils.StatusCode;
41 import org.osgi.framework.BundleContext;
42 import org.osgi.framework.FrameworkUtil;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import com.google.common.util.concurrent.ListenableFuture;
47
48 public class ConfigurationService implements IPluginInBridgeDomainConfigService, CommandProvider
49 {
50     private static final Logger logger = LoggerFactory
51             .getLogger(ConfigurationService.class);
52
53     IConnectionServiceInternal connectionService;
54     InventoryServiceInternal inventoryServiceInternal;
55     private IClusterGlobalServices clusterServices;
56     boolean forceConnect = false;
57
58     void init() {
59     }
60
61     /**
62      * Function called by the dependency manager when at least one dependency
63      * become unsatisfied or when the component is shutting down because for
64      * example bundle is being stopped.
65      *
66      */
67     void destroy() {
68     }
69
70     /**
71      * Function called by dependency manager after "init ()" is called and after
72      * the services provided by the class are registered in the service registry
73      *
74      */
75     void start() {
76         registerWithOSGIConsole();
77     }
78
79     private void registerWithOSGIConsole() {
80         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
81                 .getBundleContext();
82         bundleContext.registerService(CommandProvider.class.getName(), this,
83                 null);
84     }
85
86     /**
87      * Function called by the dependency manager before the services exported by
88      * the component are unregistered, this will be followed by a "destroy ()"
89      * calls
90      *
91      */
92     void stop() {
93     }
94
95     public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
96         this.connectionService = connectionService;
97     }
98
99     public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
100         if (this.connectionService == connectionService) {
101             this.connectionService = null;
102         }
103     }
104
105     public void setInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
106         this.inventoryServiceInternal = inventoryServiceInternal;
107     }
108
109     public void unsetInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
110         if (this.inventoryServiceInternal == inventoryServiceInternal) {
111             this.inventoryServiceInternal = null;
112         }
113     }
114
115     public void setClusterServices(IClusterGlobalServices i) {
116         this.clusterServices = i;
117     }
118
119     public void unsetClusterServices(IClusterGlobalServices i) {
120         if (this.clusterServices == i) {
121             this.clusterServices = null;
122         }
123     }
124
125     private Connection getConnection (Node node) {
126         Connection connection = connectionService.getConnection(node);
127         if (connection == null || !connection.getChannel().isActive()) {
128             return null;
129         }
130
131         return connection;
132     }
133
134     /**
135      * Add a new bridge
136      * @param node Node serving this configuration service
137      * @param bridgeConnectorIdentifier String representation of a Bridge Connector
138      * @return Bridge Connector configurations
139      */
140     @Override
141     public Status createBridgeDomain(Node node, String bridgeIdentifier,
142             Map<ConfigConstants, Object> configs) throws Throwable {
143         try{
144             if (connectionService == null) {
145                 logger.error("Couldn't refer to the ConnectionService");
146                 return new Status(StatusCode.NOSERVICE);
147             }
148
149             Connection connection = this.getConnection(node);
150             if (connection == null) {
151                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
152             }
153
154             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
155             String newBridge = "new_bridge";
156             String newInterface = "new_interface";
157             String newPort = "new_port";
158             String newSwitch = "new_switch";
159
160             Operation addSwitchRequest = null;
161
162             if(ovsTable != null){
163                 String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
164                 UUID bridgeUuidPair = new UUID(newBridge);
165                 Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuidPair);
166                 List<Mutation> mutations = new ArrayList<Mutation>();
167                 mutations.add(bm);
168
169                 UUID uuid = new UUID(ovsTableUUID);
170                 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
171                 List<Condition> where = new ArrayList<Condition>();
172                 where.add(condition);
173                 addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
174             }
175             else{
176                 Open_vSwitch ovsTableRow = new Open_vSwitch();
177                 OvsDBSet<UUID> bridges = new OvsDBSet<UUID>();
178                 UUID bridgeUuidPair = new UUID(newBridge);
179                 bridges.add(bridgeUuidPair);
180                 ovsTableRow.setBridges(bridges);
181                 addSwitchRequest = new InsertOperation(Open_vSwitch.NAME.getName(), newSwitch, ovsTableRow);
182             }
183
184             Bridge bridgeRow = new Bridge();
185             bridgeRow.setName(bridgeIdentifier);
186             OvsDBSet<UUID> ports = new OvsDBSet<UUID>();
187             UUID port = new UUID(newPort);
188             ports.add(port);
189             bridgeRow.setPorts(ports);
190             InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
191
192             Port portRow = new Port();
193             portRow.setName(bridgeIdentifier);
194             OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
195             UUID interfaceid = new UUID(newInterface);
196             interfaces.add(interfaceid);
197             portRow.setInterfaces(interfaces);
198             InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
199
200             Interface interfaceRow = new Interface();
201             interfaceRow.setName(bridgeIdentifier);
202             interfaceRow.setType("internal");
203             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(), newInterface, interfaceRow);
204
205             /* Update config version */
206             String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
207             Mutation bm = new Mutation("next_cfg", Mutator.SUM, 1);
208             List<Mutation> mutations = new ArrayList<Mutation>();
209             mutations.add(bm);
210
211             UUID uuid = new UUID(ovsTableUUID);
212             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
213             List<Condition> where = new ArrayList<Condition>();
214             where.add(condition);
215             MutateOperation updateCfgVerRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
216
217             TransactBuilder transaction = new TransactBuilder();
218             transaction.addOperations(new ArrayList<Operation>(
219                                       Arrays.asList(addSwitchRequest, addIntfRequest, addPortRequest, addBridgeRequest, updateCfgVerRequest)));
220
221             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
222             List<OperationResult> tr = transResponse.get();
223             List<Operation> requests = transaction.getRequests();
224             Status status = new Status(StatusCode.SUCCESS);
225             for (int i = 0; i < tr.size() ; i++) {
226                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
227                 if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
228                     OperationResult result = tr.get(i);
229                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
230                 }
231             }
232
233             if (tr.size() > requests.size()) {
234                 OperationResult result = tr.get(tr.size()-1);
235                 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
236                                                                                        result.getError(),
237                                                                                        result.getDetails());
238                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
239             }
240             if (status.isSuccess()) {
241                 setBridgeOFController(node, bridgeIdentifier);
242             }
243             return status;
244         } catch(Exception e){
245             e.printStackTrace();
246         }
247         return new Status(StatusCode.INTERNALERROR);
248     }
249
250     /**
251      * Create a Port Attached to a Bridge
252      * Ex. ovs-vsctl add-port br0 vif0
253      * @param node Node serving this configuration service
254      * @param bridgeDomainIdentifier String representation of a Bridge Domain
255      * @param portIdentifier String representation of a user defined Port Name
256      */
257     @Override
258     public Status addPort(Node node, String bridgeIdentifier, String portIdentifier,
259                           Map<ConfigConstants, Object> configs) {
260         try{
261             if (connectionService == null) {
262                 logger.error("Couldn't refer to the ConnectionService");
263                 return new Status(StatusCode.NOSERVICE);
264             }
265             Connection connection = this.getConnection(node);
266             if (connection == null) {
267                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
268             }
269             if (connection != null) {
270                 Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
271                 String newBridge = "new_bridge";
272                 String newInterface = "new_interface";
273                 String newPort = "new_port";
274
275                 if(brTable != null){
276                     Operation addBrMutRequest = null;
277                     String brUuid = null;
278                     for (String uuid : brTable.keySet()) {
279                         Bridge bridge = (Bridge) brTable.get(uuid);
280                         if (bridge.getName().contains(bridgeIdentifier)) {
281                             brUuid = uuid;
282                         }
283                     }
284
285                     UUID brUuidPair = new UUID(newPort);
286                     Mutation bm = new Mutation("ports", Mutator.INSERT, brUuidPair);
287                     List<Mutation> mutations = new ArrayList<Mutation>();
288                     mutations.add(bm);
289
290                     UUID uuid = new UUID(brUuid);
291                     Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
292                     List<Condition> where = new ArrayList<Condition>();
293                     where.add(condition);
294                     addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
295
296                     OvsDBMap<String, String> options = null;
297                     String type = null;
298                     OvsDBSet<BigInteger> tags = null;
299                     if (configs != null) {
300                         type = (String) configs.get(ConfigConstants.TYPE);
301                         Map<String, String> customConfigs = (Map<String, String>) configs.get(ConfigConstants.CUSTOM);
302                         if (customConfigs != null) {
303                             options = new OvsDBMap<String, String>();
304                             for (String customConfig : customConfigs.keySet()) {
305                                 options.put(customConfig, customConfigs.get(customConfig));
306                             }
307                         }
308                     }
309
310                     Interface interfaceRow = new Interface();
311                     interfaceRow.setName(portIdentifier);
312
313                     if (type != null) {
314                         if (type.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
315                             interfaceRow.setType((String)configs.get(ConfigConstants.TUNNEL_TYPE));
316                             if (options == null) options = new OvsDBMap<String, String>();
317                             options.put("remote_ip", (String)configs.get(ConfigConstants.DEST_IP));
318                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
319                             tags = new OvsDBSet<BigInteger>();
320                             tags.add(BigInteger.valueOf(Integer.parseInt((String)configs.get(ConfigConstants.VLAN))));
321                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.PATCH.name())) {
322                             interfaceRow.setType(type.toLowerCase());
323                         }
324                     }
325                     if (options != null) {
326                         interfaceRow.setOptions(options);
327                     }
328
329                     InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
330                             newInterface, interfaceRow);
331
332                     Port portRow = new Port();
333                     portRow.setName(portIdentifier);
334                     if (tags != null) portRow.setTag(tags);
335                     OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
336                     UUID interfaceid = new UUID(newInterface);
337                     interfaces.add(interfaceid);
338                     portRow.setInterfaces(interfaces);
339                     InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
340
341                     TransactBuilder transaction = new TransactBuilder();
342                     transaction.addOperations(new ArrayList<Operation>
343                             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
344
345                     ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
346                     List<OperationResult> tr = transResponse.get();
347                     List<Operation> requests = transaction.getRequests();
348                     Status status = new Status(StatusCode.SUCCESS);
349                     for (int i = 0; i < tr.size() ; i++) {
350                         if (i < requests.size()) requests.get(i).setResult(tr.get(i));
351                         if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
352                             OperationResult result = tr.get(i);
353                             status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
354                         }
355                     }
356
357                     if (tr.size() > requests.size()) {
358                         OperationResult result = tr.get(tr.size()-1);
359                         logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
360                                 result.getError(),
361                                 result.getDetails());
362                         status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
363                     }
364                     return status;
365                 }
366                 return new Status(StatusCode.INTERNALERROR);
367             }
368         } catch(Exception e){
369             e.printStackTrace();
370         }
371         return new Status(StatusCode.INTERNALERROR);
372     }
373
374     /**
375      * Implements the OVS Connection for Managers
376      *
377      * @param node Node serving this configuration service
378      * @param String with IP and connection types
379      */
380     @SuppressWarnings("unchecked")
381     public boolean setManager(Node node, String managerip) throws Throwable{
382         try{
383             if (connectionService == null) {
384                 logger.error("Couldn't refer to the ConnectionService");
385                 return false;
386             }
387             Connection connection = this.getConnection(node);
388             if (connection == null) {
389                 return false;
390             }
391
392             if (connection != null) {
393                 String newmanager = "new_manager";
394
395                 OVSInstance instance = OVSInstance.monitorOVS(connection);
396
397                 Map ovsoutter = new LinkedHashMap();
398                 Map ovsinner = new LinkedHashMap();
399                 ArrayList ovsalist1 = new ArrayList();
400                 ArrayList ovsalist2 = new ArrayList();
401                 ArrayList ovsalist3 = new ArrayList();
402                 ArrayList ovsalist4 = new ArrayList();
403
404                 //OVS Table Update
405                 ovsoutter.put("where", ovsalist1);
406                 ovsalist1.add(ovsalist2);
407                 ovsalist2.add("_uuid");
408                 ovsalist2.add("==");
409                 ovsalist2.add(ovsalist3);
410                 ovsalist3.add("uuid");
411                 ovsalist3.add(instance.getUuid());
412                 ovsoutter.put("op", "update");
413                 ovsoutter.put("table", "Open_vSwitch");
414                 ovsoutter.put("row", ovsinner);
415                 ovsinner.put("manager_options", ovsalist4);
416                 ovsalist4.add("named-uuid");
417                 ovsalist4.add(newmanager);
418
419                 Map mgroutside = new LinkedHashMap();
420                 Map mgrinside = new LinkedHashMap();
421
422                 //Manager Table Insert
423                 mgroutside.put("uuid-name", newmanager);
424                 mgroutside.put("op", "insert");
425                 mgroutside.put("table","Manager");
426                 mgroutside.put("row", mgrinside);
427                 mgrinside.put("target", managerip);
428
429                 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
430                 OvsdbMessage msg = new OvsdbMessage("transact", params);
431
432                 //connection.sendMessage(msg);
433
434             }
435         }catch(Exception e){
436             e.printStackTrace();
437         }
438         return true;
439     }
440
441     @Override
442     public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
443             Map<ConfigConstants, Object> configs) {
444         String mgmt = (String)configs.get(ConfigConstants.MGMT);
445         if (mgmt != null) {
446             try {
447                 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
448             } catch (Throwable e) {
449                 // TODO Auto-generated catch block
450                 e.printStackTrace();
451                 return new Status(StatusCode.INTERNALERROR);
452             }
453         }
454         return new Status(StatusCode.BADREQUEST);
455     }
456
457     @Override
458     public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
459             Map<ConfigConstants, Object> configs) {
460         // TODO Auto-generated method stub
461         return null;
462     }
463
464     @Override
465     public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
466
467         try{
468             if (connectionService == null) {
469                 logger.error("Couldn't refer to the ConnectionService");
470                 return new Status(StatusCode.NOSERVICE);
471             }
472
473             Connection connection = this.getConnection(node);
474             if (connection == null) {
475                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
476             }
477
478             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
479             Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
480             Operation delPortRequest = null;
481             String brUuid = null;
482             String portUuid = null;
483             if(brTable != null){
484                 for (String uuid : brTable.keySet()) {
485                     Bridge bridge = (Bridge) brTable.get(uuid);
486                     if (bridge.getName().contains(bridgeIdentifier)) {
487                         brUuid = uuid;
488                     }
489                 }
490             }
491             if(portTable != null){
492                 for (String uuid : portTable.keySet()) {
493                     Port port = (Port) portTable.get(uuid);
494                     if (port.getName().contains(portIdentifier)) {
495                         portUuid = uuid;
496                     }
497                 }
498             }
499
500             UUID portUuidPair = new UUID(portUuid);
501             Mutation bm = new Mutation("ports", Mutator.DELETE, portUuidPair);
502             List<Mutation> mutations = new ArrayList<Mutation>();
503             mutations.add(bm);
504
505             UUID uuid = new UUID(brUuid);
506             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
507             List<Condition> where = new ArrayList<Condition>();
508             where.add(condition);
509             delPortRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
510
511             TransactBuilder transaction = new TransactBuilder();
512             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delPortRequest)));
513
514             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
515             List<OperationResult> tr = transResponse.get();
516             List<Operation> requests = transaction.getRequests();
517             Status status = new Status(StatusCode.SUCCESS);
518             for (int i = 0; i < tr.size() ; i++) {
519                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
520                 if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
521                     OperationResult result = tr.get(i);
522                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
523                 }
524             }
525
526             if (tr.size() > requests.size()) {
527                 OperationResult result = tr.get(tr.size()-1);
528                 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
529                         result.getError(),
530                         result.getDetails());
531                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
532             }
533             return status;
534         } catch(Exception e){
535             e.printStackTrace();
536         }
537         return new Status(StatusCode.INTERNALERROR);
538     }
539
540     @Override
541     public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
542         // TODO Auto-generated method stub
543         return null;
544     }
545
546     @Override
547     public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
548             String portIdentifier) {
549         // TODO Auto-generated method stub
550         return null;
551     }
552
553     @Override
554     public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
555             Map<ConfigConstants, Object> configs) {
556         // TODO Auto-generated method stub
557         return null;
558     }
559
560     @Override
561     public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
562             Map<ConfigConstants, Object> configs) {
563         // TODO Auto-generated method stub
564         return null;
565     }
566
567     @Override
568     public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
569         // TODO Auto-generated method stub
570         return null;
571     }
572
573     @Override
574     public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
575         // TODO Auto-generated method stub
576         return null;
577     }
578
579     @Override
580     public List<String> getBridgeDomains(Node node) {
581         List<String> brlist = new ArrayList<String>();
582         Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
583         if(brTableCache != null){
584             for (String uuid : brTableCache.keySet()) {
585                 Bridge bridge = (Bridge) brTableCache.get(uuid);
586                 brlist.add(bridge.getName());
587             }
588         }
589         return brlist;
590     }
591
592     @Override
593     public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
594         return null;
595     }
596
597     private short getControllerOFPort() {
598         Short defaultOpenFlowPort = 6633;
599         Short openFlowPort = defaultOpenFlowPort;
600         String portString = System.getProperty("of.listenPort");
601         if (portString != null) {
602             try {
603                 openFlowPort = Short.decode(portString).shortValue();
604             } catch (NumberFormatException e) {
605                 logger.warn("Invalid port:{}, use default({})", portString,
606                         openFlowPort);
607             }
608         }
609         return openFlowPort;
610     }
611
612     private List<InetAddress> getControllerIPAddresses() {
613         List<InetAddress> controllers = null;
614         if (clusterServices != null) {
615             controllers = clusterServices.getClusteredControllers();
616             if (controllers != null && controllers.size() > 0) {
617                 if (controllers.size() == 1) {
618                     InetAddress controller = controllers.get(0);
619                     if (!controller.equals(InetAddress.getLoopbackAddress())) {
620                         return controllers;
621                     }
622                 } else {
623                     return controllers;
624                 }
625             }
626         }
627
628         controllers = new ArrayList<InetAddress>();
629         InetAddress controllerIP;
630         Enumeration<NetworkInterface> nets;
631         try {
632             nets = NetworkInterface.getNetworkInterfaces();
633             for (NetworkInterface netint : Collections.list(nets)) {
634                 Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
635                 for (InetAddress inetAddress : Collections.list(inetAddresses)) {
636                     if (!inetAddress.isLoopbackAddress() &&
637                             NetUtils.isIPv4AddressValid(inetAddress.getHostAddress())) {
638                         controllers.add(inetAddress);
639                     }
640                 }
641             }
642         } catch (SocketException e) {
643             controllers.add(InetAddress.getLoopbackAddress());
644         }
645         return controllers;
646     }
647
648     public Boolean setBridgeOFController(Node node, String bridgeIdentifier) {
649         try{
650             if (connectionService == null) {
651                 logger.error("Couldn't refer to the ConnectionService");
652                 return false;
653             }
654             Connection connection = this.getConnection(node);
655             if (connection == null) {
656                 return false;
657             }
658
659             if (connection != null) {
660                 List<InetAddress> ofControllerAddrs = getControllerIPAddresses();
661                 short ofControllerPort = getControllerOFPort();
662                 OvsDBSet<UUID> controllerUUIDs = new OvsDBSet<UUID>();
663                 List<Operation> controllerInsertOperations = new ArrayList<Operation>();
664                 Map<String, Table<?>> controllerCache = inventoryServiceInternal.getTableCache(node, Controller.NAME.getName());
665
666                 int count = 0;
667                 for (InetAddress ofControllerAddress : ofControllerAddrs) {
668                     String cntrlUuid = null;
669                     String newController = "tcp:"+ofControllerAddress.getHostAddress()+":"+ofControllerPort;
670                     if (controllerCache != null) {
671                         for (String uuid : controllerCache.keySet()) {
672                             Controller controller = (Controller)controllerCache.get(uuid);
673                             if (controller.getTarget().equals(newController)) {
674                                 cntrlUuid = uuid;
675                                 controllerUUIDs.add(new UUID(uuid));
676                                 break;
677                             }
678                         }
679                     }
680                     if (cntrlUuid == null) {
681                         count++;
682                         String uuid_name = "new_controller_"+count;
683                         controllerUUIDs.add(new UUID(uuid_name));
684                         Controller controllerRow = new Controller();
685                         controllerRow.setTarget(newController);
686                         InsertOperation addCtlRequest = new InsertOperation(Controller.NAME.getName(), uuid_name, controllerRow);
687                         controllerInsertOperations.add(addCtlRequest);
688                     }
689                 }
690                 String brCntrlUuid = null;
691                 Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
692                 for (String uuid : brTableCache.keySet()) {
693                     Bridge bridge = (Bridge)brTableCache.get(uuid);
694                     if (bridge.getName().contains(bridgeIdentifier)) {
695                         brCntrlUuid = uuid;
696                     }
697                 }
698                 Operation addControlRequest = null;
699                 Mutation bm = new Mutation("controller", Mutator.INSERT, controllerUUIDs);
700                 List<Mutation> mutations = new ArrayList<Mutation>();
701                 mutations.add(bm);
702
703                 UUID uuid = new UUID(brCntrlUuid);
704                 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
705                 List<Condition> where = new ArrayList<Condition>();
706                 where.add(condition);
707                 addControlRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
708
709                 TransactBuilder transaction = new TransactBuilder();
710                 transaction.addOperations(controllerInsertOperations);
711                 transaction.addOperation(addControlRequest);
712
713                 ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
714                 List<OperationResult> tr = transResponse.get();
715                 List<Operation> requests = transaction.getRequests();
716                 Status status = new Status(StatusCode.SUCCESS);
717                 for (int i = 0; i < tr.size() ; i++) {
718                     if (i < requests.size()) requests.get(i).setResult(tr.get(i));
719                     if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
720                         OperationResult result = tr.get(i);
721                         status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
722                     }
723                 }
724
725                 if (tr.size() > requests.size()) {
726                     OperationResult result = tr.get(tr.size()-1);
727                     logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
728                             result.getError(),
729                             result.getDetails());
730                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
731
732                 }
733             }
734         }catch(Exception e){
735             e.printStackTrace();
736         }
737         return true;
738     }
739
740     public void _ovsconnect (CommandInterpreter ci) {
741         String bridgeName = ci.nextArgument();
742         if (bridgeName == null) {
743             ci.println("Please enter Bridge Name");
744             return;
745         }
746
747         String ovsdbserver = ci.nextArgument();
748         if (ovsdbserver == null) {
749             ci.println("Please enter valid IP-Address");
750             return;
751         }
752         try {
753             InetAddress.getByName(ovsdbserver);
754         }  catch (Exception e) {
755             e.printStackTrace();
756             ci.println("Please enter valid IP-Address");
757             return;
758         }
759         String port = ci.nextArgument();
760         if (port == null) {
761             port = "6634";
762         }
763
764         ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
765         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
766         params.put(ConnectionConstants.ADDRESS, ovsdbserver);
767         params.put(ConnectionConstants.PORT, port);
768         Node node = connectionService.connect(bridgeName, params);
769         if (node != null) ci.println("Node Name: "+node.toString());
770         else ci.println("Could not connect to Node");
771     }
772
773     public void _addBridge (CommandInterpreter ci) {
774         String nodeName = ci.nextArgument();
775         if (nodeName == null) {
776             ci.println("Please enter Node Name");
777             return;
778         }
779
780         String bridgeName = ci.nextArgument();
781         if (bridgeName == null) {
782             ci.println("Please enter Bridge Name");
783             return;
784         }
785         Status status;
786         try {
787             status = this.createBridgeDomain(Node.fromString(nodeName), bridgeName, null);
788             ci.println("Bridge creation status : "+status.toString());
789         } catch (Throwable e) {
790             // TODO Auto-generated catch block
791             e.printStackTrace();
792             ci.println("Failed to create Bridge "+bridgeName);
793         }
794     }
795
796     public void _getBridgeDomains (CommandInterpreter ci) {
797         String nodeName = ci.nextArgument();
798         if (nodeName == null) {
799             ci.println("Please enter Node Name");
800             return;
801         }
802         Status status;
803         List<String> brlist = new ArrayList<String>();
804         try {
805             brlist = this.getBridgeDomains(Node.fromString(nodeName));
806             ci.println("Existing Bridges: "+brlist.toString());
807         } catch (Throwable e) {
808             e.printStackTrace();
809             ci.println("Failed to list Bridges");
810         }
811     }
812
813     public void _addPort (CommandInterpreter ci) {
814         String nodeName = ci.nextArgument();
815         if (nodeName == null) {
816             ci.println("Please enter Node Name");
817             return;
818         }
819
820         String bridgeName = ci.nextArgument();
821         if (bridgeName == null) {
822             ci.println("Please enter Bridge Name");
823             return;
824         }
825
826         String portName = ci.nextArgument();
827         if (portName == null) {
828             ci.println("Please enter Port Name");
829             return;
830         }
831
832         String type = ci.nextArgument();
833
834         Map<String, String> configs = new HashMap<String, String>();
835         while(true) {
836             String configKey = ci.nextArgument();
837             if (configKey == null) break;
838             String configValue = ci.nextArgument();
839             if (configValue == null) break;
840             configs.put(configKey, configValue);
841         }
842
843         Map<ConfigConstants, Object> customConfigs = null;
844         if (type != null) {
845             customConfigs = new HashMap<ConfigConstants, Object>();
846             customConfigs.put(ConfigConstants.TYPE, type);
847         }
848
849         if (configs.size() > 0) {
850             if (customConfigs == null) customConfigs = new HashMap<ConfigConstants, Object>();
851             customConfigs.put(ConfigConstants.CUSTOM, configs);
852             ci.println(customConfigs.toString());
853         }
854         Status status;
855         try {
856             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, customConfigs);
857             ci.println("Port creation status : "+status.toString());
858         } catch (Throwable e) {
859             // TODO Auto-generated catch block
860             e.printStackTrace();
861             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
862         }
863     }
864
865     public void _deletePort (CommandInterpreter ci) {
866         String nodeName = ci.nextArgument();
867         if (nodeName == null) {
868             ci.println("Please enter Node Name");
869             return;
870         }
871
872         String bridgeName = ci.nextArgument();
873         if (bridgeName == null) {
874             ci.println("Please enter Bridge Name");
875             return;
876         }
877
878         String portName = ci.nextArgument();
879         if (portName == null) {
880             ci.println("Please enter Port Name");
881             return;
882         }
883
884         Status status;
885         try {
886             status = this.deletePort(Node.fromString(nodeName), bridgeName, portName);
887             ci.println("Port deletion status : "+status.toString());
888         } catch (Throwable e) {
889             // TODO Auto-generated catch block
890             e.printStackTrace();
891             ci.println("Failed to delete Port "+portName+" in Bridge "+bridgeName);
892         }
893     }
894
895     public void _addPortVlan (CommandInterpreter ci) {
896         String nodeName = ci.nextArgument();
897         if (nodeName == null) {
898             ci.println("Please enter Node Name");
899             return;
900         }
901
902         String bridgeName = ci.nextArgument();
903         if (bridgeName == null) {
904             ci.println("Please enter Bridge Name");
905             return;
906         }
907
908         String portName = ci.nextArgument();
909         if (portName == null) {
910             ci.println("Please enter Port Name");
911             return;
912         }
913
914         String vlan = ci.nextArgument();
915         if (vlan == null) {
916             ci.println("Please enter Valid Vlan");
917             return;
918         } else {
919             try {
920             Integer.parseInt(vlan);
921             } catch (Exception e) {
922                 ci.println("Please enter Valid Vlan");
923                 return;
924             }
925         }
926
927         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
928         configs.put(ConfigConstants.TYPE, "VLAN");
929         configs.put(ConfigConstants.VLAN, vlan);
930
931         Status status;
932         try {
933             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
934             ci.println("Port creation status : "+status.toString());
935         } catch (Throwable e) {
936             // TODO Auto-generated catch block
937             e.printStackTrace();
938             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
939         }
940     }
941
942     public void _addTunnel (CommandInterpreter ci) {
943         String nodeName = ci.nextArgument();
944         if (nodeName == null) {
945             ci.println("Please enter Node Name");
946             return;
947         }
948
949         String bridgeName = ci.nextArgument();
950         if (bridgeName == null) {
951             ci.println("Please enter Bridge Name");
952             return;
953         }
954
955         String portName = ci.nextArgument();
956         if (portName == null) {
957             ci.println("Please enter Port Name");
958             return;
959         }
960
961         String tunnelType = ci.nextArgument();
962         if (tunnelType == null) {
963             ci.println("Please enter Tunnel Type");
964             return;
965         }
966
967         String remoteIp = ci.nextArgument();
968         if (remoteIp == null) {
969             ci.println("Please enter valid Remote IP Address");
970             return;
971         }
972
973         try {
974             InetAddress.getByName(remoteIp);
975         }  catch (Exception e) {
976             e.printStackTrace();
977             ci.println("Please enter valid Remote IP Address");
978             return;
979         }
980
981         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
982         configs.put(ConfigConstants.TYPE, "TUNNEL");
983         configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
984         configs.put(ConfigConstants.DEST_IP, remoteIp);
985
986         Status status;
987         try {
988             status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
989             ci.println("Port creation status : "+status.toString());
990         } catch (Throwable e) {
991             // TODO Auto-generated catch block
992             e.printStackTrace();
993             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
994         }
995     }
996
997     public void _printCache (CommandInterpreter ci) {
998         String nodeName = ci.nextArgument();
999         if (nodeName == null) {
1000             ci.println("Please enter Node Name");
1001             return;
1002         }
1003         inventoryServiceInternal.printCache(Node.fromString(nodeName));
1004     }
1005
1006     public void _forceConnect (CommandInterpreter ci) {
1007         String force = ci.nextArgument();
1008         if (force.equalsIgnoreCase("YES")) forceConnect = true;
1009         else if (force.equalsIgnoreCase("NO")) forceConnect = false;
1010         else ci.println("Please enter YES or NO.");
1011         ci.println("Current ForceConnect State : "+forceConnect);
1012         return;
1013     }
1014
1015     @Override
1016     public String getHelp() {
1017         StringBuffer help = new StringBuffer();
1018         help.append("---OVSDB CLI---\n");
1019         help.append("\t ovsconnect <ConnectionName> <ip-address>                        - Connect to OVSDB\n");
1020         help.append("\t addBridge <Node> <BridgeName>                                   - Add Bridge\n");
1021         help.append("\t getBridgeDomains                                                - Get Bridges\n");
1022         help.append("\t addPort <Node> <BridgeName> <PortName> <type> <options pairs>   - Add Port\n");
1023         help.append("\t delPort <Node> <BridgeName> <PortName>                          - Delete Port\n");
1024         help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan>               - Add Port, Vlan\n");
1025         help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip>      - Add Tunnel\n");
1026         help.append("\t printCache <Node>                                               - Prints Table Cache");
1027         return help.toString();
1028     }
1029 }