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