Merge "- Addressed Queue/QoS special parent column type dependency - New files found...
[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.net.UnknownHostException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.HashMap;
9 import java.util.LinkedHashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 import org.eclipse.osgi.framework.console.CommandInterpreter;
14 import org.eclipse.osgi.framework.console.CommandProvider;
15 import org.opendaylight.controller.sal.connection.ConnectionConstants;
16 import org.opendaylight.controller.sal.core.Node;
17 import org.opendaylight.controller.sal.core.NodeConnector;
18 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
19 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
20 import org.opendaylight.controller.sal.utils.Status;
21 import org.opendaylight.controller.sal.utils.StatusCode;
22 import org.opendaylight.ovsdb.lib.database.OVSInstance;
23 import org.opendaylight.ovsdb.lib.database.OvsdbType;
24 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
25 import org.opendaylight.ovsdb.lib.message.operations.DeleteOperation;
26 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
27 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
28 import org.opendaylight.ovsdb.lib.message.operations.Operation;
29 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
30 import org.opendaylight.ovsdb.lib.message.operations.UpdateOperation;
31 import org.opendaylight.ovsdb.lib.notation.Condition;
32 import org.opendaylight.ovsdb.lib.notation.Function;
33 import org.opendaylight.ovsdb.lib.notation.Mutation;
34 import org.opendaylight.ovsdb.lib.notation.Mutator;
35 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
36 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
37 import org.opendaylight.ovsdb.lib.notation.UUID;
38 import org.opendaylight.ovsdb.lib.table.Bridge;
39 import org.opendaylight.ovsdb.lib.table.Capability;
40 import org.opendaylight.ovsdb.lib.table.Controller;
41 import org.opendaylight.ovsdb.lib.table.Interface;
42 import org.opendaylight.ovsdb.lib.table.Manager;
43 import org.opendaylight.ovsdb.lib.table.Mirror;
44 import org.opendaylight.ovsdb.lib.table.NetFlow;
45 import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
46 import org.opendaylight.ovsdb.lib.table.Port;
47 import org.opendaylight.ovsdb.lib.table.Qos;
48 import org.opendaylight.ovsdb.lib.table.Queue;
49 import org.opendaylight.ovsdb.lib.table.SFlow;
50 import org.opendaylight.ovsdb.lib.table.SSL;
51 import org.opendaylight.ovsdb.lib.table.internal.Table;
52 import org.osgi.framework.BundleContext;
53 import org.osgi.framework.FrameworkUtil;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import com.fasterxml.jackson.databind.ObjectMapper;
58 import com.google.common.util.concurrent.ListenableFuture;
59
60 public class ConfigurationService implements IPluginInBridgeDomainConfigService, OVSDBConfigService,
61                                              CommandProvider
62 {
63     private static final Logger logger = LoggerFactory
64             .getLogger(ConfigurationService.class);
65
66     IConnectionServiceInternal connectionService;
67     InventoryServiceInternal inventoryServiceInternal;
68     boolean forceConnect = false;
69
70     void init() {
71     }
72
73     /**
74      * Function called by the dependency manager when at least one dependency
75      * become unsatisfied or when the component is shutting down because for
76      * example bundle is being stopped.
77      *
78      */
79     void destroy() {
80     }
81
82     /**
83      * Function called by dependency manager after "init ()" is called and after
84      * the services provided by the class are registered in the service registry
85      *
86      */
87     void start() {
88         registerWithOSGIConsole();
89     }
90
91     private void registerWithOSGIConsole() {
92         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
93                 .getBundleContext();
94         bundleContext.registerService(CommandProvider.class.getName(), this,
95                 null);
96     }
97
98     /**
99      * Function called by the dependency manager before the services exported by
100      * the component are unregistered, this will be followed by a "destroy ()"
101      * calls
102      *
103      */
104     void stop() {
105     }
106
107     public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
108         this.connectionService = connectionService;
109     }
110
111     public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
112         if (this.connectionService == connectionService) {
113             this.connectionService = null;
114         }
115     }
116
117     public void setInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
118         this.inventoryServiceInternal = inventoryServiceInternal;
119     }
120
121     public void unsetInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
122         if (this.inventoryServiceInternal == inventoryServiceInternal) {
123             this.inventoryServiceInternal = null;
124         }
125     }
126
127     private Connection getConnection (Node node) {
128         Connection connection = connectionService.getConnection(node);
129         if (connection == null || !connection.getChannel().isActive()) {
130             return null;
131         }
132
133         return connection;
134     }
135
136     /**
137      * Add a new bridge
138      * @param node Node serving this configuration service
139      * @param bridgeConnectorIdentifier String representation of a Bridge Connector
140      * @return Bridge Connector configurations
141      */
142     @Override
143     public Status createBridgeDomain(Node node, String bridgeIdentifier,
144             Map<ConfigConstants, Object> configs) {
145         try{
146             if (connectionService == null) {
147                 logger.error("Couldn't refer to the ConnectionService");
148                 return new Status(StatusCode.NOSERVICE);
149             }
150
151             Connection connection = this.getConnection(node);
152             if (connection == null) {
153                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
154             }
155
156             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
157             String newBridge = "new_bridge";
158             String newInterface = "new_interface";
159             String newPort = "new_port";
160             String newSwitch = "new_switch";
161
162             Operation addSwitchRequest = null;
163
164             if(ovsTable != null){
165                 String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
166                 UUID bridgeUuidPair = new UUID(newBridge);
167                 Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuidPair);
168                 List<Mutation> mutations = new ArrayList<Mutation>();
169                 mutations.add(bm);
170
171                 UUID uuid = new UUID(ovsTableUUID);
172                 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
173                 List<Condition> where = new ArrayList<Condition>();
174                 where.add(condition);
175                 addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
176             }
177             else{
178                 Open_vSwitch ovsTableRow = new Open_vSwitch();
179                 OvsDBSet<UUID> bridges = new OvsDBSet<UUID>();
180                 UUID bridgeUuidPair = new UUID(newBridge);
181                 bridges.add(bridgeUuidPair);
182                 ovsTableRow.setBridges(bridges);
183                 addSwitchRequest = new InsertOperation(Open_vSwitch.NAME.getName(), newSwitch, ovsTableRow);
184             }
185
186             Bridge bridgeRow = new Bridge();
187             bridgeRow.setName(bridgeIdentifier);
188             OvsDBSet<UUID> ports = new OvsDBSet<UUID>();
189             UUID port = new UUID(newPort);
190             ports.add(port);
191             bridgeRow.setPorts(ports);
192             InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
193
194             Port portRow = new Port();
195             portRow.setName(bridgeIdentifier);
196             OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
197             UUID interfaceid = new UUID(newInterface);
198             interfaces.add(interfaceid);
199             portRow.setInterfaces(interfaces);
200             InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
201
202             Interface interfaceRow = new Interface();
203             interfaceRow.setName(bridgeIdentifier);
204             interfaceRow.setType("internal");
205             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(), newInterface, interfaceRow);
206
207             /* Update config version */
208             String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
209             Mutation bm = new Mutation("next_cfg", Mutator.SUM, 1);
210             List<Mutation> mutations = new ArrayList<Mutation>();
211             mutations.add(bm);
212
213             UUID uuid = new UUID(ovsTableUUID);
214             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
215             List<Condition> where = new ArrayList<Condition>();
216             where.add(condition);
217             MutateOperation updateCfgVerRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
218
219             TransactBuilder transaction = new TransactBuilder();
220             transaction.addOperations(new ArrayList<Operation>(
221                                       Arrays.asList(addSwitchRequest,
222                                                     addIntfRequest,
223                                                     addPortRequest,
224                                                     addBridgeRequest,
225                                                     updateCfgVerRequest)));
226
227             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
228             List<OperationResult> tr = transResponse.get();
229             List<Operation> requests = transaction.getRequests();
230             Status status = new Status(StatusCode.SUCCESS);
231             for (int i = 0; i < tr.size() ; i++) {
232                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
233                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
234                     OperationResult result = tr.get(i);
235                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
236                 }
237             }
238
239             if (tr.size() > requests.size()) {
240                 OperationResult result = tr.get(tr.size()-1);
241                 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
242                                                                                        result.getError(),
243                                                                                        result.getDetails());
244                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
245             }
246             if (status.isSuccess()) {
247                 setBridgeOFController(node, bridgeIdentifier);
248             }
249             return status;
250         } catch(Exception e){
251             logger.error("Error in createBridgeDomain(): ",e);
252         }
253         return new Status(StatusCode.INTERNALERROR);
254     }
255
256     /**
257      * Create a Port Attached to a Bridge
258      * Ex. ovs-vsctl add-port br0 vif0
259      * @param node Node serving this configuration service
260      * @param bridgeDomainIdentifier String representation of a Bridge Domain
261      * @param portIdentifier String representation of a user defined Port Name
262      */
263     @Override
264     public Status addPort(Node node, String bridgeIdentifier, String portIdentifier,
265                           Map<ConfigConstants, Object> configs) {
266         try{
267             if (connectionService == null) {
268                 logger.error("Couldn't refer to the ConnectionService");
269                 return new Status(StatusCode.NOSERVICE);
270             }
271             Connection connection = this.getConnection(node);
272             if (connection == null) {
273                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
274             }
275             if (connection != null) {
276                 Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
277                 String newBridge = "new_bridge";
278                 String newInterface = "new_interface";
279                 String newPort = "new_port";
280
281                 if(brTable != null){
282                     Operation addBrMutRequest = null;
283                     String brUuid = null;
284                     for (String uuid : brTable.keySet()) {
285                         Bridge bridge = (Bridge) brTable.get(uuid);
286                         if (bridge.getName().contains(bridgeIdentifier)) {
287                             brUuid = uuid;
288                         }
289                     }
290
291                     UUID brUuidPair = new UUID(newPort);
292                     Mutation bm = new Mutation("ports", Mutator.INSERT, brUuidPair);
293                     List<Mutation> mutations = new ArrayList<Mutation>();
294                     mutations.add(bm);
295
296                     UUID uuid = new UUID(brUuid);
297                     Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
298                     List<Condition> where = new ArrayList<Condition>();
299                     where.add(condition);
300                     addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
301
302                     OvsDBMap<String, String> options = null;
303                     String type = null;
304                     OvsDBSet<BigInteger> tags = null;
305                     if (configs != null) {
306                         type = (String) configs.get(ConfigConstants.TYPE);
307                         Map<String, String> customConfigs = (Map<String, String>) configs.get(ConfigConstants.CUSTOM);
308                         if (customConfigs != null) {
309                             options = new OvsDBMap<String, String>();
310                             for (String customConfig : customConfigs.keySet()) {
311                                 options.put(customConfig, customConfigs.get(customConfig));
312                             }
313                         }
314                     }
315
316                     Interface interfaceRow = new Interface();
317                     interfaceRow.setName(portIdentifier);
318
319                     if (type != null) {
320                         if (type.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
321                             interfaceRow.setType((String)configs.get(ConfigConstants.TUNNEL_TYPE));
322                             if (options == null) options = new OvsDBMap<String, String>();
323                             options.put("remote_ip", (String)configs.get(ConfigConstants.DEST_IP));
324                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
325                             tags = new OvsDBSet<BigInteger>();
326                             tags.add(BigInteger.valueOf(Integer.parseInt((String)configs.get(ConfigConstants.VLAN))));
327                         } else if (type.equalsIgnoreCase(OvsdbType.PortType.PATCH.name())) {
328                             interfaceRow.setType(type.toLowerCase());
329                         }
330                     }
331                     if (options != null) {
332                         interfaceRow.setOptions(options);
333                     }
334
335                     InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
336                             newInterface, interfaceRow);
337
338                     Port portRow = new Port();
339                     portRow.setName(portIdentifier);
340                     if (tags != null) portRow.setTag(tags);
341                     OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
342                     UUID interfaceid = new UUID(newInterface);
343                     interfaces.add(interfaceid);
344                     portRow.setInterfaces(interfaces);
345                     InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
346
347                     TransactBuilder transaction = new TransactBuilder();
348                     transaction.addOperations(new ArrayList<Operation>
349                             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
350
351                     ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
352                     List<OperationResult> tr = transResponse.get();
353                     List<Operation> requests = transaction.getRequests();
354                     Status status = new Status(StatusCode.SUCCESS);
355                     for (int i = 0; i < tr.size() ; i++) {
356                         if (i < requests.size()) requests.get(i).setResult(tr.get(i));
357                         if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
358                             OperationResult result = tr.get(i);
359                             status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
360                         }
361                     }
362
363                     if (tr.size() > requests.size()) {
364                         OperationResult result = tr.get(tr.size()-1);
365                         logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
366                                 result.getError(),
367                                 result.getDetails());
368                         status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
369                     }
370                     return status;
371                 }
372                 return new Status(StatusCode.INTERNALERROR);
373             }
374         } catch(Exception e){
375             logger.error("Error in addPort()",e);
376         }
377         return new Status(StatusCode.INTERNALERROR);
378     }
379
380     /**
381      * Implements the OVS Connection for Managers
382      *
383      * @param node Node serving this configuration service
384      * @param String with IP and connection types
385      */
386     @SuppressWarnings("unchecked")
387     public boolean setManager(Node node, String managerip) {
388         try{
389             if (connectionService == null) {
390                 logger.error("Couldn't refer to the ConnectionService");
391                 return false;
392             }
393             Connection connection = this.getConnection(node);
394             if (connection == null) {
395                 return false;
396             }
397
398             if (connection != null) {
399                 String newmanager = "new_manager";
400
401                 OVSInstance instance = OVSInstance.monitorOVS(connection);
402
403                 Map ovsoutter = new LinkedHashMap();
404                 Map ovsinner = new LinkedHashMap();
405                 ArrayList ovsalist1 = new ArrayList();
406                 ArrayList ovsalist2 = new ArrayList();
407                 ArrayList ovsalist3 = new ArrayList();
408                 ArrayList ovsalist4 = new ArrayList();
409
410                 //OVS Table Update
411                 ovsoutter.put("where", ovsalist1);
412                 ovsalist1.add(ovsalist2);
413                 ovsalist2.add("_uuid");
414                 ovsalist2.add("==");
415                 ovsalist2.add(ovsalist3);
416                 ovsalist3.add("uuid");
417                 ovsalist3.add(instance.getUuid());
418                 ovsoutter.put("op", "update");
419                 ovsoutter.put("table", "Open_vSwitch");
420                 ovsoutter.put("row", ovsinner);
421                 ovsinner.put("manager_options", ovsalist4);
422                 ovsalist4.add("named-uuid");
423                 ovsalist4.add(newmanager);
424
425                 Map mgroutside = new LinkedHashMap();
426                 Map mgrinside = new LinkedHashMap();
427
428                 //Manager Table Insert
429                 mgroutside.put("uuid-name", newmanager);
430                 mgroutside.put("op", "insert");
431                 mgroutside.put("table","Manager");
432                 mgroutside.put("row", mgrinside);
433                 mgrinside.put("target", managerip);
434
435                 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
436                 OvsdbMessage msg = new OvsdbMessage("transact", params);
437
438                 //connection.sendMessage(msg);
439
440             }
441         }catch(Exception e){
442             logger.error("Error in setManager(): ",e);
443         }
444         return true;
445     }
446
447     @Override
448     public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
449             Map<ConfigConstants, Object> configs) {
450         String mgmt = (String)configs.get(ConfigConstants.MGMT);
451         if (mgmt != null) {
452             if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
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             logger.error("Error in deletePort()",e);
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
570         try {
571             if (connectionService == null) {
572                 logger.error("Couldn't refer to the ConnectionService");
573                 return new Status(StatusCode.NOSERVICE);
574             }
575             Connection connection = this.getConnection(node);
576             if (connection == null) {
577                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
578             }
579             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
580             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
581             Operation delBrRequest = null;
582             String ovsUuid = null;
583             String brUuid = null;
584
585             if (brTable != null) {
586                 for (String uuid : brTable.keySet()) {
587                     Bridge bridge = (Bridge) brTable.get(uuid);
588                     if (bridge.getName().contains(bridgeIdentifier)) {
589                         brUuid = uuid;
590                     }
591                 }
592             }
593             if (ovsTable != null) {
594                 ovsUuid = (String) ovsTable.keySet().toArray()[0];
595             }
596             UUID bridgeUuidPair = new UUID(brUuid);
597             Mutation bm = new Mutation("bridges", Mutator.DELETE, bridgeUuidPair);
598             List<Mutation> mutations = new ArrayList<Mutation>();
599             mutations.add(bm);
600
601             UUID uuid = new UUID(ovsUuid);
602             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
603             List<Condition> where = new ArrayList<Condition>();
604             where.add(condition);
605             delBrRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
606
607             TransactBuilder transaction = new TransactBuilder();
608             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delBrRequest)));
609
610             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
611             List<OperationResult> tr = transResponse.get();
612             List<Operation> requests = transaction.getRequests();
613             Status status = new Status(StatusCode.SUCCESS);
614             for (int i = 0; i < tr.size(); i++) {
615                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
616                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
617                     OperationResult result = tr.get(i);
618                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
619                 }
620             }
621
622             if (tr.size() > requests.size()) {
623                 OperationResult result = tr.get(tr.size() - 1);
624                 logger.error("Error deleting Bridge : {}\n Error : {}\n Details : {}",
625                         bridgeIdentifier, result.getError(), result.getDetails());
626                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
627             }
628             return status;
629         } catch (Exception e) {
630             logger.error("Error in deleteBridgeDomain(): ",e);
631         }
632         return new Status(StatusCode.INTERNALERROR);
633     }
634
635     @Override
636     public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
637         // TODO Auto-generated method stub
638         return null;
639     }
640
641     @Override
642     public List<String> getBridgeDomains(Node node) {
643         List<String> brlist = new ArrayList<String>();
644         Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
645         if(brTableCache != null){
646             for (String uuid : brTableCache.keySet()) {
647                 Bridge bridge = (Bridge) brTableCache.get(uuid);
648                 brlist.add(bridge.getName());
649             }
650         }
651         return brlist;
652     }
653
654     @Override
655     public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
656         return null;
657     }
658
659     Boolean setBridgeOFController(Node node, String bridgeIdentifier) {
660         if (connectionService == null) {
661             logger.error("Couldn't refer to the ConnectionService");
662             return false;
663         }
664
665         try{
666             Map<String, Table<?>> brTableCache = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
667             for (String uuid : brTableCache.keySet()) {
668                 Bridge bridge = (Bridge)brTableCache.get(uuid);
669                 if (bridge.getName().contains(bridgeIdentifier)) {
670                     return connectionService.setOFController(node, uuid);
671                 }
672             }
673         } catch(Exception e) {
674             logger.error("Error in setBridgeOFController()",e);
675         }
676         return false;
677     }
678
679     @Override
680     public StatusWithUuid insertRow(Node node, String tableName, String parent_uuid, Table<?> row) {
681         logger.info("tableName : {}, parent_uuid : {} Row : {}", tableName, parent_uuid, row.toString());
682         StatusWithUuid statusWithUUID = null;
683
684         // Schema based Table handling will help fix this static Table handling.
685
686         if (row.getTableName().getName().equalsIgnoreCase("Bridge")) {
687             statusWithUUID = insertBridgeRow(node, parent_uuid, (Bridge)row);
688         }
689         else if (row.getTableName().getName().equalsIgnoreCase("Capability")) {
690             return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
691         }
692         else if (row.getTableName().getName().equalsIgnoreCase("Controller")) {
693             statusWithUUID = insertControllerRow(node, parent_uuid, (Controller)row);
694         }
695         else if (row.getTableName().getName().equalsIgnoreCase("Interface")) {
696             statusWithUUID = insertInterfaceRow(node, parent_uuid, (Interface)row);
697         }
698         else if (row.getTableName().getName().equalsIgnoreCase("Manager")) {
699             statusWithUUID = insertManagerRow(node, parent_uuid, (Manager)row);
700         }
701         else if (row.getTableName().getName().equalsIgnoreCase("Mirror")) {
702             statusWithUUID = insertMirrorRow(node, parent_uuid, (Mirror)row);
703         }
704         else if (row.getTableName().getName().equalsIgnoreCase("NetFlow")) {
705             statusWithUUID = insertNetFlowRow(node, parent_uuid, (NetFlow)row);
706         }
707         else if (row.getTableName().getName().equalsIgnoreCase("Open_vSwitch")) {
708             statusWithUUID = insertOpen_vSwitchRow(node, (Open_vSwitch)row);
709         }
710         else if (row.getTableName().getName().equalsIgnoreCase("Port")) {
711             statusWithUUID = insertPortRow(node, parent_uuid, (Port)row);
712         }
713         else if (row.getTableName().getName().equalsIgnoreCase("QoS")) {
714             statusWithUUID = insertQosRow(node, parent_uuid, (Qos)row);
715         }
716         else if (row.getTableName().getName().equalsIgnoreCase("Queue")) {
717             statusWithUUID = insertQueueRow(node, parent_uuid, (Queue)row);
718         }
719         else if (row.getTableName().getName().equalsIgnoreCase("sFlow")) {
720             statusWithUUID = insertSflowRow(node, parent_uuid, (SFlow)row);
721         }
722         else if (row.getTableName().getName().equalsIgnoreCase("SSL")) {
723             statusWithUUID = insertSSLRow(node, parent_uuid, (SSL)row);
724         }
725         return statusWithUUID;
726     }
727
728
729     @Override
730     public Status updateRow (Node node, String tableName, String parentUUID, String rowUUID, Table<?> row) {
731         try{
732             if (connectionService == null) {
733                 logger.error("Couldn't refer to the ConnectionService");
734                 return new Status(StatusCode.NOSERVICE);
735             }
736
737             Connection connection = this.getConnection(node);
738             if (connection == null) {
739                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
740             }
741
742             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
743
744             if (ovsTable == null) {
745                 return new Status(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
746             }
747
748             UUID uuid = new UUID(rowUUID);
749             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
750             List<Condition> where = new ArrayList<Condition>();
751             where.add(condition);
752             Operation updateRequest = new UpdateOperation(tableName, where, row);
753
754             TransactBuilder transaction = new TransactBuilder();
755             transaction.addOperations(new ArrayList<Operation>(
756                                       Arrays.asList(updateRequest)));
757
758             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
759             List<OperationResult> tr = transResponse.get();
760             List<Operation> requests = transaction.getRequests();
761             Status status = new Status(StatusCode.SUCCESS);
762             for (int i = 0; i < tr.size() ; i++) {
763                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
764                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
765                     OperationResult result = tr.get(i);
766                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
767                 }
768             }
769
770             if (tr.size() > requests.size()) {
771                 OperationResult result = tr.get(tr.size()-1);
772                 logger.error("Error Updating Row : {}/{}\n Error : {}\n Details : {}", tableName, row,
773                                                                                        result.getError(),
774                                                                                        result.getDetails());
775                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
776             }
777             if (status.isSuccess()) {
778                 status = new Status(StatusCode.SUCCESS);
779             }
780             return status;
781         } catch(Exception e){
782             logger.error("Error in updateRow(): ",e);
783         }
784         return new Status(StatusCode.INTERNALERROR);
785     }
786
787     @Override
788     public Status deleteRow(Node node, String tableName, String uuid) {
789         if (tableName.equalsIgnoreCase("Bridge")) {
790             return deleteBridgeRow(node, uuid);
791         }
792         else if (tableName.equalsIgnoreCase("Capbility")) {
793             return new Status(StatusCode.NOTIMPLEMENTED, "Delete operation for this Table is not implemented yet.");
794         }
795         else if (tableName.equalsIgnoreCase("Controller")) {
796             return deleteControllerRow(node, uuid);
797         }
798         else if (tableName.equalsIgnoreCase("Interface")) {
799             return deleteInterfaceRow(node, uuid);
800         }
801         else if (tableName.equalsIgnoreCase("Manager")) {
802             return deleteManagerRow(node, uuid);
803         }
804         else if (tableName.equalsIgnoreCase("Mirror")) {
805             return deleteMirrorRow(node, uuid);
806         }
807         else if (tableName.equalsIgnoreCase("NetFlow")) {
808             return deleteNetFlowRow(node, uuid);
809         }
810         else if (tableName.equalsIgnoreCase("Open_vSwitch")) {
811             return deleteOpen_vSwitchRow(node, uuid);
812         }
813         else if (tableName.equalsIgnoreCase("Port")) {
814             return deletePortRow(node, uuid);
815         }
816         else if (tableName.equalsIgnoreCase("QoS")) {
817             return deleteQosRow(node, uuid);
818         }
819         else if (tableName.equalsIgnoreCase("Queue")) {
820             return deleteQueueRow(node, uuid);
821         }
822         else if (tableName.equalsIgnoreCase("sFlow")) {
823             return deleteSflowRow(node, uuid);
824         }
825         else if (tableName.equalsIgnoreCase("SSL")) {
826             return deleteSSLRow(node, uuid);
827         }
828         return new Status(StatusCode.NOTFOUND, "Table "+tableName+" not supported");
829     }
830
831     @Override
832     public Map<String, Table<?>> getRows(Node node, String tableName) throws Exception{
833         try{
834             if (inventoryServiceInternal == null) {
835                 throw new Exception("Inventory Service is Unavailable.");
836             }
837             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, tableName);
838             return ovsTable;
839         } catch(Exception e){
840             throw new Exception("Unable to read table due to "+e.getMessage());
841         }
842     }
843
844     @Override
845     public Table<?> getRow(Node node, String tableName, String uuid) throws Exception {
846         try{
847             if (inventoryServiceInternal == null) {
848                 throw new Exception("Inventory Service is Unavailable.");
849             }
850             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, tableName);
851             if (ovsTable == null) return null;
852             return ovsTable.get(uuid);
853         } catch(Exception e){
854             throw new Exception("Unable to read table due to "+e.getMessage());
855         }
856     }
857
858     @Override
859     public String getSerializedRows(Node node, String tableName) throws Exception{
860         try{
861             Map<String, Table<?>> ovsTable = this.getRows(node, tableName);
862             if (ovsTable == null) return null;
863             ObjectMapper mapper = new ObjectMapper();
864             return mapper.writeValueAsString(ovsTable);
865         } catch(Exception e){
866             throw new Exception("Unable to read table due to "+e.getMessage());
867         }
868     }
869
870     @Override
871     public String getSerializedRow(Node node, String tableName, String uuid) throws Exception {
872         try{
873             Table<?> row = this.getRow(node, tableName, uuid);
874             if (row == null) return null;
875             ObjectMapper mapper = new ObjectMapper();
876             return mapper.writeValueAsString(row);
877         } catch(Exception e){
878             throw new Exception("Unable to read table due to "+e.getMessage());
879         }
880     }
881
882     @Override
883     public List<String> getTables(Node node) {
884         // TODO Auto-generated method stub
885         return null;
886     }
887
888     private StatusWithUuid insertBridgeRow(Node node, String open_VSwitch_uuid, Bridge bridgeRow) {
889
890         String insertErrorMsg = "bridge";
891         String rowName=bridgeRow.getName();
892
893         try{
894             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
895
896             if (ovsTable == null) {
897                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
898             }
899
900             String newBridge = "new_bridge";
901
902             Operation addSwitchRequest = null;
903
904             String ovsTableUUID = open_VSwitch_uuid;
905             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
906             UUID bridgeUuid = new UUID(newBridge);
907             Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuid);
908             List<Mutation> mutations = new ArrayList<Mutation>();
909             mutations.add(bm);
910
911             UUID uuid = new UUID(ovsTableUUID);
912             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
913             List<Condition> where = new ArrayList<Condition>();
914             where.add(condition);
915             addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
916
917             InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
918
919             TransactBuilder transaction = new TransactBuilder();
920             transaction.addOperations(new ArrayList<Operation>(
921                                       Arrays.asList(addSwitchRequest,
922                                                     addBridgeRequest)));
923
924             int bridgeInsertIndex = transaction.getRequests().indexOf(addBridgeRequest);
925
926             return _insertTableRow(node,transaction,bridgeInsertIndex,insertErrorMsg,rowName);
927
928         } catch(Exception e){
929             logger.error("Error in insertBridgeRow(): ",e);
930         }
931         return new StatusWithUuid(StatusCode.INTERNALERROR);
932     }
933
934
935     private StatusWithUuid insertPortRow(Node node, String bridge_uuid, Port portRow) {
936
937         String insertErrorMsg = "port";
938         String rowName=portRow.getName();
939
940         try{
941             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
942             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
943                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
944             }
945             String newPort = "new_port";
946             UUID portUUID = new UUID(newPort);
947             Mutation bm = new Mutation("ports", Mutator.INSERT, portUUID);
948             List<Mutation> mutations = new ArrayList<Mutation>();
949             mutations.add(bm);
950
951             UUID uuid = new UUID(bridge_uuid);
952             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
953             List<Condition> where = new ArrayList<Condition>();
954             where.add(condition);
955             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
956
957             // Default OVS schema is to have 1 or more interface part of Bridge. Hence it is mandatory to
958             // Insert an Interface in a Port add case
959
960             String newInterface = "new_interface";
961             Interface interfaceRow = new Interface();
962             interfaceRow.setName(portRow.getName());
963             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
964                     newInterface, interfaceRow);
965
966             OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
967             UUID interfaceid = new UUID(newInterface);
968             interfaces.add(interfaceid);
969             portRow.setInterfaces(interfaces);
970
971             InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
972
973             TransactBuilder transaction = new TransactBuilder();
974             transaction.addOperations(new ArrayList<Operation>
975             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
976             int portInsertIndex = transaction.getRequests().indexOf(addPortRequest);
977
978             return _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
979
980             } catch (Exception e) {
981             logger.error("Error in insertPortRow(): ",e);
982         }
983         return new StatusWithUuid(StatusCode.INTERNALERROR);
984     }
985
986     private StatusWithUuid insertInterfaceRow(Node node, String port_uuid, Interface interfaceRow) {
987
988         String insertErrorMsg = "interface";
989         String rowName=interfaceRow.getName();
990
991         try{
992
993             // Interface table must have entry in Port table, checking port table for port
994             Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
995             if (portTable == null ||  portTable.get(port_uuid) == null) {
996                 return new StatusWithUuid(StatusCode.NOTFOUND, "Port with UUID "+port_uuid+" Not found");
997             }
998             // MUTATOR, need to insert the interface UUID to LIST of interfaces in PORT TABLE for port_uuid
999             String newInterface = "new_interface";
1000             UUID interfaceUUID = new UUID(newInterface);
1001             Mutation portTableMutation = new Mutation("interfaces", Mutator.INSERT, interfaceUUID); // field name to append is "interfaces"
1002             List<Mutation> mutations = new ArrayList<Mutation>();
1003             mutations.add(portTableMutation);
1004
1005             // Create the Operation which will be used in Transact to perform the PORT TABLE mutation
1006             UUID uuid = new UUID(port_uuid);
1007             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1008             List<Condition> where = new ArrayList<Condition>();
1009             where.add(condition);
1010             Operation addPortMutationRequest = new MutateOperation(Port.NAME.getName(), where, mutations);
1011
1012             // Create the interface row request
1013             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),newInterface, interfaceRow);
1014
1015             // Transaction to insert/modify tables - validate using "sudo ovsdb-client dump" on host running OVSDB process
1016             TransactBuilder transaction = new TransactBuilder();
1017             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addIntfRequest,addPortMutationRequest)));
1018
1019             // Check the results. Iterates over the results of the Array of transaction Operations, and reports STATUS
1020             int interfaceInsertIndex = transaction.getRequests().indexOf(addIntfRequest);
1021
1022             return _insertTableRow(node,transaction,interfaceInsertIndex,insertErrorMsg,rowName);
1023
1024         } catch (Exception e) {
1025             logger.error("Error in insertInterfaceRow(): ",e);
1026         }
1027         return new StatusWithUuid(StatusCode.INTERNALERROR);
1028     }
1029
1030     private StatusWithUuid insertOpen_vSwitchRow(Node node, Open_vSwitch row) {
1031         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1032     }
1033
1034     private StatusWithUuid insertControllerRow(Node node, String bridge_uuid, Controller row) {
1035
1036         String insertErrorMsg = "controller";
1037         String rowName=row.getTableName().toString();
1038
1039         try{
1040
1041             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1042             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
1043                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
1044             }
1045
1046             Map<String, Table<?>> controllerCache = inventoryServiceInternal.getTableCache(node, Controller.NAME.getName());
1047
1048             String uuid_name = "new_controller";
1049             boolean controllerExists = false;
1050             if (controllerCache != null) {
1051                 for (String uuid : controllerCache.keySet()) {
1052                     Controller controller = (Controller)controllerCache.get(uuid);
1053                     if (controller.getTarget().equals(row.getTarget())) {
1054                         uuid_name = uuid;
1055                         controllerExists = true;
1056                         break;
1057                     }
1058                 }
1059             }
1060
1061             UUID controllerUUID = new UUID(uuid_name);
1062             Mutation bm = new Mutation("controller", Mutator.INSERT, controllerUUID);
1063             List<Mutation> mutations = new ArrayList<Mutation>();
1064             mutations.add(bm);
1065
1066             UUID uuid = new UUID(bridge_uuid);
1067             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1068             List<Condition> where = new ArrayList<Condition>();
1069             where.add(condition);
1070             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1071             InsertOperation addControllerRequest = null;
1072
1073             TransactBuilder transaction = new TransactBuilder();
1074             transaction.addOperation(addBrMutRequest);
1075             int portInsertIndex = -1;
1076             if (!controllerExists) {
1077                 addControllerRequest = new InsertOperation(Controller.NAME.getName(), uuid_name, row);
1078                 transaction.addOperation(addControllerRequest);
1079                 portInsertIndex = transaction.getRequests().indexOf(addControllerRequest);
1080             }
1081
1082             StatusWithUuid status = _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
1083             if (status.isSuccess() && controllerExists) {
1084                 // We won't get the uuid from the transact, so we set it here
1085                 status = new StatusWithUuid(status.getCode(), controllerUUID);
1086             }
1087             return status;
1088
1089         } catch (Exception e) {
1090             logger.error("Error in insertControllerRow(): ",e);
1091         }
1092         return new StatusWithUuid(StatusCode.INTERNALERROR);
1093     }
1094
1095     private StatusWithUuid insertSSLRow(Node node, String parent_uuid, SSL row) {
1096         String insertErrorMsg = "SSL";
1097         String rowName=row.NAME.getName();
1098
1099         try{
1100             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
1101
1102             if (ovsTable == null) {
1103                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
1104             }
1105
1106             String newSSL = "new_SSL";
1107
1108             Operation addOpen_vSwitchRequest = null;
1109
1110             String ovsTableUUID = parent_uuid;
1111             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
1112             UUID sslUuid = new UUID(newSSL);
1113             Mutation sslMutation = new Mutation("ssl", Mutator.INSERT, sslUuid);
1114             List<Mutation> mutations = new ArrayList<Mutation>();
1115             mutations.add(sslMutation);
1116
1117             UUID uuid = new UUID(ovsTableUUID);
1118             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1119             List<Condition> where = new ArrayList<Condition>();
1120             where.add(condition);
1121             addOpen_vSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
1122
1123             InsertOperation addSSLRequest = new InsertOperation(SSL.NAME.getName(), newSSL, row);
1124
1125             TransactBuilder transaction = new TransactBuilder();
1126             transaction.addOperations(new ArrayList<Operation>(
1127                                       Arrays.asList(addSSLRequest,
1128                                                     addOpen_vSwitchRequest)));
1129
1130             int sslInsertIndex = transaction.getRequests().indexOf(addSSLRequest);
1131
1132             return _insertTableRow(node,transaction,sslInsertIndex,insertErrorMsg,rowName);
1133
1134         } catch(Exception e){
1135             logger.error("Error in insertSSLRow(): ",e);
1136         }
1137         return new StatusWithUuid(StatusCode.INTERNALERROR);
1138     }
1139
1140     private StatusWithUuid insertSflowRow(Node node, String parent_uuid, SFlow row) {
1141
1142         String insertErrorMsg = "sFlow";
1143         String rowName=row.NAME.getName();
1144
1145         try{
1146             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1147             if (brTable == null ||  brTable.get(parent_uuid) == null) {
1148                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
1149             }
1150
1151             if (parent_uuid == null) {
1152                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
1153             }
1154
1155             UUID uuid = new UUID(parent_uuid);
1156
1157             String newSflow = "new_sflow";
1158
1159             Operation addBridgeRequest = null;
1160
1161             UUID sflowUuid = new UUID(newSflow);
1162             Mutation sflowMutation = new Mutation("sflow", Mutator.INSERT, sflowUuid);
1163             List<Mutation> mutations = new ArrayList<Mutation>();
1164             mutations.add(sflowMutation);
1165
1166             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1167             List<Condition> where = new ArrayList<Condition>();
1168             where.add(condition);
1169             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1170
1171             InsertOperation addSflowRequest = new InsertOperation(SFlow.NAME.getName(), newSflow, row);
1172
1173             TransactBuilder transaction = new TransactBuilder();
1174             transaction.addOperations(new ArrayList<Operation>(
1175                                       Arrays.asList(addSflowRequest,
1176                                                     addBridgeRequest)));
1177
1178             int sflowInsertIndex = transaction.getRequests().indexOf(addSflowRequest);
1179
1180
1181             return _insertTableRow(node,transaction,sflowInsertIndex,insertErrorMsg,rowName);
1182
1183         } catch (Exception e) {
1184             logger.error("Error in insertInterfaceRow(): ",e);
1185         }
1186         return new StatusWithUuid(StatusCode.INTERNALERROR);
1187     }
1188
1189     private StatusWithUuid insertQueueRow(Node node, String parent_uuid, Queue row) {
1190         String insertErrorMsg = "Queue";
1191         String rowName=row.NAME.getName();
1192
1193         try{
1194             Map<String, Table<?>> qosTable = inventoryServiceInternal.getTableCache(node, Qos.NAME.getName());
1195             if (qosTable == null ||  qosTable.get(parent_uuid) == null) {
1196                 return new StatusWithUuid(StatusCode.NOTFOUND, "QoS with UUID "+parent_uuid+" Not found");
1197             }
1198
1199             if (parent_uuid == null) {
1200                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent QoS UUID.");
1201             }
1202
1203             // NOTE: Queue Table is "isroot" meaning it can have a hanging reference. This is different from
1204             // standing insertRow due to the parent column type being a map, where one of the items may not be known
1205             // at time of insert. Therefore this is a simple insert, rather than mutate/insert.
1206             String newQueue = "new_queue";
1207             InsertOperation addQueueRequest = new InsertOperation(Queue.NAME.getName(), newQueue, row);
1208
1209             TransactBuilder transaction = new TransactBuilder();
1210             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQueueRequest)));
1211
1212             int queueInsertIndex = transaction.getRequests().indexOf(addQueueRequest);
1213
1214             return _insertTableRow(node,transaction,queueInsertIndex,insertErrorMsg,rowName);
1215
1216         } catch (Exception e) {
1217             logger.error("Error in insertQueueRow(): ",e);
1218         }
1219         return new StatusWithUuid(StatusCode.INTERNALERROR);    }
1220
1221     private StatusWithUuid insertQosRow(Node node, String parent_uuid, Qos row) {
1222         String insertErrorMsg = "Qos";
1223         String rowName=row.NAME.getName();
1224
1225         try{
1226
1227             String newQos = "new_qos";
1228
1229             // QoS Table "isroot" meaning it can have hanging references. If parent_uuid is not supplied in API call this becomes a simple
1230             // insert operation, rather than the typical mutate/insert parent/child insert.
1231             if (parent_uuid != null) {
1232                 // Port (parent) table check for UUID existance.
1233                 Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1234                 if (portTable == null ||  portTable.get(parent_uuid) == null) {
1235                     return new StatusWithUuid(StatusCode.NOTFOUND, "Port with UUID "+parent_uuid+" Not found");
1236                 }
1237
1238                 UUID qosUuid = new UUID(newQos);
1239                 Mutation qosMutation = new Mutation("qos", Mutator.INSERT, qosUuid);
1240                 List<Mutation> mutations = new ArrayList<Mutation>();
1241                 mutations.add(qosMutation);
1242
1243                 Operation addPortRequest = null;
1244                 UUID uuid = new UUID(parent_uuid);
1245                 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1246                 List<Condition> where = new ArrayList<Condition>();
1247                 where.add(condition);
1248                 addPortRequest = new MutateOperation(Port.NAME.getName(), where, mutations);
1249
1250                 InsertOperation addQosRequest = new InsertOperation(Qos.NAME.getName(), newQos, row);
1251
1252                 TransactBuilder transaction = new TransactBuilder();
1253                 transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQosRequest,addPortRequest)));
1254
1255                 int qosInsertIndex = transaction.getRequests().indexOf(addQosRequest);
1256
1257                 return _insertTableRow(node,transaction,qosInsertIndex,insertErrorMsg,rowName);
1258
1259             } else {
1260                 InsertOperation addQosRequest = new InsertOperation(Qos.NAME.getName(), newQos, row);
1261
1262                 TransactBuilder transaction = new TransactBuilder();
1263                 transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQosRequest)));
1264
1265                 int qosInsertIndex = transaction.getRequests().indexOf(addQosRequest);
1266
1267                 return _insertTableRow(node,transaction,qosInsertIndex,insertErrorMsg,rowName);
1268             }
1269
1270         } catch (Exception e) {
1271             logger.error("Error in insertQosRow(): ",e);
1272         }
1273         return new StatusWithUuid(StatusCode.INTERNALERROR);
1274     }
1275
1276
1277     private StatusWithUuid insertNetFlowRow(Node node, String parent_uuid, NetFlow row) {
1278         String insertErrorMsg = "netFlow";
1279         String rowName=row.NAME.getName();
1280
1281         try{
1282             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1283             if (brTable == null ||  brTable.get(parent_uuid) == null) {
1284                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
1285             }
1286
1287             if (parent_uuid == null) {
1288                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
1289             }
1290
1291             UUID uuid = new UUID(parent_uuid);
1292             String newNetflow = "new_netflow";
1293
1294             Operation addBridgeRequest = null;
1295
1296             UUID netFlowUuid = new UUID(newNetflow);
1297             Mutation netFlowMutation = new Mutation("netflow", Mutator.INSERT, netFlowUuid);
1298             List<Mutation> mutations = new ArrayList<Mutation>();
1299             mutations.add(netFlowMutation);
1300
1301             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1302             List<Condition> where = new ArrayList<Condition>();
1303             where.add(condition);
1304             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1305
1306             InsertOperation addNetflowRequest = new InsertOperation(NetFlow.NAME.getName(), newNetflow, row);
1307
1308             TransactBuilder transaction = new TransactBuilder();
1309             transaction.addOperations(new ArrayList<Operation>(
1310                                       Arrays.asList(addNetflowRequest,
1311                                                     addBridgeRequest)));
1312
1313             int netflowInsertIndex = transaction.getRequests().indexOf(addNetflowRequest);
1314
1315
1316             return _insertTableRow(node,transaction,netflowInsertIndex,insertErrorMsg,rowName);
1317
1318         } catch (Exception e) {
1319             logger.error("Error in insertNetFlowRow(): ",e);
1320         }
1321         return new StatusWithUuid(StatusCode.INTERNALERROR);
1322     }
1323
1324     private StatusWithUuid insertMirrorRow(Node node, String parent_uuid, Mirror row) {
1325         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1326     }
1327
1328     private StatusWithUuid insertManagerRow(Node node, String parent_uuid, Manager row) {
1329         String insertErrorMsg = "manager";
1330         String rowName=row.NAME.getName();
1331
1332         try{
1333             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
1334
1335             if (ovsTable == null) {
1336                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
1337             }
1338
1339             String newManager = "new_manager";
1340
1341             Operation addSwitchRequest = null;
1342
1343             String ovsTableUUID = parent_uuid;
1344             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
1345             UUID managerUuid = new UUID(newManager);
1346             Mutation managerMutation = new Mutation("manager_options", Mutator.INSERT, managerUuid);
1347             List<Mutation> mutations = new ArrayList<Mutation>();
1348             mutations.add(managerMutation);
1349
1350             UUID uuid = new UUID(ovsTableUUID);
1351             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1352             List<Condition> where = new ArrayList<Condition>();
1353             where.add(condition);
1354             addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
1355
1356             InsertOperation addManagerRequest = new InsertOperation(Manager.NAME.getName(), newManager, row);
1357
1358             TransactBuilder transaction = new TransactBuilder();
1359             transaction.addOperations(new ArrayList<Operation>(
1360                                       Arrays.asList(addSwitchRequest,
1361                                                     addManagerRequest)));
1362
1363             int managerInsertIndex = transaction.getRequests().indexOf(addManagerRequest);
1364
1365             return _insertTableRow(node,transaction,managerInsertIndex,insertErrorMsg,rowName);
1366
1367         } catch(Exception e){
1368             logger.error("Error in insertManagerRow(): ",e);
1369         }
1370         return new StatusWithUuid(StatusCode.INTERNALERROR);
1371     }
1372
1373     private StatusWithUuid _insertTableRow(Node node, TransactBuilder transaction, Integer insertIndex, String insertErrorMsg,String rowName){
1374
1375         try{
1376             //Check for connection before calling RPC to perform transaction
1377             if (connectionService == null) {
1378                 logger.error("Couldn't refer to the ConnectionService");
1379                 return new StatusWithUuid(StatusCode.NOSERVICE);
1380             }
1381
1382             Connection connection = this.getConnection(node);
1383             if (connection == null) {
1384                 return new StatusWithUuid(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1385             }
1386
1387             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1388             List<OperationResult> tr = transResponse.get();
1389             List<Operation> requests = transaction.getRequests();
1390             StatusWithUuid status = new StatusWithUuid(StatusCode.SUCCESS);
1391             for (int i = 0; i < tr.size() ; i++) {
1392                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1393                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1394                     OperationResult result = tr.get(i);
1395                     status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1396                 }
1397             }
1398
1399             if (tr.size() > requests.size()) {
1400                 OperationResult result = tr.get(tr.size()-1);
1401                 logger.error("Error creating {} : {}\n Error : {}\n Details : {}",     insertErrorMsg,
1402                                                                                        rowName,
1403                                                                                        result.getError(),
1404                                                                                        result.getDetails());
1405                 status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1406             }
1407             if (status.isSuccess()) {
1408                 if (insertIndex >0 && insertIndex < tr.size() && tr.get(insertIndex) != null) {
1409                     UUID uuid = tr.get(insertIndex).getUuid();
1410                     status = new StatusWithUuid(StatusCode.SUCCESS, uuid);
1411                 } else {
1412                     // We can't get the uuid from the transact as the insertIndex is invalid or -1
1413                     // return null uuid.
1414                     status = new StatusWithUuid(StatusCode.SUCCESS, (UUID) null);
1415                 }
1416             }
1417             return status;
1418         } catch(Exception e){
1419             logger.error("Error in _insertTableRow(): ",e);
1420         }
1421         return new StatusWithUuid(StatusCode.INTERNALERROR);
1422     }
1423
1424
1425     private Status deleteBridgeRow(Node node, String uuid) {
1426         // Set up variables for generic _deleteTableRow()
1427         String parentTableName=Open_vSwitch.NAME.getName();
1428         String childTableName=Bridge.NAME.getName();
1429         String parentColumn = "bridges";
1430
1431         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1432     }
1433
1434     private Status deletePortRow(Node node, String uuid) {
1435         // Set up variables for generic _deleteTableRow()
1436         String parentTableName=Bridge.NAME.getName();
1437         String childTableName=Port.NAME.getName();
1438         String parentColumn = "ports";
1439
1440         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1441     }
1442
1443     private Status deleteInterfaceRow(Node node, String uuid) {
1444         // Since Port<-Interface tables have a 1:n relationship, need to test if this is the last interface
1445         // assigned to a port before attempting delete.
1446         Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1447         Map<String, Table<?>> interfaceTable = inventoryServiceInternal.getTableCache(node, Interface.NAME.getName());
1448         // Check that the UUID exists
1449         if (portTable == null || interfaceTable == null || uuid == null || interfaceTable.get(uuid) == null) {
1450             return new Status(StatusCode.NOTFOUND, "");
1451         }
1452
1453         // Since the above past, it's safe to use the generic _deleteTableRow method
1454         // Set up variables for generic _deleteTableRow()
1455         String parentTableName=Port.NAME.getName();
1456         String childTableName=Interface.NAME.getName();
1457         String parentColumn = "interfaces";
1458
1459         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1460     }
1461
1462     private Status deleteControllerRow(Node node, String uuid) {
1463         // Set up variables for generic _deleteTableRow()
1464         String parentTableName=Bridge.NAME.getName();
1465         String childTableName=Controller.NAME.getName();
1466         String parentColumn = "controller";
1467
1468         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1469     }
1470
1471     private Status deleteOpen_vSwitchRow(Node node, String uuid) {
1472         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1473     }
1474
1475     private Status deleteSSLRow(Node node, String uuid) {
1476         // Set up variables for generic _deleteTableRow()
1477         String parentTableName=Open_vSwitch.NAME.getName();
1478         String childTableName=SSL.NAME.getName();
1479         String parentColumn = "ssl";
1480
1481         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1482     }
1483
1484     private Status deleteSflowRow(Node node, String uuid) {
1485         // Set up variables for generic _deleteTableRow()
1486         String parentTableName=Bridge.NAME.getName();
1487         String childTableName=SFlow.NAME.getName();
1488         String parentColumn = "sflow";
1489
1490         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1491     }
1492
1493     private Status deleteQueueRow(Node node, String uuid) {
1494         // Set up variables for _deleteRootTableRow()
1495         // This doesn't do a mutate on parent, but simply deletes row
1496         String childTableName=Queue.NAME.getName();
1497
1498         return _deleteRootTableRow(node,uuid,childTableName);
1499     }
1500
1501     private Status deleteQosRow(Node node, String uuid) {
1502         // Set up variables for generic _deleteTableRow()
1503         String parentTableName=Port.NAME.getName();
1504         String childTableName=Qos.NAME.getName();
1505         String parentColumn = "qos";
1506
1507         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1508     }
1509
1510     private Status deleteNetFlowRow(Node node, String uuid) {
1511         // Set up variables for generic _deleteTableRow()
1512         String parentTableName=Bridge.NAME.getName();
1513         String childTableName=NetFlow.NAME.getName();
1514         String parentColumn = "netflow";
1515
1516         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1517     }
1518
1519     private Status deleteMirrorRow(Node node, String uuid) {
1520         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1521     }
1522
1523     private Status deleteManagerRow(Node node, String uuid) {
1524         // Set up variables for generic _deleteTableRow()
1525         String parentTableName=Open_vSwitch.NAME.getName();
1526         String childTableName=Manager.NAME.getName();
1527         String parentColumn = "manager_options";
1528
1529         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1530     }
1531
1532     private Status _deleteTableRow(Node node,String uuid,String parentTableName, String childTableName, String parentColumn) {
1533         try {
1534             // Check there is a connectionService
1535             if (connectionService == null) {
1536                 logger.error("Couldn't refer to the ConnectionService");
1537                 return new Status(StatusCode.NOSERVICE);
1538             }
1539
1540             // Establish the connection
1541             Connection connection = this.getConnection(node);
1542             if (connection == null) {
1543                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1544             }
1545
1546             // Remove from Parent and Child
1547             Map<String, Table<?>> parentTable = inventoryServiceInternal.getTableCache(node, parentTableName);
1548             Map<String, Table<?>> childTable = inventoryServiceInternal.getTableCache(node, childTableName);
1549
1550             // Check that the UUID exists
1551             if (parentTable == null || childTable == null || uuid == null || childTable.get(uuid) == null) {
1552                 return new Status(StatusCode.NOTFOUND, "");
1553             }
1554
1555             // Initialise the actual request var
1556             Operation delRequest = null;
1557
1558             // Prepare the mutator to remove the child UUID from the parentColumn list in the parent TABLE
1559             UUID rowUuid = new UUID(uuid);
1560             Mutation mutator = new Mutation(parentColumn, Mutator.DELETE, rowUuid);
1561             List<Mutation> mutations = new ArrayList<Mutation>();
1562             mutations.add(mutator);
1563
1564             Status status = new Status(StatusCode.SUCCESS);
1565
1566             // INCLUDES condition ensures that it captures all rows in the parent table (ie duplicates) that have the child UUID
1567             Condition condition = new Condition(parentColumn, Function.INCLUDES, rowUuid);
1568             List<Condition> where = new ArrayList<Condition>();
1569             where.add(condition);
1570             delRequest = new MutateOperation(parentTableName, where, mutations);
1571
1572             TransactBuilder transaction = new TransactBuilder();
1573             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delRequest)));
1574
1575             // This executes the transaction.
1576             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1577
1578             // Pull the responses
1579             List<OperationResult> tr = transResponse.get();
1580             List<Operation> requests = transaction.getRequests();
1581
1582             for (int i = 0; i < tr.size(); i++) {
1583                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1584                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1585                     OperationResult result = tr.get(i);
1586                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1587                 }
1588             }
1589
1590             if (tr.size() > requests.size()) {
1591                 OperationResult result = tr.get(tr.size() - 1);
1592                 logger.error("Error deleting: {}\n Error : {}\n Details : {}",
1593                         uuid, result.getError(), result.getDetails());
1594                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1595             }
1596             return status;
1597         } catch (Exception e) {
1598             logger.error("Error in _deleteTableRow",e);
1599         }
1600         return new Status(StatusCode.INTERNALERROR);
1601     }
1602
1603     private Status _deleteRootTableRow(Node node,String uuid,String TableName) {
1604         try {
1605             // Check there is a connectionService
1606             if (connectionService == null) {
1607                 logger.error("Couldn't refer to the ConnectionService");
1608                 return new Status(StatusCode.NOSERVICE);
1609             }
1610
1611             // Establish the connection
1612             Connection connection = this.getConnection(node);
1613             if (connection == null) {
1614                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1615             }
1616
1617             Map<String, Table<?>> table = inventoryServiceInternal.getTableCache(node, TableName);
1618
1619             // Check that the UUID exists
1620             if (table == null || table.get(uuid) == null) {
1621                 return new Status(StatusCode.NOTFOUND, "");
1622             }
1623
1624             // Initialise the actual request var
1625             Operation delRequest = null;
1626
1627             UUID rowUuid = new UUID(uuid);
1628
1629             Status status = new Status(StatusCode.SUCCESS);
1630
1631             Condition condition = new Condition("_uuid", Function.EQUALS, rowUuid);
1632             List<Condition> where = new ArrayList<Condition>();
1633             where.add(condition);
1634             delRequest = new DeleteOperation(TableName, where);
1635
1636             TransactBuilder transaction = new TransactBuilder();
1637             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delRequest)));
1638
1639             // This executes the transaction.
1640             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1641
1642             // Pull the responses
1643             List<OperationResult> tr = transResponse.get();
1644             List<Operation> requests = transaction.getRequests();
1645
1646             for (int i = 0; i < tr.size(); i++) {
1647                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1648                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1649                     OperationResult result = tr.get(i);
1650                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1651                 }
1652             }
1653
1654             if (tr.size() > requests.size()) {
1655                 OperationResult result = tr.get(tr.size() - 1);
1656                 logger.error("Error deleting: {}\n Error : {}\n Details : {}",
1657                         uuid, result.getError(), result.getDetails());
1658                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1659             }
1660             return status;
1661         } catch (Exception e) {
1662             logger.error("Error in _deleteRootTableRow",e);
1663         }
1664         return new Status(StatusCode.INTERNALERROR);
1665     }
1666
1667     public void _ovsconnect (CommandInterpreter ci) {
1668         String bridgeName = ci.nextArgument();
1669         if (bridgeName == null) {
1670             ci.println("Please enter Bridge Name");
1671             return;
1672         }
1673
1674         String ovsdbserver = ci.nextArgument();
1675         if (ovsdbserver == null) {
1676             ci.println("Please enter valid IP-Address");
1677             return;
1678         }
1679         try {
1680             InetAddress.getByName(ovsdbserver);
1681         }  catch (UnknownHostException e) {
1682             logger.error("Unable to resolve " + ovsdbserver, e);
1683             ci.println("Please enter valid IP-Address");
1684             return;
1685         }
1686         String port = ci.nextArgument();
1687         if (port == null) {
1688             port = "6634";
1689         }
1690
1691         ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
1692         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
1693         params.put(ConnectionConstants.ADDRESS, ovsdbserver);
1694         params.put(ConnectionConstants.PORT, port);
1695         Node node = connectionService.connect(bridgeName, params);
1696         if (node != null) ci.println("Node Name: "+node.toString());
1697         else ci.println("Could not connect to Node");
1698     }
1699
1700     public void _addBridge (CommandInterpreter ci) {
1701         String nodeName = ci.nextArgument();
1702         if (nodeName == null) {
1703             ci.println("Please enter Node Name");
1704             return;
1705         }
1706         String bridgeName = ci.nextArgument();
1707         if (bridgeName == null) {
1708             ci.println("Please enter Bridge Name");
1709             return;
1710         }
1711         Status status;
1712
1713         Node node = Node.fromString(nodeName);
1714         if (node == null) {
1715             ci.println("Invalid Node");
1716             return;
1717         }
1718         status = this.createBridgeDomain(node, bridgeName, null);
1719         ci.println("Bridge creation status : "+status.toString());
1720     }
1721
1722     public void _getBridgeDomains (CommandInterpreter ci) {
1723         String nodeName = ci.nextArgument();
1724         if (nodeName == null) {
1725             ci.println("Please enter Node Name");
1726             return;
1727         }
1728
1729         List<String> brlist = new ArrayList<String>();
1730         Node node = Node.fromString(nodeName);
1731         brlist = this.getBridgeDomains(node);
1732         if (node == null) {
1733             ci.println("Invalid Node");
1734             return;
1735         }
1736         ci.println("Existing Bridges: "+brlist.toString());
1737     }
1738
1739     public void _deleteBridgeDomain (CommandInterpreter ci) {
1740         String nodeName = ci.nextArgument();
1741         if (nodeName == null) {
1742             ci.println("Please enter Node Name");
1743             return;
1744         }
1745         String bridgeName = ci.nextArgument();
1746         if (bridgeName == null) {
1747             ci.println("Please enter Bridge Name");
1748             return;
1749         }
1750         Status status;
1751         Node node = Node.fromString(nodeName);
1752         if (node == null) {
1753             ci.println("Invalid Node");
1754             return;
1755         }
1756         status = this.deleteBridgeDomain(node, bridgeName);
1757         ci.println("Bridge deletion status : "+status.toString());
1758     }
1759
1760     public void _addPort (CommandInterpreter ci) {
1761         String nodeName = ci.nextArgument();
1762         if (nodeName == null) {
1763             ci.println("Please enter Node Name");
1764             return;
1765         }
1766
1767         String bridgeName = ci.nextArgument();
1768         if (bridgeName == null) {
1769             ci.println("Please enter Bridge Name");
1770             return;
1771         }
1772
1773         String portName = ci.nextArgument();
1774         if (portName == null) {
1775             ci.println("Please enter Port Name");
1776             return;
1777         }
1778
1779         String type = ci.nextArgument();
1780
1781         Map<String, String> configs = new HashMap<String, String>();
1782         while(true) {
1783             String configKey = ci.nextArgument();
1784             if (configKey == null) break;
1785             String configValue = ci.nextArgument();
1786             if (configValue == null) break;
1787             configs.put(configKey, configValue);
1788         }
1789
1790         Map<ConfigConstants, Object> customConfigs = null;
1791         if (type != null) {
1792             customConfigs = new HashMap<ConfigConstants, Object>();
1793             customConfigs.put(ConfigConstants.TYPE, type);
1794         }
1795
1796         if (configs.size() > 0) {
1797             if (customConfigs == null) customConfigs = new HashMap<ConfigConstants, Object>();
1798             customConfigs.put(ConfigConstants.CUSTOM, configs);
1799             ci.println(customConfigs.toString());
1800         }
1801         Status status;
1802         Node node = Node.fromString(nodeName);
1803         if (node == null) {
1804             ci.println("Invalid Node");
1805             return;
1806         }
1807         status = this.addPort(node, bridgeName, portName, customConfigs);
1808         ci.println("Port creation status : "+status.toString());
1809     }
1810
1811     public void _deletePort (CommandInterpreter ci) {
1812         String nodeName = ci.nextArgument();
1813         if (nodeName == null) {
1814             ci.println("Please enter Node Name");
1815             return;
1816         }
1817
1818         String bridgeName = ci.nextArgument();
1819         if (bridgeName == null) {
1820             ci.println("Please enter Bridge Name");
1821             return;
1822         }
1823
1824         String portName = ci.nextArgument();
1825         if (portName == null) {
1826             ci.println("Please enter Port Name");
1827             return;
1828         }
1829
1830         Status status;
1831         Node node = Node.fromString(nodeName);
1832         if (node == null) {
1833             ci.println("Invalid Node");
1834             return;
1835         }
1836         status = this.deletePort(node, bridgeName, portName);
1837         ci.println("Port deletion status : "+status.toString());
1838     }
1839
1840     public void _addPortVlan (CommandInterpreter ci) {
1841         String nodeName = ci.nextArgument();
1842         if (nodeName == null) {
1843             ci.println("Please enter Node Name");
1844             return;
1845         }
1846
1847         String bridgeName = ci.nextArgument();
1848         if (bridgeName == null) {
1849             ci.println("Please enter Bridge Name");
1850             return;
1851         }
1852
1853         String portName = ci.nextArgument();
1854         if (portName == null) {
1855             ci.println("Please enter Port Name");
1856             return;
1857         }
1858
1859         String vlan = ci.nextArgument();
1860         if (vlan == null) {
1861             ci.println("Please enter Valid Vlan");
1862             return;
1863         } else {
1864             try {
1865             Integer.parseInt(vlan);
1866             } catch (NumberFormatException e) {
1867                 ci.println("Please enter Valid Vlan");
1868                 return;
1869             }
1870         }
1871
1872         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1873         configs.put(ConfigConstants.TYPE, "VLAN");
1874         configs.put(ConfigConstants.VLAN, vlan);
1875
1876         Status status;
1877         Node node = Node.fromString(nodeName);
1878         if (node == null) {
1879             ci.println("Invalid Node");
1880             return;
1881         }
1882         status = this.addPort(node, bridgeName, portName, configs);
1883         ci.println("Port creation status : "+status.toString());
1884     }
1885
1886     public void _addTunnel (CommandInterpreter ci) {
1887         String nodeName = ci.nextArgument();
1888         if (nodeName == null) {
1889             ci.println("Please enter Node Name");
1890             return;
1891         }
1892
1893         String bridgeName = ci.nextArgument();
1894         if (bridgeName == null) {
1895             ci.println("Please enter Bridge Name");
1896             return;
1897         }
1898
1899         String portName = ci.nextArgument();
1900         if (portName == null) {
1901             ci.println("Please enter Port Name");
1902             return;
1903         }
1904
1905         String tunnelType = ci.nextArgument();
1906         if (tunnelType == null) {
1907             ci.println("Please enter Tunnel Type");
1908             return;
1909         }
1910
1911         String remoteIp = ci.nextArgument();
1912         if (remoteIp == null) {
1913             ci.println("Please enter valid Remote IP Address");
1914             return;
1915         }
1916
1917         try {
1918             InetAddress.getByName(remoteIp);
1919         }  catch (Exception e) {
1920             logger.error("Unable to resolve " + remoteIp, e);
1921             ci.println("Please enter valid Remote IP Address");
1922             return;
1923         }
1924
1925         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1926         configs.put(ConfigConstants.TYPE, "TUNNEL");
1927         configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
1928         configs.put(ConfigConstants.DEST_IP, remoteIp);
1929
1930         Status status;
1931         Node node = Node.fromString(nodeName);
1932         if (node == null) {
1933             ci.println("Invalid Node");
1934             return;
1935         }
1936         status = this.addPort(node, bridgeName, portName, configs);
1937         ci.println("Port creation status : "+status.toString());
1938     }
1939
1940     public void _printCache (CommandInterpreter ci) {
1941         String nodeName = ci.nextArgument();
1942         if (nodeName == null) {
1943             ci.println("Please enter Node Name");
1944             return;
1945         }
1946         Node node = Node.fromString(nodeName);
1947         if (node == null) {
1948             ci.println("Invalid Node");
1949             return;
1950         }
1951         inventoryServiceInternal.printCache(node);
1952     }
1953
1954     public void _forceConnect (CommandInterpreter ci) {
1955         String force = ci.nextArgument();
1956         if (force.equalsIgnoreCase("YES")) forceConnect = true;
1957         else if (force.equalsIgnoreCase("NO")) forceConnect = false;
1958         else ci.println("Please enter YES or NO.");
1959         ci.println("Current ForceConnect State : "+forceConnect);
1960         return;
1961     }
1962
1963     @Override
1964     public String getHelp() {
1965         StringBuffer help = new StringBuffer();
1966         help.append("---OVSDB CLI---\n");
1967         help.append("\t ovsconnect <ConnectionName> <ip-address>                        - Connect to OVSDB\n");
1968         help.append("\t addBridge <Node> <BridgeName>                                   - Add Bridge\n");
1969         help.append("\t getBridgeDomains <Node>                                         - Get Bridges\n");
1970         help.append("\t deleteBridgeDomain <Node> <BridgeName>                          - Delete a Bridge\n");
1971         help.append("\t addPort <Node> <BridgeName> <PortName> <type> <options pairs>   - Add Port\n");
1972         help.append("\t deletePort <Node> <BridgeName> <PortName>                       - Delete Port\n");
1973         help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan>               - Add Port, Vlan\n");
1974         help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip>      - Add Tunnel\n");
1975         help.append("\t printCache <Node>                                               - Prints Table Cache");
1976         return help.toString();
1977     }
1978 }
1979