Modified the insertRow methods to return StatusWithUuid instead of Status
[ovsdb.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.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.LinkedHashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.eclipse.osgi.framework.console.CommandInterpreter;
13 import org.eclipse.osgi.framework.console.CommandProvider;
14 import org.opendaylight.controller.sal.connection.ConnectionConstants;
15 import org.opendaylight.controller.sal.core.Node;
16 import org.opendaylight.controller.sal.core.NodeConnector;
17 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
18 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
19 import org.opendaylight.controller.sal.utils.Status;
20 import org.opendaylight.controller.sal.utils.StatusCode;
21 import org.opendaylight.ovsdb.lib.database.OVSInstance;
22 import org.opendaylight.ovsdb.lib.database.OvsdbType;
23 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
24 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
25 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
26 import org.opendaylight.ovsdb.lib.message.operations.Operation;
27 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
28 import org.opendaylight.ovsdb.lib.message.operations.UpdateOperation;
29 import org.opendaylight.ovsdb.lib.notation.Condition;
30 import org.opendaylight.ovsdb.lib.notation.Function;
31 import org.opendaylight.ovsdb.lib.notation.Mutation;
32 import org.opendaylight.ovsdb.lib.notation.Mutator;
33 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
34 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
35 import org.opendaylight.ovsdb.lib.notation.UUID;
36 import org.opendaylight.ovsdb.lib.table.Bridge;
37 import org.opendaylight.ovsdb.lib.table.Capability;
38 import org.opendaylight.ovsdb.lib.table.Controller;
39 import org.opendaylight.ovsdb.lib.table.Interface;
40 import org.opendaylight.ovsdb.lib.table.Manager;
41 import org.opendaylight.ovsdb.lib.table.Mirror;
42 import org.opendaylight.ovsdb.lib.table.NetFlow;
43 import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
44 import org.opendaylight.ovsdb.lib.table.Port;
45 import org.opendaylight.ovsdb.lib.table.Qos;
46 import org.opendaylight.ovsdb.lib.table.Queue;
47 import org.opendaylight.ovsdb.lib.table.SFlow;
48 import org.opendaylight.ovsdb.lib.table.SSL;
49 import org.opendaylight.ovsdb.lib.table.internal.Table;
50 import org.osgi.framework.BundleContext;
51 import org.osgi.framework.FrameworkUtil;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 import com.fasterxml.jackson.databind.ObjectMapper;
56 import com.google.common.util.concurrent.ListenableFuture;
57
58 public class ConfigurationService implements IPluginInBridgeDomainConfigService, OVSDBConfigService,
59                                              CommandProvider
60 {
61     private static final Logger logger = LoggerFactory
62             .getLogger(ConfigurationService.class);
63
64     IConnectionServiceInternal connectionService;
65     InventoryServiceInternal inventoryServiceInternal;
66     boolean forceConnect = false;
67
68     void init() {
69     }
70
71     /**
72      * Function called by the dependency manager when at least one dependency
73      * become unsatisfied or when the component is shutting down because for
74      * example bundle is being stopped.
75      *
76      */
77     void destroy() {
78     }
79
80     /**
81      * Function called by dependency manager after "init ()" is called and after
82      * the services provided by the class are registered in the service registry
83      *
84      */
85     void start() {
86         registerWithOSGIConsole();
87     }
88
89     private void registerWithOSGIConsole() {
90         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
91                 .getBundleContext();
92         bundleContext.registerService(CommandProvider.class.getName(), this,
93                 null);
94     }
95
96     /**
97      * Function called by the dependency manager before the services exported by
98      * the component are unregistered, this will be followed by a "destroy ()"
99      * calls
100      *
101      */
102     void stop() {
103     }
104
105     public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
106         this.connectionService = connectionService;
107     }
108
109     public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
110         if (this.connectionService == connectionService) {
111             this.connectionService = null;
112         }
113     }
114
115     public void setInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
116         this.inventoryServiceInternal = inventoryServiceInternal;
117     }
118
119     public void unsetInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
120         if (this.inventoryServiceInternal == inventoryServiceInternal) {
121             this.inventoryServiceInternal = 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,
220                                                     addIntfRequest,
221                                                     addPortRequest,
222                                                     addBridgeRequest,
223                                                     updateCfgVerRequest)));
224
225             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
226             List<OperationResult> tr = transResponse.get();
227             List<Operation> requests = transaction.getRequests();
228             Status status = new Status(StatusCode.SUCCESS);
229             for (int i = 0; i < tr.size() ; i++) {
230                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
231                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
232                     OperationResult result = tr.get(i);
233                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
234                 }
235             }
236
237             if (tr.size() > requests.size()) {
238                 OperationResult result = tr.get(tr.size()-1);
239                 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
240                                                                                        result.getError(),
241                                                                                        result.getDetails());
242                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
243             }
244             if (status.isSuccess()) {
245                 setBridgeOFController(node, bridgeIdentifier);
246             }
247             return status;
248         } catch(Exception e){
249             logger.error("Error in createBridgeDomain(): ",e);
250         }
251         return new Status(StatusCode.INTERNALERROR);
252     }
253
254     /**
255      * Create a Port Attached to a Bridge
256      * Ex. ovs-vsctl add-port br0 vif0
257      * @param node Node serving this configuration service
258      * @param bridgeDomainIdentifier String representation of a Bridge Domain
259      * @param portIdentifier String representation of a user defined Port Name
260      */
261     @Override
262     public Status addPort(Node node, String bridgeIdentifier, String portIdentifier,
263                           Map<ConfigConstants, Object> configs) {
264         try{
265             if (connectionService == null) {
266                 logger.error("Couldn't refer to the ConnectionService");
267                 return new Status(StatusCode.NOSERVICE);
268             }
269             Connection connection = this.getConnection(node);
270             if (connection == null) {
271                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
272             }
273             if (connection != null) {
274                 Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
275                 String newBridge = "new_bridge";
276                 String newInterface = "new_interface";
277                 String newPort = "new_port";
278
279                 if(brTable != null){
280                     Operation addBrMutRequest = null;
281                     String brUuid = null;
282                     for (String uuid : brTable.keySet()) {
283                         Bridge bridge = (Bridge) brTable.get(uuid);
284                         if (bridge.getName().contains(bridgeIdentifier)) {
285                             brUuid = uuid;
286                         }
287                     }
288
289                     UUID brUuidPair = new UUID(newPort);
290                     Mutation bm = new Mutation("ports", Mutator.INSERT, brUuidPair);
291                     List<Mutation> mutations = new ArrayList<Mutation>();
292                     mutations.add(bm);
293
294                     UUID uuid = new UUID(brUuid);
295                     Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
296                     List<Condition> where = new ArrayList<Condition>();
297                     where.add(condition);
298                     addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
299
300                     OvsDBMap<String, String> options = null;
301                     String type = null;
302                     OvsDBSet<BigInteger> tags = null;
303                     if (configs != null) {
304                         type = (String) configs.get(ConfigConstants.TYPE);
305                         Map<String, String> customConfigs = (Map<String, String>) configs.get(ConfigConstants.CUSTOM);
306                         if (customConfigs != null) {
307                             options = new OvsDBMap<String, String>();
308                             for (String customConfig : customConfigs.keySet()) {
309                                 options.put(customConfig, customConfigs.get(customConfig));
310                             }
311                         }
312                     }
313
314                     Interface interfaceRow = new Interface();
315                     interfaceRow.setName(portIdentifier);
316
317                     if (type != null) {
318                         if (type.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
319                             interfaceRow.setType((String)configs.get(ConfigConstants.TUNNEL_TYPE));
320                             if (options == null) options = new OvsDBMap<String, String>();
321                             options.put("remote_ip", (String)configs.get(ConfigConstants.DEST_IP));
322                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
323                             tags = new OvsDBSet<BigInteger>();
324                             tags.add(BigInteger.valueOf(Integer.parseInt((String)configs.get(ConfigConstants.VLAN))));
325                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.PATCH.name())) {
326                             interfaceRow.setType(type.toLowerCase());
327                         }
328                     }
329                     if (options != null) {
330                         interfaceRow.setOptions(options);
331                     }
332
333                     InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
334                             newInterface, interfaceRow);
335
336                     Port portRow = new Port();
337                     portRow.setName(portIdentifier);
338                     if (tags != null) portRow.setTag(tags);
339                     OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
340                     UUID interfaceid = new UUID(newInterface);
341                     interfaces.add(interfaceid);
342                     portRow.setInterfaces(interfaces);
343                     InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
344
345                     TransactBuilder transaction = new TransactBuilder();
346                     transaction.addOperations(new ArrayList<Operation>
347                             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
348
349                     ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
350                     List<OperationResult> tr = transResponse.get();
351                     List<Operation> requests = transaction.getRequests();
352                     Status status = new Status(StatusCode.SUCCESS);
353                     for (int i = 0; i < tr.size() ; i++) {
354                         if (i < requests.size()) requests.get(i).setResult(tr.get(i));
355                         if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
356                             OperationResult result = tr.get(i);
357                             status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
358                         }
359                     }
360
361                     if (tr.size() > requests.size()) {
362                         OperationResult result = tr.get(tr.size()-1);
363                         logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
364                                 result.getError(),
365                                 result.getDetails());
366                         status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
367                     }
368                     return status;
369                 }
370                 return new Status(StatusCode.INTERNALERROR);
371             }
372         } catch(Exception e){
373             logger.error("Error in addPort()",e);
374         }
375         return new Status(StatusCode.INTERNALERROR);
376     }
377
378     /**
379      * Implements the OVS Connection for Managers
380      *
381      * @param node Node serving this configuration service
382      * @param String with IP and connection types
383      */
384     @SuppressWarnings("unchecked")
385     public boolean setManager(Node node, String managerip) throws Throwable{
386         try{
387             if (connectionService == null) {
388                 logger.error("Couldn't refer to the ConnectionService");
389                 return false;
390             }
391             Connection connection = this.getConnection(node);
392             if (connection == null) {
393                 return false;
394             }
395
396             if (connection != null) {
397                 String newmanager = "new_manager";
398
399                 OVSInstance instance = OVSInstance.monitorOVS(connection);
400
401                 Map ovsoutter = new LinkedHashMap();
402                 Map ovsinner = new LinkedHashMap();
403                 ArrayList ovsalist1 = new ArrayList();
404                 ArrayList ovsalist2 = new ArrayList();
405                 ArrayList ovsalist3 = new ArrayList();
406                 ArrayList ovsalist4 = new ArrayList();
407
408                 //OVS Table Update
409                 ovsoutter.put("where", ovsalist1);
410                 ovsalist1.add(ovsalist2);
411                 ovsalist2.add("_uuid");
412                 ovsalist2.add("==");
413                 ovsalist2.add(ovsalist3);
414                 ovsalist3.add("uuid");
415                 ovsalist3.add(instance.getUuid());
416                 ovsoutter.put("op", "update");
417                 ovsoutter.put("table", "Open_vSwitch");
418                 ovsoutter.put("row", ovsinner);
419                 ovsinner.put("manager_options", ovsalist4);
420                 ovsalist4.add("named-uuid");
421                 ovsalist4.add(newmanager);
422
423                 Map mgroutside = new LinkedHashMap();
424                 Map mgrinside = new LinkedHashMap();
425
426                 //Manager Table Insert
427                 mgroutside.put("uuid-name", newmanager);
428                 mgroutside.put("op", "insert");
429                 mgroutside.put("table","Manager");
430                 mgroutside.put("row", mgrinside);
431                 mgrinside.put("target", managerip);
432
433                 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
434                 OvsdbMessage msg = new OvsdbMessage("transact", params);
435
436                 //connection.sendMessage(msg);
437
438             }
439         }catch(Exception e){
440             logger.error("Error in setManager(): ",e);
441         }
442         return true;
443     }
444
445     @Override
446     public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
447             Map<ConfigConstants, Object> configs) {
448         String mgmt = (String)configs.get(ConfigConstants.MGMT);
449         if (mgmt != null) {
450             try {
451                 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
452             } catch (Throwable e) {
453                 // TODO Auto-generated catch block
454                 e.printStackTrace();
455                 return new Status(StatusCode.INTERNALERROR);
456             }
457         }
458         return new Status(StatusCode.BADREQUEST);
459     }
460
461     @Override
462     public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
463             Map<ConfigConstants, Object> configs) {
464         // TODO Auto-generated method stub
465         return null;
466     }
467
468     @Override
469     public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
470
471             try{
472                 if (connectionService == null) {
473                     logger.error("Couldn't refer to the ConnectionService");
474                     return new Status(StatusCode.NOSERVICE);
475                 }
476
477                 Connection connection = this.getConnection(node);
478                 if (connection == null) {
479                     return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
480                 }
481
482                 Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
483                 Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
484                 Operation delPortRequest = null;
485                 String brUuid = null;
486                 String portUuid = null;
487                 if(brTable != null){
488                     for (String uuid : brTable.keySet()) {
489                         Bridge bridge = (Bridge) brTable.get(uuid);
490                         if (bridge.getName().contains(bridgeIdentifier)) {
491                             brUuid = uuid;
492                         }
493                     }
494                 }
495             if(portTable != null){
496                 for (String uuid : portTable.keySet()) {
497                     Port port = (Port) portTable.get(uuid);
498                     if (port.getName().contains(portIdentifier)) {
499                         portUuid = uuid;
500                     }
501                 }
502             }
503
504             UUID portUuidPair = new UUID(portUuid);
505             Mutation bm = new Mutation("ports", Mutator.DELETE, portUuidPair);
506             List<Mutation> mutations = new ArrayList<Mutation>();
507             mutations.add(bm);
508
509             UUID uuid = new UUID(brUuid);
510             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
511             List<Condition> where = new ArrayList<Condition>();
512             where.add(condition);
513             delPortRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
514
515             TransactBuilder transaction = new TransactBuilder();
516             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delPortRequest)));
517
518             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
519             List<OperationResult> tr = transResponse.get();
520             List<Operation> requests = transaction.getRequests();
521             Status status = new Status(StatusCode.SUCCESS);
522             for (int i = 0; i < tr.size() ; i++) {
523                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
524                 if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
525                     OperationResult result = tr.get(i);
526                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
527                 }
528             }
529
530             if (tr.size() > requests.size()) {
531                 OperationResult result = tr.get(tr.size()-1);
532                 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
533                         result.getError(),
534                         result.getDetails());
535                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
536             }
537             return status;
538         } catch(Exception e){
539             logger.error("Error in deletePort()",e);
540         }
541         return new Status(StatusCode.INTERNALERROR);
542     }
543
544     @Override
545     public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
546         // TODO Auto-generated method stub
547         return null;
548     }
549
550     @Override
551     public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
552             String portIdentifier) {
553         // TODO Auto-generated method stub
554         return null;
555     }
556
557     @Override
558     public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
559             Map<ConfigConstants, Object> configs) {
560         // TODO Auto-generated method stub
561         return null;
562     }
563
564     @Override
565     public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
566             Map<ConfigConstants, Object> configs) {
567         // TODO Auto-generated method stub
568         return null;
569     }
570
571     @Override
572     public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
573
574         try {
575             if (connectionService == null) {
576                 logger.error("Couldn't refer to the ConnectionService");
577                 return new Status(StatusCode.NOSERVICE);
578             }
579             Connection connection = this.getConnection(node);
580             if (connection == null) {
581                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
582             }
583             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
584             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
585             Operation delBrRequest = null;
586             String ovsUuid = null;
587             String brUuid = null;
588
589             if (brTable != null) {
590                 for (String uuid : brTable.keySet()) {
591                     Bridge bridge = (Bridge) brTable.get(uuid);
592                     if (bridge.getName().contains(bridgeIdentifier)) {
593                         brUuid = uuid;
594                     }
595                 }
596             }
597             if (ovsTable != null) {
598                 ovsUuid = (String) ovsTable.keySet().toArray()[0];
599             }
600             UUID bridgeUuidPair = new UUID(brUuid);
601             Mutation bm = new Mutation("bridges", Mutator.DELETE, bridgeUuidPair);
602             List<Mutation> mutations = new ArrayList<Mutation>();
603             mutations.add(bm);
604
605             UUID uuid = new UUID(ovsUuid);
606             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
607             List<Condition> where = new ArrayList<Condition>();
608             where.add(condition);
609             delBrRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
610
611             TransactBuilder transaction = new TransactBuilder();
612             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delBrRequest)));
613
614             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
615             List<OperationResult> tr = transResponse.get();
616             List<Operation> requests = transaction.getRequests();
617             Status status = new Status(StatusCode.SUCCESS);
618             for (int i = 0; i < tr.size(); i++) {
619                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
620                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
621                     OperationResult result = tr.get(i);
622                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
623                 }
624             }
625
626             if (tr.size() > requests.size()) {
627                 OperationResult result = tr.get(tr.size() - 1);
628                 logger.error("Error deleting Bridge : {}\n Error : {}\n Details : {}",
629                         bridgeIdentifier, result.getError(), result.getDetails());
630                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
631             }
632             return status;
633         } catch (Exception e) {
634             logger.error("Error in deleteBridgeDomain(): ",e);
635         }
636         return new Status(StatusCode.INTERNALERROR);
637     }
638
639     @Override
640     public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
641         // TODO Auto-generated method stub
642         return null;
643     }
644
645     @Override
646     public List<String> getBridgeDomains(Node node) {
647         List<String> brlist = new ArrayList<String>();
648         Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
649         if(brTableCache != null){
650             for (String uuid : brTableCache.keySet()) {
651                 Bridge bridge = (Bridge) brTableCache.get(uuid);
652                 brlist.add(bridge.getName());
653             }
654         }
655         return brlist;
656     }
657
658     @Override
659     public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
660         return null;
661     }
662
663     Boolean setBridgeOFController(Node node, String bridgeIdentifier) {
664         if (connectionService == null) {
665             logger.error("Couldn't refer to the ConnectionService");
666             return false;
667         }
668
669         try{
670             Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
671             for (String uuid : brTableCache.keySet()) {
672                 Bridge bridge = (Bridge)brTableCache.get(uuid);
673                 if (bridge.getName().contains(bridgeIdentifier)) {
674                     return connectionService.setOFController(node, uuid);
675                 }
676             }
677         } catch(Exception e) {
678             logger.error("Error in setBridgeOFController()",e);
679         }
680         return false;
681     }
682
683     @Override
684     public StatusWithUuid insertRow(Node node, String tableName, String parent_uuid, Table<?> row) {
685         logger.info("tableName : {}, parent_uuid : {} Row : {}", tableName, parent_uuid, row.toString());
686         StatusWithUuid statusWithUUID = null;
687
688         // Schema based Table handling will help fix this static Table handling.
689
690         if (row.getTableName().getName().equalsIgnoreCase("Bridge")) {
691             statusWithUUID = insertBridgeRow(node, parent_uuid, (Bridge)row);
692         }
693         else if (row.getTableName().getName().equalsIgnoreCase("Capbility")) {
694             statusWithUUID = insertCapabilityRow(node, parent_uuid, (Capability)row);
695         }
696         else if (row.getTableName().getName().equalsIgnoreCase("Controller")) {
697             statusWithUUID = insertControllerRow(node, parent_uuid, (Controller)row);
698         }
699         else if (row.getTableName().getName().equalsIgnoreCase("Interface")) {
700             statusWithUUID = insertInterfaceRow(node, parent_uuid, (Interface)row);
701         }
702         else if (row.getTableName().getName().equalsIgnoreCase("Manager")) {
703             statusWithUUID = insertManagerRow(node, parent_uuid, (Manager)row);
704         }
705         else if (row.getTableName().getName().equalsIgnoreCase("Mirror")) {
706             statusWithUUID = insertMirrorRow(node, parent_uuid, (Mirror)row);
707         }
708         else if (row.getTableName().getName().equalsIgnoreCase("NetFlow")) {
709             statusWithUUID = insertNetFlowRow(node, parent_uuid, (NetFlow)row);
710         }
711         else if (row.getTableName().getName().equalsIgnoreCase("Open_vSwitch")) {
712             statusWithUUID = insertOpen_vSwitchRow(node, (Open_vSwitch)row);
713         }
714         else if (row.getTableName().getName().equalsIgnoreCase("Port")) {
715             statusWithUUID = insertPortRow(node, parent_uuid, (Port)row);
716         }
717         else if (row.getTableName().getName().equalsIgnoreCase("QoS")) {
718             statusWithUUID = insertQosRow(node, parent_uuid, (Qos)row);
719         }
720         else if (row.getTableName().getName().equalsIgnoreCase("Queue")) {
721             statusWithUUID = insertQueueRow(node, parent_uuid, (Queue)row);
722         }
723         else if (row.getTableName().getName().equalsIgnoreCase("sFlow")) {
724             statusWithUUID = insertSflowRow(node, parent_uuid, (SFlow)row);
725         }
726         else if (row.getTableName().getName().equalsIgnoreCase("SSL")) {
727             statusWithUUID = insertSSLRow(node, parent_uuid, (SSL)row);
728         }
729         return statusWithUUID;
730     }
731
732
733     @Override
734     public Status updateRow (Node node, String tableName, String parentUUID, String rowUUID, Table<?> row) {
735         try{
736             if (connectionService == null) {
737                 logger.error("Couldn't refer to the ConnectionService");
738                 return new Status(StatusCode.NOSERVICE);
739             }
740
741             Connection connection = this.getConnection(node);
742             if (connection == null) {
743                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
744             }
745
746             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
747
748             if (ovsTable == null) {
749                 return new Status(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
750             }
751
752             UUID uuid = new UUID(rowUUID);
753             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
754             List<Condition> where = new ArrayList<Condition>();
755             where.add(condition);
756             Operation updateRequest = new UpdateOperation(tableName, where, row);
757
758             TransactBuilder transaction = new TransactBuilder();
759             transaction.addOperations(new ArrayList<Operation>(
760                                       Arrays.asList(updateRequest)));
761
762             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
763             List<OperationResult> tr = transResponse.get();
764             List<Operation> requests = transaction.getRequests();
765             Status status = new Status(StatusCode.SUCCESS);
766             for (int i = 0; i < tr.size() ; i++) {
767                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
768                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
769                     OperationResult result = tr.get(i);
770                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
771                 }
772             }
773
774             if (tr.size() > requests.size()) {
775                 OperationResult result = tr.get(tr.size()-1);
776                 logger.error("Error Updating Row : {}/{}\n Error : {}\n Details : {}", tableName, row,
777                                                                                        result.getError(),
778                                                                                        result.getDetails());
779                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
780             }
781             if (status.isSuccess()) {
782                 status = new Status(StatusCode.SUCCESS);
783             }
784             return status;
785         } catch(Exception e){
786             logger.error("Error in updateRow(): ",e);
787         }
788         return new Status(StatusCode.INTERNALERROR);
789     }
790
791     @Override
792     public Status deleteRow(Node node, String tableName, String uuid) {
793         if (tableName.equalsIgnoreCase("Bridge")) {
794             return deleteBridgeRow(node, uuid);
795         }
796         else if (tableName.equalsIgnoreCase("Capbility")) {
797             return deleteCapabilityRow(node, uuid);
798         }
799         else if (tableName.equalsIgnoreCase("Controller")) {
800             return deleteControllerRow(node, uuid);
801         }
802         else if (tableName.equalsIgnoreCase("Interface")) {
803             return deleteInterfaceRow(node, uuid);
804         }
805         else if (tableName.equalsIgnoreCase("Manager")) {
806             return deleteManagerRow(node, uuid);
807         }
808         else if (tableName.equalsIgnoreCase("Mirror")) {
809             return deleteMirrorRow(node, uuid);
810         }
811         else if (tableName.equalsIgnoreCase("NetFlow")) {
812             return deleteNetFlowRow(node, uuid);
813         }
814         else if (tableName.equalsIgnoreCase("Open_vSwitch")) {
815             return deleteOpen_vSwitchRow(node, uuid);
816         }
817         else if (tableName.equalsIgnoreCase("Port")) {
818             return deletePortRow(node, uuid);
819         }
820         else if (tableName.equalsIgnoreCase("QoS")) {
821             return deleteQosRow(node, uuid);
822         }
823         else if (tableName.equalsIgnoreCase("Queue")) {
824             return deleteQueueRow(node, uuid);
825         }
826         else if (tableName.equalsIgnoreCase("sFlow")) {
827             return deleteSflowRow(node, uuid);
828         }
829         else if (tableName.equalsIgnoreCase("SSL")) {
830             return deleteSSLRow(node, uuid);
831         }
832         return new Status(StatusCode.NOTFOUND, "Table "+tableName+" not supported");
833     }
834
835     @Override
836     public Map<String, Table<?>> getRows(Node node, String tableName) throws Exception{
837         try{
838             if (inventoryServiceInternal == null) {
839                 throw new Exception("Inventory Service is Unavailable.");
840             }
841             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, tableName);
842             return ovsTable;
843         } catch(Exception e){
844             throw new Exception("Unable to read table due to "+e.getMessage());
845         }
846     }
847
848     @Override
849     public Table<?> getRow(Node node, String tableName, String uuid) throws Exception {
850         try{
851             if (inventoryServiceInternal == null) {
852                 throw new Exception("Inventory Service is Unavailable.");
853             }
854             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, tableName);
855             if (ovsTable == null) return null;
856             return ovsTable.get(uuid);
857         } catch(Exception e){
858             throw new Exception("Unable to read table due to "+e.getMessage());
859         }
860     }
861
862     @Override
863     public String getSerializedRows(Node node, String tableName) throws Exception{
864         try{
865             Map<String, Table<?>> ovsTable = this.getRows(node, tableName);
866             if (ovsTable == null) return null;
867             ObjectMapper mapper = new ObjectMapper();
868             return mapper.writeValueAsString(ovsTable);
869         } catch(Exception e){
870             throw new Exception("Unable to read table due to "+e.getMessage());
871         }
872     }
873
874     @Override
875     public String getSerializedRow(Node node, String tableName, String uuid) throws Exception {
876         try{
877             Table<?> row = this.getRow(node, tableName, uuid);
878             if (row == null) return null;
879             ObjectMapper mapper = new ObjectMapper();
880             return mapper.writeValueAsString(row);
881         } catch(Exception e){
882             throw new Exception("Unable to read table due to "+e.getMessage());
883         }
884     }
885
886     @Override
887     public List<String> getTables(Node node) {
888         // TODO Auto-generated method stub
889         return null;
890     }
891
892     private StatusWithUuid insertBridgeRow(Node node, String open_VSwitch_uuid, Bridge bridgeRow) {
893
894         String insertErrorMsg = "bridge";
895         String rowName=bridgeRow.getName();
896
897         try{
898             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
899
900             if (ovsTable == null) {
901                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
902             }
903
904             String newBridge = "new_bridge";
905
906             Operation addSwitchRequest = null;
907
908             String ovsTableUUID = open_VSwitch_uuid;
909             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
910             UUID bridgeUuidPair = new UUID(newBridge);
911             Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuidPair);
912             List<Mutation> mutations = new ArrayList<Mutation>();
913             mutations.add(bm);
914
915             UUID uuid = new UUID(ovsTableUUID);
916             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
917             List<Condition> where = new ArrayList<Condition>();
918             where.add(condition);
919             addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
920
921             InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
922
923             TransactBuilder transaction = new TransactBuilder();
924             transaction.addOperations(new ArrayList<Operation>(
925                                       Arrays.asList(addSwitchRequest,
926                                                     addBridgeRequest)));
927
928             int bridgeInsertIndex = transaction.getRequests().indexOf(addBridgeRequest);
929
930             return _insertTableRow(node,transaction,bridgeInsertIndex,insertErrorMsg,rowName);
931
932         } catch(Exception e){
933             logger.error("Error in insertBridgeRow(): ",e);
934         }
935         return new StatusWithUuid(StatusCode.INTERNALERROR);
936     }
937
938
939     private StatusWithUuid insertPortRow(Node node, String bridge_uuid, Port portRow) {
940
941         String insertErrorMsg = "port";
942         String rowName=portRow.getName();
943
944         try{
945             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
946             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
947                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
948             }
949             String newPort = "new_port";
950             UUID portUUID = new UUID(newPort);
951             Mutation bm = new Mutation("ports", Mutator.INSERT, portUUID);
952             List<Mutation> mutations = new ArrayList<Mutation>();
953             mutations.add(bm);
954
955             UUID uuid = new UUID(bridge_uuid);
956             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
957             List<Condition> where = new ArrayList<Condition>();
958             where.add(condition);
959             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
960
961             // Default OVS schema is to have 1 or more interface part of Bridge. Hence it is mandatory to
962             // Insert an Interface in a Port add case :-(.
963
964             String newInterface = "new_interface";
965             Interface interfaceRow = new Interface();
966             interfaceRow.setName(portRow.getName());
967             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
968                     newInterface, interfaceRow);
969
970             OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
971             UUID interfaceid = new UUID(newInterface);
972             interfaces.add(interfaceid);
973             portRow.setInterfaces(interfaces);
974
975             InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
976
977             TransactBuilder transaction = new TransactBuilder();
978             transaction.addOperations(new ArrayList<Operation>
979             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
980             int portInsertIndex = transaction.getRequests().indexOf(addPortRequest);
981
982             return _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
983
984             } catch (Exception e) {
985             logger.error("Error in insertPortRow(): ",e);
986         }
987         return new StatusWithUuid(StatusCode.INTERNALERROR);
988     }
989
990     private StatusWithUuid insertInterfaceRow(Node node, String port_uuid, Interface interfaceRow) {
991
992         String insertErrorMsg = "interface";
993         String rowName=interfaceRow.getName();
994
995         try{
996
997             // Interface table must have entry in Port table, checking port table for port
998             Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
999             if (portTable == null ||  portTable.get(port_uuid) == null) {
1000                 return new StatusWithUuid(StatusCode.NOTFOUND, "Port with UUID "+port_uuid+" Not found");
1001             }
1002             // MUTATOR, need to insert the interface UUID to LIST of interfaces in PORT TABLE for port_uuid
1003             String newInterface = "new_interface";
1004             UUID interfaceUUID = new UUID(newInterface);
1005             Mutation portTableMutation = new Mutation("interfaces", Mutator.INSERT, interfaceUUID); // field name to append is "interfaces"
1006             List<Mutation> mutations = new ArrayList<Mutation>();
1007             mutations.add(portTableMutation);
1008
1009             // Create the Operation which will be used in Transact to perform the PORT TABLE mutation
1010             UUID uuid = new UUID(port_uuid);
1011             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1012             List<Condition> where = new ArrayList<Condition>();
1013             where.add(condition);
1014             Operation addPortMutationRequest = new MutateOperation(Port.NAME.getName(), where, mutations);
1015
1016             // Create the interface row request
1017             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),newInterface, interfaceRow);
1018
1019             // Transaction to insert/modify tables - validate using "sudo ovsdb-client dump" on host running OVSDB process
1020             TransactBuilder transaction = new TransactBuilder();
1021             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addIntfRequest,addPortMutationRequest)));
1022
1023             // Check the results. Iterates over the results of the Array of transaction Operations, and reports STATUS
1024             int interfaceInsertIndex = transaction.getRequests().indexOf(addIntfRequest);
1025
1026             return _insertTableRow(node,transaction,interfaceInsertIndex,insertErrorMsg,rowName);
1027
1028         } catch (Exception e) {
1029             logger.error("Error in insertInterfaceRow(): ",e);
1030         }
1031         return new StatusWithUuid(StatusCode.INTERNALERROR);
1032     }
1033
1034     private StatusWithUuid insertOpen_vSwitchRow(Node node, Open_vSwitch row) {
1035         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1036     }
1037
1038     private StatusWithUuid insertControllerRow(Node node, String bridge_uuid, Controller row) {
1039
1040         String insertErrorMsg = "controller";
1041         String rowName=row.getTableName().toString();
1042
1043         try{
1044
1045             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1046             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
1047                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
1048             }
1049
1050             Map<String, Table<?>> controllerCache = inventoryServiceInternal.getTableCache(node, Controller.NAME.getName());
1051
1052             String uuid_name = "new_controller";
1053             boolean controllerExists = false;
1054             if (controllerCache != null) {
1055                 for (String uuid : controllerCache.keySet()) {
1056                     Controller controller = (Controller)controllerCache.get(uuid);
1057                     if (controller.getTarget().equals(row.getTarget())) {
1058                         uuid_name = uuid;
1059                         controllerExists = true;
1060                         break;
1061                     }
1062                 }
1063             }
1064
1065             UUID controllerUUID = new UUID(uuid_name);
1066             Mutation bm = new Mutation("controller", Mutator.INSERT, controllerUUID);
1067             List<Mutation> mutations = new ArrayList<Mutation>();
1068             mutations.add(bm);
1069
1070             UUID uuid = new UUID(bridge_uuid);
1071             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1072             List<Condition> where = new ArrayList<Condition>();
1073             where.add(condition);
1074             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1075             InsertOperation addControllerRequest = null;
1076
1077             TransactBuilder transaction = new TransactBuilder();
1078             transaction.addOperation(addBrMutRequest);
1079             int portInsertIndex = -1;
1080             if (!controllerExists) {
1081                 addControllerRequest = new InsertOperation(Controller.NAME.getName(), uuid_name, row);
1082                 transaction.addOperation(addControllerRequest);
1083                 portInsertIndex = transaction.getRequests().indexOf(addControllerRequest);
1084             }
1085
1086             return _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
1087
1088         } catch (Exception e) {
1089             logger.error("Error in insertControllerRow(): ",e);
1090         }
1091         return new StatusWithUuid(StatusCode.INTERNALERROR);
1092     }
1093
1094     private StatusWithUuid insertSSLRow(Node node, String parent_uuid, SSL row) {
1095         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1096     }
1097
1098     private StatusWithUuid insertSflowRow(Node node, String parent_uuid, SFlow row) {
1099         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1100     }
1101
1102     private StatusWithUuid insertQueueRow(Node node, String parent_uuid, Queue row) {
1103         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1104     }
1105
1106     private StatusWithUuid insertQosRow(Node node, String parent_uuid, Qos row) {
1107         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1108     }
1109
1110     private StatusWithUuid insertNetFlowRow(Node node, String parent_uuid, NetFlow row) {
1111         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1112     }
1113
1114     private StatusWithUuid insertMirrorRow(Node node, String parent_uuid, Mirror row) {
1115         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1116     }
1117
1118     private StatusWithUuid insertManagerRow(Node node, String parent_uuid, Manager row) {
1119         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1120     }
1121
1122     private StatusWithUuid insertCapabilityRow(Node node, String parent_uuid, Capability row) {
1123         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1124     }
1125
1126     private StatusWithUuid _insertTableRow(Node node, TransactBuilder transaction, Integer insertIndex, String insertErrorMsg,String rowName){
1127
1128         try{
1129             //Check for connection before calling RPC to perform transaction
1130             if (connectionService == null) {
1131                 logger.error("Couldn't refer to the ConnectionService");
1132                 return new StatusWithUuid(StatusCode.NOSERVICE);
1133             }
1134
1135             Connection connection = this.getConnection(node);
1136             if (connection == null) {
1137                 return new StatusWithUuid(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1138             }
1139
1140             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1141             List<OperationResult> tr = transResponse.get();
1142             List<Operation> requests = transaction.getRequests();
1143             StatusWithUuid status = new StatusWithUuid(StatusCode.SUCCESS);
1144             for (int i = 0; i < tr.size() ; i++) {
1145                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1146                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1147                     OperationResult result = tr.get(i);
1148                     status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1149                 }
1150             }
1151
1152             if (tr.size() > requests.size()) {
1153                 OperationResult result = tr.get(tr.size()-1);
1154                 logger.error("Error creating {} : {}\n Error : {}\n Details : {}",     insertErrorMsg,
1155                                                                                        rowName,
1156                                                                                        result.getError(),
1157                                                                                        result.getDetails());
1158                 status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1159             }
1160             if (status.isSuccess()) {
1161                 UUID uuid = tr.get(insertIndex).getUuid();
1162                 status = new StatusWithUuid(StatusCode.SUCCESS, uuid);
1163             }
1164             return status;
1165         } catch(Exception e){
1166             logger.error("Error in _insertTableRow(): ",e);
1167         }
1168         return new StatusWithUuid(StatusCode.INTERNALERROR);
1169     }
1170
1171
1172     private Status deleteBridgeRow(Node node, String uuid) {
1173         // Set up variables for generic _deleteTableRow()
1174         String parentTableName=Open_vSwitch.NAME.getName();
1175         String childTableName=Bridge.NAME.getName();
1176         String parentColumn = "bridges";
1177
1178         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1179     }
1180
1181     private Status deletePortRow(Node node, String uuid) {
1182         // Set up variables for generic _deleteTableRow()
1183         String parentTableName=Bridge.NAME.getName();
1184         String childTableName=Port.NAME.getName();
1185         String parentColumn = "ports";
1186
1187         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1188     }
1189
1190     private Status deleteInterfaceRow(Node node, String uuid) {
1191         // Since Port<-Interface tables have a 1:n relationship, need to test if this is the last interface
1192         // assigned to a port before attempting delete.
1193         Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1194         Map<String, Table<?>> interfaceTable = inventoryServiceInternal.getTableCache(node, Interface.NAME.getName());
1195         // Check that the UUID exists
1196         if (portTable == null || interfaceTable == null || uuid == null || interfaceTable.get(uuid) == null) {
1197             return new Status(StatusCode.NOTFOUND, "");
1198         }
1199
1200         // Need to check if this is the last interface for that port. Cannot delete last interface.
1201         UUID compareUuid = new UUID(uuid);
1202         for (int i=0 ; i < portTable.values().size(); i++){
1203             Port port = (Port)portTable.values().toArray()[i];
1204             if ((port.getInterfaces().size() == 1) && (port.getInterfaces().contains(compareUuid))){
1205                 return new Status(StatusCode.BADREQUEST, "Cannot delete last interface from port");
1206             }
1207         }
1208
1209         // Since the above past, it's safe to use the generic _deleteTableRow method
1210         // Set up variables for generic _deleteTableRow()
1211         String parentTableName=Port.NAME.getName();
1212         String childTableName=Interface.NAME.getName();
1213         String parentColumn = "interfaces";
1214
1215         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1216     }
1217
1218     private Status deleteControllerRow(Node node, String uuid) {
1219         // Set up variables for generic _deleteTableRow()
1220         String parentTableName=Bridge.NAME.getName();
1221         String childTableName=Controller.NAME.getName();
1222         String parentColumn = "controller";
1223
1224         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1225     }
1226
1227     private Status deleteOpen_vSwitchRow(Node node, String uuid) {
1228         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1229     }
1230
1231     private Status deleteSSLRow(Node node, String uuid) {
1232         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1233     }
1234
1235     private Status deleteSflowRow(Node node, String uuid) {
1236         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1237     }
1238
1239     private Status deleteQueueRow(Node node, String uuid) {
1240         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1241     }
1242
1243     private Status deleteQosRow(Node node, String uuid) {
1244         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1245     }
1246
1247     private Status deleteNetFlowRow(Node node, String uuid) {
1248         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1249     }
1250
1251     private Status deleteMirrorRow(Node node, String uuid) {
1252         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1253     }
1254
1255     private Status deleteManagerRow(Node node, String uuid) {
1256         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1257     }
1258
1259     private Status deleteCapabilityRow(Node node, String uuid) {
1260         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1261     }
1262     private Status _deleteTableRow(Node node,String uuid,String parentTableName, String childTableName, String parentColumn) {
1263         try {
1264             // Check there is a connectionService
1265             if (connectionService == null) {
1266                 logger.error("Couldn't refer to the ConnectionService");
1267                 return new Status(StatusCode.NOSERVICE);
1268             }
1269
1270             // Establish the connection
1271             Connection connection = this.getConnection(node);
1272             if (connection == null) {
1273                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1274             }
1275
1276             // Ports have a 0:n relationship with Bridges, so need to MUTATE BRIDGE row and DELETE PORT row
1277             Map<String, Table<?>> parentTable = inventoryServiceInternal.getTableCache(node, parentTableName);
1278             Map<String, Table<?>> childTable = inventoryServiceInternal.getTableCache(node, childTableName);
1279
1280             // Check that the UUID exists
1281             if (parentTable == null || childTable == null || uuid == null || childTable.get(uuid) == null) {
1282                 return new Status(StatusCode.NOTFOUND, "");
1283             }
1284
1285             // Initialise the actual request var
1286             Operation delRequest = null;
1287
1288             // Prepare the mutator to remove the port UUID from the "ports" list in the BRIDGE TABLE
1289             UUID rowUuid = new UUID(uuid);
1290             Mutation mutator = new Mutation(parentColumn, Mutator.DELETE, rowUuid);
1291             List<Mutation> mutations = new ArrayList<Mutation>();
1292             mutations.add(mutator);
1293
1294             Status status = new Status(StatusCode.SUCCESS);
1295
1296             // INCLUDES condition ensures that it captures all rows in the parent table (ie duplicates) that have the child UUID
1297             Condition condition = new Condition(parentColumn, Function.INCLUDES, rowUuid);
1298             List<Condition> where = new ArrayList<Condition>();
1299             where.add(condition);
1300             delRequest = new MutateOperation(parentTableName, where, mutations);
1301
1302             TransactBuilder transaction = new TransactBuilder();
1303             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delRequest)));
1304
1305             // This executes the transaction.
1306             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1307
1308             // Pull the responses
1309             List<OperationResult> tr = transResponse.get();
1310             List<Operation> requests = transaction.getRequests();
1311
1312             for (int i = 0; i < tr.size(); i++) {
1313                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1314                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1315                     OperationResult result = tr.get(i);
1316                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1317                 }
1318             }
1319
1320             if (tr.size() > requests.size()) {
1321                 OperationResult result = tr.get(tr.size() - 1);
1322                 logger.error("Error deleting: {}\n Error : {}\n Details : {}",
1323                         uuid, result.getError(), result.getDetails());
1324                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1325             }
1326             return status;
1327         } catch (Exception e) {
1328             logger.error("Error in _deleteTableRow",e);
1329         }
1330         return new Status(StatusCode.INTERNALERROR);
1331     }
1332
1333     public void _ovsconnect (CommandInterpreter ci) {
1334         String bridgeName = ci.nextArgument();
1335         if (bridgeName == null) {
1336             ci.println("Please enter Bridge Name");
1337             return;
1338         }
1339
1340         String ovsdbserver = ci.nextArgument();
1341         if (ovsdbserver == null) {
1342             ci.println("Please enter valid IP-Address");
1343             return;
1344         }
1345         try {
1346             InetAddress.getByName(ovsdbserver);
1347         }  catch (Exception e) {
1348             e.printStackTrace();
1349             ci.println("Please enter valid IP-Address");
1350             return;
1351         }
1352         String port = ci.nextArgument();
1353         if (port == null) {
1354             port = "6634";
1355         }
1356
1357         ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
1358         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
1359         params.put(ConnectionConstants.ADDRESS, ovsdbserver);
1360         params.put(ConnectionConstants.PORT, port);
1361         Node node = connectionService.connect(bridgeName, params);
1362         if (node != null) ci.println("Node Name: "+node.toString());
1363         else ci.println("Could not connect to Node");
1364     }
1365
1366     public void _addBridge (CommandInterpreter ci) {
1367         String nodeName = ci.nextArgument();
1368         if (nodeName == null) {
1369             ci.println("Please enter Node Name");
1370             return;
1371         }
1372         String bridgeName = ci.nextArgument();
1373         if (bridgeName == null) {
1374             ci.println("Please enter Bridge Name");
1375             return;
1376         }
1377         Status status;
1378
1379         try {
1380             Node node = Node.fromString(nodeName);
1381             if (node == null) {
1382                 ci.println("Invalid Node");
1383                 return;
1384             }
1385             status = this.createBridgeDomain(node, bridgeName, null);
1386             ci.println("Bridge creation status : "+status.toString());
1387         } catch (Throwable e) {
1388             // TODO Auto-generated catch block
1389             e.printStackTrace();
1390             ci.println("Failed to create Bridge "+bridgeName);
1391         }
1392     }
1393
1394     public void _getBridgeDomains (CommandInterpreter ci) {
1395         String nodeName = ci.nextArgument();
1396         if (nodeName == null) {
1397             ci.println("Please enter Node Name");
1398             return;
1399         }
1400         Status status;
1401
1402         List<String> brlist = new ArrayList<String>();
1403         try {
1404             Node node = Node.fromString(nodeName);
1405             brlist = this.getBridgeDomains(node);
1406             if (node == null) {
1407                 ci.println("Invalid Node");
1408                 return;
1409             }
1410             ci.println("Existing Bridges: "+brlist.toString());
1411         } catch (Throwable e) {
1412             e.printStackTrace();
1413             ci.println("Failed to list Bridges");
1414         }
1415     }
1416
1417     public void _deleteBridgeDomain (CommandInterpreter ci) {
1418         String nodeName = ci.nextArgument();
1419         if (nodeName == null) {
1420             ci.println("Please enter Node Name");
1421             return;
1422         }
1423         String bridgeName = ci.nextArgument();
1424         if (bridgeName == null) {
1425             ci.println("Please enter Bridge Name");
1426             return;
1427         }
1428         Status status;
1429         try {
1430             Node node = Node.fromString(nodeName);
1431             if (node == null) {
1432                 ci.println("Invalid Node");
1433                 return;
1434             }
1435             status = this.deleteBridgeDomain(node, bridgeName);
1436             ci.println("Bridge deletion status : "+status.toString());
1437         } catch (Throwable e) {
1438             e.printStackTrace();
1439             ci.println("Failed to delete Bridge "+bridgeName);
1440         }
1441     }
1442
1443     public void _addPort (CommandInterpreter ci) {
1444         String nodeName = ci.nextArgument();
1445         if (nodeName == null) {
1446             ci.println("Please enter Node Name");
1447             return;
1448         }
1449
1450         String bridgeName = ci.nextArgument();
1451         if (bridgeName == null) {
1452             ci.println("Please enter Bridge Name");
1453             return;
1454         }
1455
1456         String portName = ci.nextArgument();
1457         if (portName == null) {
1458             ci.println("Please enter Port Name");
1459             return;
1460         }
1461
1462         String type = ci.nextArgument();
1463
1464         Map<String, String> configs = new HashMap<String, String>();
1465         while(true) {
1466             String configKey = ci.nextArgument();
1467             if (configKey == null) break;
1468             String configValue = ci.nextArgument();
1469             if (configValue == null) break;
1470             configs.put(configKey, configValue);
1471         }
1472
1473         Map<ConfigConstants, Object> customConfigs = null;
1474         if (type != null) {
1475             customConfigs = new HashMap<ConfigConstants, Object>();
1476             customConfigs.put(ConfigConstants.TYPE, type);
1477         }
1478
1479         if (configs.size() > 0) {
1480             if (customConfigs == null) customConfigs = new HashMap<ConfigConstants, Object>();
1481             customConfigs.put(ConfigConstants.CUSTOM, configs);
1482             ci.println(customConfigs.toString());
1483         }
1484         Status status;
1485         try {
1486             Node node = Node.fromString(nodeName);
1487             if (node == null) {
1488                 ci.println("Invalid Node");
1489                 return;
1490             }
1491             status = this.addPort(node, bridgeName, portName, customConfigs);
1492             ci.println("Port creation status : "+status.toString());
1493         } catch (Throwable e) {
1494             // TODO Auto-generated catch block
1495             e.printStackTrace();
1496             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
1497         }
1498     }
1499
1500     public void _deletePort (CommandInterpreter ci) {
1501         String nodeName = ci.nextArgument();
1502         if (nodeName == null) {
1503             ci.println("Please enter Node Name");
1504             return;
1505         }
1506
1507         String bridgeName = ci.nextArgument();
1508         if (bridgeName == null) {
1509             ci.println("Please enter Bridge Name");
1510             return;
1511         }
1512
1513         String portName = ci.nextArgument();
1514         if (portName == null) {
1515             ci.println("Please enter Port Name");
1516             return;
1517         }
1518
1519         Status status;
1520         try {
1521             Node node = Node.fromString(nodeName);
1522             if (node == null) {
1523                 ci.println("Invalid Node");
1524                 return;
1525             }
1526             status = this.deletePort(node, bridgeName, portName);
1527             ci.println("Port deletion status : "+status.toString());
1528         } catch (Throwable e) {
1529             // TODO Auto-generated catch block
1530             e.printStackTrace();
1531             ci.println("Failed to delete Port "+portName+" in Bridge "+bridgeName);
1532         }
1533     }
1534
1535     public void _addPortVlan (CommandInterpreter ci) {
1536         String nodeName = ci.nextArgument();
1537         if (nodeName == null) {
1538             ci.println("Please enter Node Name");
1539             return;
1540         }
1541
1542         String bridgeName = ci.nextArgument();
1543         if (bridgeName == null) {
1544             ci.println("Please enter Bridge Name");
1545             return;
1546         }
1547
1548         String portName = ci.nextArgument();
1549         if (portName == null) {
1550             ci.println("Please enter Port Name");
1551             return;
1552         }
1553
1554         String vlan = ci.nextArgument();
1555         if (vlan == null) {
1556             ci.println("Please enter Valid Vlan");
1557             return;
1558         } else {
1559             try {
1560             Integer.parseInt(vlan);
1561             } catch (Exception e) {
1562                 ci.println("Please enter Valid Vlan");
1563                 return;
1564             }
1565         }
1566
1567         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1568         configs.put(ConfigConstants.TYPE, "VLAN");
1569         configs.put(ConfigConstants.VLAN, vlan);
1570
1571         Status status;
1572         try {
1573             Node node = Node.fromString(nodeName);
1574             if (node == null) {
1575                 ci.println("Invalid Node");
1576                 return;
1577             }
1578             status = this.addPort(node, bridgeName, portName, configs);
1579             ci.println("Port creation status : "+status.toString());
1580         } catch (Throwable e) {
1581             // TODO Auto-generated catch block
1582             e.printStackTrace();
1583             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
1584         }
1585     }
1586
1587     public void _addTunnel (CommandInterpreter ci) {
1588         String nodeName = ci.nextArgument();
1589         if (nodeName == null) {
1590             ci.println("Please enter Node Name");
1591             return;
1592         }
1593
1594         String bridgeName = ci.nextArgument();
1595         if (bridgeName == null) {
1596             ci.println("Please enter Bridge Name");
1597             return;
1598         }
1599
1600         String portName = ci.nextArgument();
1601         if (portName == null) {
1602             ci.println("Please enter Port Name");
1603             return;
1604         }
1605
1606         String tunnelType = ci.nextArgument();
1607         if (tunnelType == null) {
1608             ci.println("Please enter Tunnel Type");
1609             return;
1610         }
1611
1612         String remoteIp = ci.nextArgument();
1613         if (remoteIp == null) {
1614             ci.println("Please enter valid Remote IP Address");
1615             return;
1616         }
1617
1618         try {
1619             InetAddress.getByName(remoteIp);
1620         }  catch (Exception e) {
1621             e.printStackTrace();
1622             ci.println("Please enter valid Remote IP Address");
1623             return;
1624         }
1625
1626         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1627         configs.put(ConfigConstants.TYPE, "TUNNEL");
1628         configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
1629         configs.put(ConfigConstants.DEST_IP, remoteIp);
1630
1631         Status status;
1632         try {
1633             Node node = Node.fromString(nodeName);
1634             if (node == null) {
1635                 ci.println("Invalid Node");
1636                 return;
1637             }
1638             status = this.addPort(node, bridgeName, portName, configs);
1639             ci.println("Port creation status : "+status.toString());
1640         } catch (Throwable e) {
1641             // TODO Auto-generated catch block
1642             e.printStackTrace();
1643             ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
1644         }
1645     }
1646
1647     public void _printCache (CommandInterpreter ci) {
1648         String nodeName = ci.nextArgument();
1649         if (nodeName == null) {
1650             ci.println("Please enter Node Name");
1651             return;
1652         }
1653         Node node = Node.fromString(nodeName);
1654         if (node == null) {
1655             ci.println("Invalid Node");
1656             return;
1657         }
1658         inventoryServiceInternal.printCache(node);
1659     }
1660
1661     public void _forceConnect (CommandInterpreter ci) {
1662         String force = ci.nextArgument();
1663         if (force.equalsIgnoreCase("YES")) forceConnect = true;
1664         else if (force.equalsIgnoreCase("NO")) forceConnect = false;
1665         else ci.println("Please enter YES or NO.");
1666         ci.println("Current ForceConnect State : "+forceConnect);
1667         return;
1668     }
1669
1670     @Override
1671     public String getHelp() {
1672         StringBuffer help = new StringBuffer();
1673         help.append("---OVSDB CLI---\n");
1674         help.append("\t ovsconnect <ConnectionName> <ip-address>                        - Connect to OVSDB\n");
1675         help.append("\t addBridge <Node> <BridgeName>                                   - Add Bridge\n");
1676         help.append("\t getBridgeDomains <Node>                                         - Get Bridges\n");
1677         help.append("\t deleteBridgeDomain <Node> <BridgeName>                          - Delete a Bridge\n");
1678         help.append("\t addPort <Node> <BridgeName> <PortName> <type> <options pairs>   - Add Port\n");
1679         help.append("\t deletePort <Node> <BridgeName> <PortName>                       - Delete Port\n");
1680         help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan>               - Add Port, Vlan\n");
1681         help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip>      - Add Tunnel\n");
1682         help.append("\t printCache <Node>                                               - Prints Table Cache");
1683         return help.toString();
1684     }
1685 }
1686