Merge "Added the missing Copyright headers to most of the java files."
[ovsdb.git] / ovsdb / 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
22 import org.eclipse.osgi.framework.console.CommandInterpreter;
23 import org.eclipse.osgi.framework.console.CommandProvider;
24 import org.opendaylight.controller.sal.connection.ConnectionConstants;
25 import org.opendaylight.controller.sal.core.Node;
26 import org.opendaylight.controller.sal.core.NodeConnector;
27 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
28 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
29 import org.opendaylight.controller.sal.utils.Status;
30 import org.opendaylight.controller.sal.utils.StatusCode;
31 import org.opendaylight.ovsdb.lib.database.OVSInstance;
32 import org.opendaylight.ovsdb.lib.database.OvsdbType;
33 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
34 import org.opendaylight.ovsdb.lib.message.operations.DeleteOperation;
35 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
36 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
37 import org.opendaylight.ovsdb.lib.message.operations.Operation;
38 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
39 import org.opendaylight.ovsdb.lib.message.operations.UpdateOperation;
40 import org.opendaylight.ovsdb.lib.notation.Condition;
41 import org.opendaylight.ovsdb.lib.notation.Function;
42 import org.opendaylight.ovsdb.lib.notation.Mutation;
43 import org.opendaylight.ovsdb.lib.notation.Mutator;
44 import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
45 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
46 import org.opendaylight.ovsdb.lib.notation.UUID;
47 import org.opendaylight.ovsdb.lib.table.Bridge;
48 import org.opendaylight.ovsdb.lib.table.Capability;
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.internal.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 bridgeConnectorIdentifier 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 String 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(connection);
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.info("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 Map<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             Map<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         // TODO Auto-generated method stub
894         return null;
895     }
896
897     private StatusWithUuid insertBridgeRow(Node node, String open_VSwitch_uuid, Bridge bridgeRow) {
898
899         String insertErrorMsg = "bridge";
900         String rowName=bridgeRow.getName();
901
902         try{
903             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
904
905             if (ovsTable == null) {
906                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
907             }
908
909             String newBridge = "new_bridge";
910
911             Operation addSwitchRequest = null;
912
913             String ovsTableUUID = open_VSwitch_uuid;
914             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
915             UUID bridgeUuid = new UUID(newBridge);
916             Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuid);
917             List<Mutation> mutations = new ArrayList<Mutation>();
918             mutations.add(bm);
919
920             UUID uuid = new UUID(ovsTableUUID);
921             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
922             List<Condition> where = new ArrayList<Condition>();
923             where.add(condition);
924             addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
925
926             InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
927
928             TransactBuilder transaction = new TransactBuilder();
929             transaction.addOperations(new ArrayList<Operation>(
930                                       Arrays.asList(addSwitchRequest,
931                                                     addBridgeRequest)));
932
933             int bridgeInsertIndex = transaction.getRequests().indexOf(addBridgeRequest);
934
935             return _insertTableRow(node,transaction,bridgeInsertIndex,insertErrorMsg,rowName);
936
937         } catch(Exception e){
938             logger.error("Error in insertBridgeRow(): ",e);
939         }
940         return new StatusWithUuid(StatusCode.INTERNALERROR);
941     }
942
943
944     private StatusWithUuid insertPortRow(Node node, String bridge_uuid, Port portRow) {
945
946         String insertErrorMsg = "port";
947         String rowName=portRow.getName();
948
949         try{
950             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
951             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
952                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
953             }
954             String newPort = "new_port";
955             UUID portUUID = new UUID(newPort);
956             Mutation bm = new Mutation("ports", Mutator.INSERT, portUUID);
957             List<Mutation> mutations = new ArrayList<Mutation>();
958             mutations.add(bm);
959
960             UUID uuid = new UUID(bridge_uuid);
961             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
962             List<Condition> where = new ArrayList<Condition>();
963             where.add(condition);
964             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
965
966             // Default OVS schema is to have 1 or more interface part of Bridge. Hence it is mandatory to
967             // Insert an Interface in a Port add case
968
969             String newInterface = "new_interface";
970             Interface interfaceRow = new Interface();
971             interfaceRow.setName(portRow.getName());
972             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),
973                     newInterface, interfaceRow);
974
975             OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
976             UUID interfaceid = new UUID(newInterface);
977             interfaces.add(interfaceid);
978             portRow.setInterfaces(interfaces);
979
980             InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
981
982             TransactBuilder transaction = new TransactBuilder();
983             transaction.addOperations(new ArrayList<Operation>
984             (Arrays.asList(addBrMutRequest, addPortRequest, addIntfRequest)));
985             int portInsertIndex = transaction.getRequests().indexOf(addPortRequest);
986
987             return _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
988
989             } catch (Exception e) {
990             logger.error("Error in insertPortRow(): ",e);
991         }
992         return new StatusWithUuid(StatusCode.INTERNALERROR);
993     }
994
995     private StatusWithUuid insertInterfaceRow(Node node, String port_uuid, Interface interfaceRow) {
996
997         String insertErrorMsg = "interface";
998         String rowName=interfaceRow.getName();
999
1000         try{
1001
1002             // Interface table must have entry in Port table, checking port table for port
1003             Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1004             if (portTable == null ||  portTable.get(port_uuid) == null) {
1005                 return new StatusWithUuid(StatusCode.NOTFOUND, "Port with UUID "+port_uuid+" Not found");
1006             }
1007             // MUTATOR, need to insert the interface UUID to LIST of interfaces in PORT TABLE for port_uuid
1008             String newInterface = "new_interface";
1009             UUID interfaceUUID = new UUID(newInterface);
1010             Mutation portTableMutation = new Mutation("interfaces", Mutator.INSERT, interfaceUUID); // field name to append is "interfaces"
1011             List<Mutation> mutations = new ArrayList<Mutation>();
1012             mutations.add(portTableMutation);
1013
1014             // Create the Operation which will be used in Transact to perform the PORT TABLE mutation
1015             UUID uuid = new UUID(port_uuid);
1016             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1017             List<Condition> where = new ArrayList<Condition>();
1018             where.add(condition);
1019             Operation addPortMutationRequest = new MutateOperation(Port.NAME.getName(), where, mutations);
1020
1021             // Create the interface row request
1022             InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(),newInterface, interfaceRow);
1023
1024             // Transaction to insert/modify tables - validate using "sudo ovsdb-client dump" on host running OVSDB process
1025             TransactBuilder transaction = new TransactBuilder();
1026             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addIntfRequest,addPortMutationRequest)));
1027
1028             // Check the results. Iterates over the results of the Array of transaction Operations, and reports STATUS
1029             int interfaceInsertIndex = transaction.getRequests().indexOf(addIntfRequest);
1030
1031             return _insertTableRow(node,transaction,interfaceInsertIndex,insertErrorMsg,rowName);
1032
1033         } catch (Exception e) {
1034             logger.error("Error in insertInterfaceRow(): ",e);
1035         }
1036         return new StatusWithUuid(StatusCode.INTERNALERROR);
1037     }
1038
1039     private StatusWithUuid insertOpen_vSwitchRow(Node node, Open_vSwitch row) {
1040         return new StatusWithUuid(StatusCode.NOTIMPLEMENTED, "Insert operation for this Table is not implemented yet.");
1041     }
1042
1043     private StatusWithUuid insertControllerRow(Node node, String bridge_uuid, Controller row) {
1044
1045         String insertErrorMsg = "controller";
1046         String rowName=row.getTableName().toString();
1047
1048         try{
1049
1050             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1051             if (brTable == null ||  brTable.get(bridge_uuid) == null) {
1052                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+bridge_uuid+" Not found");
1053             }
1054
1055             Map<String, Table<?>> controllerCache = inventoryServiceInternal.getTableCache(node, Controller.NAME.getName());
1056
1057             String uuid_name = "new_controller";
1058             boolean controllerExists = false;
1059             if (controllerCache != null) {
1060                 for (String uuid : controllerCache.keySet()) {
1061                     Controller controller = (Controller)controllerCache.get(uuid);
1062                     if (controller.getTarget().equals(row.getTarget())) {
1063                         uuid_name = uuid;
1064                         controllerExists = true;
1065                         break;
1066                     }
1067                 }
1068             }
1069
1070             UUID controllerUUID = new UUID(uuid_name);
1071             Mutation bm = new Mutation("controller", Mutator.INSERT, controllerUUID);
1072             List<Mutation> mutations = new ArrayList<Mutation>();
1073             mutations.add(bm);
1074
1075             UUID uuid = new UUID(bridge_uuid);
1076             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1077             List<Condition> where = new ArrayList<Condition>();
1078             where.add(condition);
1079             Operation addBrMutRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1080             InsertOperation addControllerRequest = null;
1081
1082             TransactBuilder transaction = new TransactBuilder();
1083             transaction.addOperation(addBrMutRequest);
1084             int portInsertIndex = -1;
1085             if (!controllerExists) {
1086                 addControllerRequest = new InsertOperation(Controller.NAME.getName(), uuid_name, row);
1087                 transaction.addOperation(addControllerRequest);
1088                 portInsertIndex = transaction.getRequests().indexOf(addControllerRequest);
1089             }
1090
1091             StatusWithUuid status = _insertTableRow(node,transaction,portInsertIndex,insertErrorMsg,rowName);
1092             if (status.isSuccess() && controllerExists) {
1093                 // We won't get the uuid from the transact, so we set it here
1094                 status = new StatusWithUuid(status.getCode(), controllerUUID);
1095             }
1096             return status;
1097
1098         } catch (Exception e) {
1099             logger.error("Error in insertControllerRow(): ",e);
1100         }
1101         return new StatusWithUuid(StatusCode.INTERNALERROR);
1102     }
1103
1104     private StatusWithUuid insertSSLRow(Node node, String parent_uuid, SSL row) {
1105         String insertErrorMsg = "SSL";
1106         String rowName=row.NAME.getName();
1107
1108         try{
1109             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
1110
1111             if (ovsTable == null) {
1112                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
1113             }
1114
1115             String newSSL = "new_SSL";
1116
1117             Operation addOpen_vSwitchRequest = null;
1118
1119             String ovsTableUUID = parent_uuid;
1120             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
1121             UUID sslUuid = new UUID(newSSL);
1122             Mutation sslMutation = new Mutation("ssl", Mutator.INSERT, sslUuid);
1123             List<Mutation> mutations = new ArrayList<Mutation>();
1124             mutations.add(sslMutation);
1125
1126             UUID uuid = new UUID(ovsTableUUID);
1127             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1128             List<Condition> where = new ArrayList<Condition>();
1129             where.add(condition);
1130             addOpen_vSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
1131
1132             InsertOperation addSSLRequest = new InsertOperation(SSL.NAME.getName(), newSSL, row);
1133
1134             TransactBuilder transaction = new TransactBuilder();
1135             transaction.addOperations(new ArrayList<Operation>(
1136                                       Arrays.asList(addSSLRequest,
1137                                                     addOpen_vSwitchRequest)));
1138
1139             int sslInsertIndex = transaction.getRequests().indexOf(addSSLRequest);
1140
1141             return _insertTableRow(node,transaction,sslInsertIndex,insertErrorMsg,rowName);
1142
1143         } catch(Exception e){
1144             logger.error("Error in insertSSLRow(): ",e);
1145         }
1146         return new StatusWithUuid(StatusCode.INTERNALERROR);
1147     }
1148
1149     private StatusWithUuid insertSflowRow(Node node, String parent_uuid, SFlow row) {
1150
1151         String insertErrorMsg = "sFlow";
1152         String rowName=row.NAME.getName();
1153
1154         try{
1155             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1156             if (brTable == null ||  brTable.get(parent_uuid) == null) {
1157                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
1158             }
1159
1160             if (parent_uuid == null) {
1161                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
1162             }
1163
1164             UUID uuid = new UUID(parent_uuid);
1165
1166             String newSflow = "new_sflow";
1167
1168             Operation addBridgeRequest = null;
1169
1170             UUID sflowUuid = new UUID(newSflow);
1171             Mutation sflowMutation = new Mutation("sflow", Mutator.INSERT, sflowUuid);
1172             List<Mutation> mutations = new ArrayList<Mutation>();
1173             mutations.add(sflowMutation);
1174
1175             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1176             List<Condition> where = new ArrayList<Condition>();
1177             where.add(condition);
1178             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1179
1180             InsertOperation addSflowRequest = new InsertOperation(SFlow.NAME.getName(), newSflow, row);
1181
1182             TransactBuilder transaction = new TransactBuilder();
1183             transaction.addOperations(new ArrayList<Operation>(
1184                                       Arrays.asList(addSflowRequest,
1185                                                     addBridgeRequest)));
1186
1187             int sflowInsertIndex = transaction.getRequests().indexOf(addSflowRequest);
1188
1189
1190             return _insertTableRow(node,transaction,sflowInsertIndex,insertErrorMsg,rowName);
1191
1192         } catch (Exception e) {
1193             logger.error("Error in insertInterfaceRow(): ",e);
1194         }
1195         return new StatusWithUuid(StatusCode.INTERNALERROR);
1196     }
1197
1198     private StatusWithUuid insertQueueRow(Node node, String parent_uuid, Queue row) {
1199         String insertErrorMsg = "Queue";
1200         String rowName=row.NAME.getName();
1201
1202         try{
1203             Map<String, Table<?>> qosTable = inventoryServiceInternal.getTableCache(node, Qos.NAME.getName());
1204             if (qosTable == null ||  qosTable.get(parent_uuid) == null) {
1205                 return new StatusWithUuid(StatusCode.NOTFOUND, "QoS with UUID "+parent_uuid+" Not found");
1206             }
1207
1208             if (parent_uuid == null) {
1209                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent QoS UUID.");
1210             }
1211
1212             // NOTE: Queue Table is "isroot" meaning it can have a hanging reference. This is different from
1213             // standing insertRow due to the parent column type being a map, where one of the items may not be known
1214             // at time of insert. Therefore this is a simple insert, rather than mutate/insert.
1215             String newQueue = "new_queue";
1216             InsertOperation addQueueRequest = new InsertOperation(Queue.NAME.getName(), newQueue, row);
1217
1218             TransactBuilder transaction = new TransactBuilder();
1219             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQueueRequest)));
1220
1221             int queueInsertIndex = transaction.getRequests().indexOf(addQueueRequest);
1222
1223             return _insertTableRow(node,transaction,queueInsertIndex,insertErrorMsg,rowName);
1224
1225         } catch (Exception e) {
1226             logger.error("Error in insertQueueRow(): ",e);
1227         }
1228         return new StatusWithUuid(StatusCode.INTERNALERROR);    }
1229
1230     private StatusWithUuid insertQosRow(Node node, String parent_uuid, Qos row) {
1231         String insertErrorMsg = "Qos";
1232         String rowName=row.NAME.getName();
1233
1234         try{
1235
1236             String newQos = "new_qos";
1237
1238             // QoS Table "isroot" meaning it can have hanging references. If parent_uuid is not supplied in API call this becomes a simple
1239             // insert operation, rather than the typical mutate/insert parent/child insert.
1240             if (parent_uuid != null) {
1241                 // Port (parent) table check for UUID existance.
1242                 Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1243                 if (portTable == null ||  portTable.get(parent_uuid) == null) {
1244                     return new StatusWithUuid(StatusCode.NOTFOUND, "Port with UUID "+parent_uuid+" Not found");
1245                 }
1246
1247                 UUID qosUuid = new UUID(newQos);
1248                 Mutation qosMutation = new Mutation("qos", Mutator.INSERT, qosUuid);
1249                 List<Mutation> mutations = new ArrayList<Mutation>();
1250                 mutations.add(qosMutation);
1251
1252                 Operation addPortRequest = null;
1253                 UUID uuid = new UUID(parent_uuid);
1254                 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1255                 List<Condition> where = new ArrayList<Condition>();
1256                 where.add(condition);
1257                 addPortRequest = new MutateOperation(Port.NAME.getName(), where, mutations);
1258
1259                 InsertOperation addQosRequest = new InsertOperation(Qos.NAME.getName(), newQos, row);
1260
1261                 TransactBuilder transaction = new TransactBuilder();
1262                 transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQosRequest,addPortRequest)));
1263
1264                 int qosInsertIndex = transaction.getRequests().indexOf(addQosRequest);
1265
1266                 return _insertTableRow(node,transaction,qosInsertIndex,insertErrorMsg,rowName);
1267
1268             } else {
1269                 InsertOperation addQosRequest = new InsertOperation(Qos.NAME.getName(), newQos, row);
1270
1271                 TransactBuilder transaction = new TransactBuilder();
1272                 transaction.addOperations(new ArrayList<Operation>(Arrays.asList(addQosRequest)));
1273
1274                 int qosInsertIndex = transaction.getRequests().indexOf(addQosRequest);
1275
1276                 return _insertTableRow(node,transaction,qosInsertIndex,insertErrorMsg,rowName);
1277             }
1278
1279         } catch (Exception e) {
1280             logger.error("Error in insertQosRow(): ",e);
1281         }
1282         return new StatusWithUuid(StatusCode.INTERNALERROR);
1283     }
1284
1285
1286     private StatusWithUuid insertNetFlowRow(Node node, String parent_uuid, NetFlow row) {
1287         String insertErrorMsg = "netFlow";
1288         String rowName=row.NAME.getName();
1289
1290         try{
1291             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1292             if (brTable == null ||  brTable.get(parent_uuid) == null) {
1293                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
1294             }
1295
1296             if (parent_uuid == null) {
1297                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
1298             }
1299
1300             UUID uuid = new UUID(parent_uuid);
1301             String newNetflow = "new_netflow";
1302
1303             Operation addBridgeRequest = null;
1304
1305             UUID netFlowUuid = new UUID(newNetflow);
1306             Mutation netFlowMutation = new Mutation("netflow", Mutator.INSERT, netFlowUuid);
1307             List<Mutation> mutations = new ArrayList<Mutation>();
1308             mutations.add(netFlowMutation);
1309
1310             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1311             List<Condition> where = new ArrayList<Condition>();
1312             where.add(condition);
1313             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1314
1315             InsertOperation addNetflowRequest = new InsertOperation(NetFlow.NAME.getName(), newNetflow, row);
1316
1317             TransactBuilder transaction = new TransactBuilder();
1318             transaction.addOperations(new ArrayList<Operation>(
1319                                       Arrays.asList(addNetflowRequest,
1320                                                     addBridgeRequest)));
1321
1322             int netflowInsertIndex = transaction.getRequests().indexOf(addNetflowRequest);
1323
1324
1325             return _insertTableRow(node,transaction,netflowInsertIndex,insertErrorMsg,rowName);
1326
1327         } catch (Exception e) {
1328             logger.error("Error in insertNetFlowRow(): ",e);
1329         }
1330         return new StatusWithUuid(StatusCode.INTERNALERROR);
1331     }
1332
1333     private StatusWithUuid insertMirrorRow(Node node, String parent_uuid, Mirror row) {
1334         String insertErrorMsg = "mirror";
1335         String rowName=row.NAME.getName();
1336
1337         try{
1338             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
1339             if (brTable == null ||  brTable.get(parent_uuid) == null) {
1340                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
1341             }
1342
1343             if (parent_uuid == null) {
1344                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
1345             }
1346
1347             UUID uuid = new UUID(parent_uuid);
1348             String newMirror = "new_mirror";
1349
1350             Operation addBridgeRequest = null;
1351
1352             UUID mirrorUuid = new UUID(newMirror);
1353             Mutation mirrorMutation = new Mutation("mirrors", Mutator.INSERT, mirrorUuid);
1354             List<Mutation> mutations = new ArrayList<Mutation>();
1355             mutations.add(mirrorMutation);
1356
1357             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1358             List<Condition> where = new ArrayList<Condition>();
1359             where.add(condition);
1360             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
1361
1362             InsertOperation addMirrorRequest = new InsertOperation(Mirror.NAME.getName(), newMirror, row);
1363
1364             TransactBuilder transaction = new TransactBuilder();
1365             transaction.addOperations(new ArrayList<Operation>(
1366                                       Arrays.asList(addBridgeRequest, addMirrorRequest)));
1367
1368             int mirrorInsertIndex = transaction.getRequests().indexOf(addMirrorRequest);
1369
1370             return _insertTableRow(node,transaction,mirrorInsertIndex,insertErrorMsg,rowName);
1371
1372             } catch (Exception e) {
1373             logger.error("Error in insertMirrorRow(): ",e);
1374         }
1375         return new StatusWithUuid(StatusCode.INTERNALERROR);
1376     }
1377
1378     private StatusWithUuid insertManagerRow(Node node, String parent_uuid, Manager row) {
1379         String insertErrorMsg = "manager";
1380         String rowName=row.NAME.getName();
1381
1382         try{
1383             Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
1384
1385             if (ovsTable == null) {
1386                 return new StatusWithUuid(StatusCode.NOTFOUND, "There are no Open_vSwitch instance in the Open_vSwitch table");
1387             }
1388
1389             String newManager = "new_manager";
1390
1391             Operation addSwitchRequest = null;
1392
1393             String ovsTableUUID = parent_uuid;
1394             if (ovsTableUUID == null) ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
1395             UUID managerUuid = new UUID(newManager);
1396             Mutation managerMutation = new Mutation("manager_options", Mutator.INSERT, managerUuid);
1397             List<Mutation> mutations = new ArrayList<Mutation>();
1398             mutations.add(managerMutation);
1399
1400             UUID uuid = new UUID(ovsTableUUID);
1401             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
1402             List<Condition> where = new ArrayList<Condition>();
1403             where.add(condition);
1404             addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
1405
1406             InsertOperation addManagerRequest = new InsertOperation(Manager.NAME.getName(), newManager, row);
1407
1408             TransactBuilder transaction = new TransactBuilder();
1409             transaction.addOperations(new ArrayList<Operation>(
1410                                       Arrays.asList(addSwitchRequest,
1411                                                     addManagerRequest)));
1412
1413             int managerInsertIndex = transaction.getRequests().indexOf(addManagerRequest);
1414
1415             return _insertTableRow(node,transaction,managerInsertIndex,insertErrorMsg,rowName);
1416
1417         } catch(Exception e){
1418             logger.error("Error in insertManagerRow(): ",e);
1419         }
1420         return new StatusWithUuid(StatusCode.INTERNALERROR);
1421     }
1422
1423     private StatusWithUuid _insertTableRow(Node node, TransactBuilder transaction, Integer insertIndex, String insertErrorMsg,String rowName){
1424
1425         try{
1426             //Check for connection before calling RPC to perform transaction
1427             if (connectionService == null) {
1428                 logger.error("Couldn't refer to the ConnectionService");
1429                 return new StatusWithUuid(StatusCode.NOSERVICE);
1430             }
1431
1432             Connection connection = this.getConnection(node);
1433             if (connection == null) {
1434                 return new StatusWithUuid(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1435             }
1436
1437             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1438             List<OperationResult> tr = transResponse.get();
1439             List<Operation> requests = transaction.getRequests();
1440             StatusWithUuid status = new StatusWithUuid(StatusCode.SUCCESS);
1441             for (int i = 0; i < tr.size() ; i++) {
1442                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1443                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1444                     OperationResult result = tr.get(i);
1445                     status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1446                 }
1447             }
1448
1449             if (tr.size() > requests.size()) {
1450                 OperationResult result = tr.get(tr.size()-1);
1451                 logger.error("Error creating {} : {}\n Error : {}\n Details : {}",     insertErrorMsg,
1452                                                                                        rowName,
1453                                                                                        result.getError(),
1454                                                                                        result.getDetails());
1455                 status = new StatusWithUuid(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1456             }
1457             if (status.isSuccess()) {
1458                 if (insertIndex >= 0 && insertIndex < tr.size() && tr.get(insertIndex) != null) {
1459                     UUID uuid = tr.get(insertIndex).getUuid();
1460                     status = new StatusWithUuid(StatusCode.SUCCESS, uuid);
1461                 } else {
1462                     // We can't get the uuid from the transact as the insertIndex is invalid or -1
1463                     // return null uuid.
1464                     status = new StatusWithUuid(StatusCode.SUCCESS, (UUID) null);
1465                 }
1466             }
1467             return status;
1468         } catch(Exception e){
1469             logger.error("Error in _insertTableRow(): ",e);
1470         }
1471         return new StatusWithUuid(StatusCode.INTERNALERROR);
1472     }
1473
1474
1475     private Status deleteBridgeRow(Node node, String uuid) {
1476         // Set up variables for generic _deleteTableRow()
1477         String parentTableName=Open_vSwitch.NAME.getName();
1478         String childTableName=Bridge.NAME.getName();
1479         String parentColumn = "bridges";
1480
1481         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1482     }
1483
1484     private Status deletePortRow(Node node, String uuid) {
1485         // Set up variables for generic _deleteTableRow()
1486         String parentTableName=Bridge.NAME.getName();
1487         String childTableName=Port.NAME.getName();
1488         String parentColumn = "ports";
1489
1490         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1491     }
1492
1493     private Status deleteInterfaceRow(Node node, String uuid) {
1494         // Since Port<-Interface tables have a 1:n relationship, need to test if this is the last interface
1495         // assigned to a port before attempting delete.
1496         Map<String, Table<?>> portTable = inventoryServiceInternal.getTableCache(node, Port.NAME.getName());
1497         Map<String, Table<?>> interfaceTable = inventoryServiceInternal.getTableCache(node, Interface.NAME.getName());
1498         // Check that the UUID exists
1499         if (portTable == null || interfaceTable == null || uuid == null || interfaceTable.get(uuid) == null) {
1500             return new Status(StatusCode.NOTFOUND, "");
1501         }
1502
1503         // Since the above past, it's safe to use the generic _deleteTableRow method
1504         // Set up variables for generic _deleteTableRow()
1505         String parentTableName=Port.NAME.getName();
1506         String childTableName=Interface.NAME.getName();
1507         String parentColumn = "interfaces";
1508
1509         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1510     }
1511
1512     private Status deleteControllerRow(Node node, String uuid) {
1513         // Set up variables for generic _deleteTableRow()
1514         String parentTableName=Bridge.NAME.getName();
1515         String childTableName=Controller.NAME.getName();
1516         String parentColumn = "controller";
1517
1518         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1519     }
1520
1521     private Status deleteOpen_vSwitchRow(Node node, String uuid) {
1522         return new Status(StatusCode.NOTIMPLEMENTED, "delete operation for this Table is not implemented yet.");
1523     }
1524
1525     private Status deleteSSLRow(Node node, String uuid) {
1526         // Set up variables for generic _deleteTableRow()
1527         String parentTableName=Open_vSwitch.NAME.getName();
1528         String childTableName=SSL.NAME.getName();
1529         String parentColumn = "ssl";
1530
1531         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1532     }
1533
1534     private Status deleteSflowRow(Node node, String uuid) {
1535         // Set up variables for generic _deleteTableRow()
1536         String parentTableName=Bridge.NAME.getName();
1537         String childTableName=SFlow.NAME.getName();
1538         String parentColumn = "sflow";
1539
1540         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1541     }
1542
1543     private Status deleteQueueRow(Node node, String uuid) {
1544         // Set up variables for _deleteRootTableRow()
1545         // This doesn't do a mutate on parent, but simply deletes row
1546         String childTableName=Queue.NAME.getName();
1547
1548         return _deleteRootTableRow(node,uuid,childTableName);
1549     }
1550
1551     private Status deleteQosRow(Node node, String uuid) {
1552         // Set up variables for generic _deleteTableRow()
1553         String parentTableName=Port.NAME.getName();
1554         String childTableName=Qos.NAME.getName();
1555         String parentColumn = "qos";
1556
1557         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1558     }
1559
1560     private Status deleteNetFlowRow(Node node, String uuid) {
1561         // Set up variables for generic _deleteTableRow()
1562         String parentTableName=Bridge.NAME.getName();
1563         String childTableName=NetFlow.NAME.getName();
1564         String parentColumn = "netflow";
1565
1566         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1567     }
1568
1569     private Status deleteMirrorRow(Node node, String uuid) {
1570         // Set up variables for generic _deleteTableRow()
1571         String parentTableName=Bridge.NAME.getName();
1572         String childTableName=Mirror.NAME.getName();
1573         String parentColumn = "mirrors";
1574         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1575     }
1576
1577     private Status deleteManagerRow(Node node, String uuid) {
1578         // Set up variables for generic _deleteTableRow()
1579         String parentTableName=Open_vSwitch.NAME.getName();
1580         String childTableName=Manager.NAME.getName();
1581         String parentColumn = "manager_options";
1582
1583         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
1584     }
1585
1586     private Status _deleteTableRow(Node node,String uuid,String parentTableName, String childTableName, String parentColumn) {
1587         try {
1588             // Check there is a connectionService
1589             if (connectionService == null) {
1590                 logger.error("Couldn't refer to the ConnectionService");
1591                 return new Status(StatusCode.NOSERVICE);
1592             }
1593
1594             // Establish the connection
1595             Connection connection = this.getConnection(node);
1596             if (connection == null) {
1597                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1598             }
1599
1600             // Remove from Parent and Child
1601             Map<String, Table<?>> parentTable = inventoryServiceInternal.getTableCache(node, parentTableName);
1602             Map<String, Table<?>> childTable = inventoryServiceInternal.getTableCache(node, childTableName);
1603
1604             // Check that the UUID exists
1605             if (parentTable == null || childTable == null || uuid == null || childTable.get(uuid) == null) {
1606                 return new Status(StatusCode.NOTFOUND, "");
1607             }
1608
1609             // Initialise the actual request var
1610             Operation delRequest = null;
1611
1612             // Prepare the mutator to remove the child UUID from the parentColumn list in the parent TABLE
1613             UUID rowUuid = new UUID(uuid);
1614             Mutation mutator = new Mutation(parentColumn, Mutator.DELETE, rowUuid);
1615             List<Mutation> mutations = new ArrayList<Mutation>();
1616             mutations.add(mutator);
1617
1618             Status status = new Status(StatusCode.SUCCESS);
1619
1620             // INCLUDES condition ensures that it captures all rows in the parent table (ie duplicates) that have the child UUID
1621             Condition condition = new Condition(parentColumn, Function.INCLUDES, rowUuid);
1622             List<Condition> where = new ArrayList<Condition>();
1623             where.add(condition);
1624             delRequest = new MutateOperation(parentTableName, where, mutations);
1625
1626             TransactBuilder transaction = new TransactBuilder();
1627             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delRequest)));
1628
1629             // This executes the transaction.
1630             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1631
1632             // Pull the responses
1633             List<OperationResult> tr = transResponse.get();
1634             List<Operation> requests = transaction.getRequests();
1635
1636             for (int i = 0; i < tr.size(); i++) {
1637                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1638                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1639                     OperationResult result = tr.get(i);
1640                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1641                 }
1642             }
1643
1644             if (tr.size() > requests.size()) {
1645                 OperationResult result = tr.get(tr.size() - 1);
1646                 logger.error("Error deleting: {}\n Error : {}\n Details : {}",
1647                         uuid, result.getError(), result.getDetails());
1648                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1649             }
1650             return status;
1651         } catch (Exception e) {
1652             logger.error("Error in _deleteTableRow",e);
1653         }
1654         return new Status(StatusCode.INTERNALERROR);
1655     }
1656
1657     private Status _deleteRootTableRow(Node node,String uuid,String TableName) {
1658         try {
1659             // Check there is a connectionService
1660             if (connectionService == null) {
1661                 logger.error("Couldn't refer to the ConnectionService");
1662                 return new Status(StatusCode.NOSERVICE);
1663             }
1664
1665             // Establish the connection
1666             Connection connection = this.getConnection(node);
1667             if (connection == null) {
1668                 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
1669             }
1670
1671             Map<String, Table<?>> table = inventoryServiceInternal.getTableCache(node, TableName);
1672
1673             // Check that the UUID exists
1674             if (table == null || table.get(uuid) == null) {
1675                 return new Status(StatusCode.NOTFOUND, "");
1676             }
1677
1678             // Initialise the actual request var
1679             Operation delRequest = null;
1680
1681             UUID rowUuid = new UUID(uuid);
1682
1683             Status status = new Status(StatusCode.SUCCESS);
1684
1685             Condition condition = new Condition("_uuid", Function.EQUALS, rowUuid);
1686             List<Condition> where = new ArrayList<Condition>();
1687             where.add(condition);
1688             delRequest = new DeleteOperation(TableName, where);
1689
1690             TransactBuilder transaction = new TransactBuilder();
1691             transaction.addOperations(new ArrayList<Operation>(Arrays.asList(delRequest)));
1692
1693             // This executes the transaction.
1694             ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
1695
1696             // Pull the responses
1697             List<OperationResult> tr = transResponse.get();
1698             List<Operation> requests = transaction.getRequests();
1699
1700             for (int i = 0; i < tr.size(); i++) {
1701                 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
1702                 if (tr.get(i) != null && tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
1703                     OperationResult result = tr.get(i);
1704                     status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1705                 }
1706             }
1707
1708             if (tr.size() > requests.size()) {
1709                 OperationResult result = tr.get(tr.size() - 1);
1710                 logger.error("Error deleting: {}\n Error : {}\n Details : {}",
1711                         uuid, result.getError(), result.getDetails());
1712                 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
1713             }
1714             return status;
1715         } catch (Exception e) {
1716             logger.error("Error in _deleteRootTableRow",e);
1717         }
1718         return new Status(StatusCode.INTERNALERROR);
1719     }
1720
1721     public void _ovsconnect (CommandInterpreter ci) {
1722         String bridgeName = ci.nextArgument();
1723         if (bridgeName == null) {
1724             ci.println("Please enter Bridge Name");
1725             return;
1726         }
1727
1728         String ovsdbserver = ci.nextArgument();
1729         if (ovsdbserver == null) {
1730             ci.println("Please enter valid IP-Address");
1731             return;
1732         }
1733         try {
1734             InetAddress.getByName(ovsdbserver);
1735         }  catch (UnknownHostException e) {
1736             logger.error("Unable to resolve " + ovsdbserver, e);
1737             ci.println("Please enter valid IP-Address");
1738             return;
1739         }
1740         String port = ci.nextArgument();
1741         if (port == null) {
1742             port = "6634";
1743         }
1744
1745         ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
1746         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
1747         params.put(ConnectionConstants.ADDRESS, ovsdbserver);
1748         params.put(ConnectionConstants.PORT, port);
1749         Node node = connectionService.connect(bridgeName, params);
1750         if (node != null) ci.println("Node Name: "+node.toString());
1751         else ci.println("Could not connect to Node");
1752     }
1753
1754     public void _addBridge (CommandInterpreter ci) {
1755         String nodeName = ci.nextArgument();
1756         if (nodeName == null) {
1757             ci.println("Please enter Node Name");
1758             return;
1759         }
1760         String bridgeName = ci.nextArgument();
1761         if (bridgeName == null) {
1762             ci.println("Please enter Bridge Name");
1763             return;
1764         }
1765         Status status;
1766
1767         Node node = Node.fromString(nodeName);
1768         if (node == null) {
1769             ci.println("Invalid Node");
1770             return;
1771         }
1772         status = this.createBridgeDomain(node, bridgeName, null);
1773         ci.println("Bridge creation status : "+status.toString());
1774     }
1775
1776     public void _getBridgeDomains (CommandInterpreter ci) {
1777         String nodeName = ci.nextArgument();
1778         if (nodeName == null) {
1779             ci.println("Please enter Node Name");
1780             return;
1781         }
1782
1783         List<String> brlist = new ArrayList<String>();
1784         Node node = Node.fromString(nodeName);
1785         brlist = this.getBridgeDomains(node);
1786         if (node == null) {
1787             ci.println("Invalid Node");
1788             return;
1789         }
1790         ci.println("Existing Bridges: "+brlist.toString());
1791     }
1792
1793     public void _deleteBridgeDomain (CommandInterpreter ci) {
1794         String nodeName = ci.nextArgument();
1795         if (nodeName == null) {
1796             ci.println("Please enter Node Name");
1797             return;
1798         }
1799         String bridgeName = ci.nextArgument();
1800         if (bridgeName == null) {
1801             ci.println("Please enter Bridge Name");
1802             return;
1803         }
1804         Status status;
1805         Node node = Node.fromString(nodeName);
1806         if (node == null) {
1807             ci.println("Invalid Node");
1808             return;
1809         }
1810         status = this.deleteBridgeDomain(node, bridgeName);
1811         ci.println("Bridge deletion status : "+status.toString());
1812     }
1813
1814     public void _addPort (CommandInterpreter ci) {
1815         String nodeName = ci.nextArgument();
1816         if (nodeName == null) {
1817             ci.println("Please enter Node Name");
1818             return;
1819         }
1820
1821         String bridgeName = ci.nextArgument();
1822         if (bridgeName == null) {
1823             ci.println("Please enter Bridge Name");
1824             return;
1825         }
1826
1827         String portName = ci.nextArgument();
1828         if (portName == null) {
1829             ci.println("Please enter Port Name");
1830             return;
1831         }
1832
1833         String type = ci.nextArgument();
1834
1835         Map<String, String> configs = new HashMap<String, String>();
1836         while(true) {
1837             String configKey = ci.nextArgument();
1838             if (configKey == null) break;
1839             String configValue = ci.nextArgument();
1840             if (configValue == null) break;
1841             configs.put(configKey, configValue);
1842         }
1843
1844         Map<ConfigConstants, Object> customConfigs = null;
1845         if (type != null) {
1846             customConfigs = new HashMap<ConfigConstants, Object>();
1847             customConfigs.put(ConfigConstants.TYPE, type);
1848         }
1849
1850         if (configs.size() > 0) {
1851             if (customConfigs == null) customConfigs = new HashMap<ConfigConstants, Object>();
1852             customConfigs.put(ConfigConstants.CUSTOM, configs);
1853             ci.println(customConfigs.toString());
1854         }
1855         Status status;
1856         Node node = Node.fromString(nodeName);
1857         if (node == null) {
1858             ci.println("Invalid Node");
1859             return;
1860         }
1861         status = this.addPort(node, bridgeName, portName, customConfigs);
1862         ci.println("Port creation status : "+status.toString());
1863     }
1864
1865     public void _deletePort (CommandInterpreter ci) {
1866         String nodeName = ci.nextArgument();
1867         if (nodeName == null) {
1868             ci.println("Please enter Node Name");
1869             return;
1870         }
1871
1872         String bridgeName = ci.nextArgument();
1873         if (bridgeName == null) {
1874             ci.println("Please enter Bridge Name");
1875             return;
1876         }
1877
1878         String portName = ci.nextArgument();
1879         if (portName == null) {
1880             ci.println("Please enter Port Name");
1881             return;
1882         }
1883
1884         Status status;
1885         Node node = Node.fromString(nodeName);
1886         if (node == null) {
1887             ci.println("Invalid Node");
1888             return;
1889         }
1890         status = this.deletePort(node, bridgeName, portName);
1891         ci.println("Port deletion status : "+status.toString());
1892     }
1893
1894     public void _addPortVlan (CommandInterpreter ci) {
1895         String nodeName = ci.nextArgument();
1896         if (nodeName == null) {
1897             ci.println("Please enter Node Name");
1898             return;
1899         }
1900
1901         String bridgeName = ci.nextArgument();
1902         if (bridgeName == null) {
1903             ci.println("Please enter Bridge Name");
1904             return;
1905         }
1906
1907         String portName = ci.nextArgument();
1908         if (portName == null) {
1909             ci.println("Please enter Port Name");
1910             return;
1911         }
1912
1913         String vlan = ci.nextArgument();
1914         if (vlan == null) {
1915             ci.println("Please enter Valid Vlan");
1916             return;
1917         } else {
1918             try {
1919             Integer.parseInt(vlan);
1920             } catch (NumberFormatException e) {
1921                 ci.println("Please enter Valid Vlan");
1922                 return;
1923             }
1924         }
1925
1926         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1927         configs.put(ConfigConstants.TYPE, "VLAN");
1928         configs.put(ConfigConstants.VLAN, vlan);
1929
1930         Status status;
1931         Node node = Node.fromString(nodeName);
1932         if (node == null) {
1933             ci.println("Invalid Node");
1934             return;
1935         }
1936         status = this.addPort(node, bridgeName, portName, configs);
1937         ci.println("Port creation status : "+status.toString());
1938     }
1939
1940     public void _addTunnel (CommandInterpreter ci) {
1941         String nodeName = ci.nextArgument();
1942         if (nodeName == null) {
1943             ci.println("Please enter Node Name");
1944             return;
1945         }
1946
1947         String bridgeName = ci.nextArgument();
1948         if (bridgeName == null) {
1949             ci.println("Please enter Bridge Name");
1950             return;
1951         }
1952
1953         String portName = ci.nextArgument();
1954         if (portName == null) {
1955             ci.println("Please enter Port Name");
1956             return;
1957         }
1958
1959         String tunnelType = ci.nextArgument();
1960         if (tunnelType == null) {
1961             ci.println("Please enter Tunnel Type");
1962             return;
1963         }
1964
1965         String remoteIp = ci.nextArgument();
1966         if (remoteIp == null) {
1967             ci.println("Please enter valid Remote IP Address");
1968             return;
1969         }
1970
1971         try {
1972             InetAddress.getByName(remoteIp);
1973         }  catch (Exception e) {
1974             logger.error("Unable to resolve " + remoteIp, e);
1975             ci.println("Please enter valid Remote IP Address");
1976             return;
1977         }
1978
1979         Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
1980         configs.put(ConfigConstants.TYPE, "TUNNEL");
1981         configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
1982         configs.put(ConfigConstants.DEST_IP, remoteIp);
1983
1984         Status status;
1985         Node node = Node.fromString(nodeName);
1986         if (node == null) {
1987             ci.println("Invalid Node");
1988             return;
1989         }
1990         status = this.addPort(node, bridgeName, portName, configs);
1991         ci.println("Port creation status : "+status.toString());
1992     }
1993
1994     public void _printCache (CommandInterpreter ci) {
1995         String nodeName = ci.nextArgument();
1996         if (nodeName == null) {
1997             ci.println("Please enter Node Name");
1998             return;
1999         }
2000         Node node = Node.fromString(nodeName);
2001         if (node == null) {
2002             ci.println("Invalid Node");
2003             return;
2004         }
2005         inventoryServiceInternal.printCache(node);
2006     }
2007
2008     public void _forceConnect (CommandInterpreter ci) {
2009         String force = ci.nextArgument();
2010         if (force.equalsIgnoreCase("YES")) forceConnect = true;
2011         else if (force.equalsIgnoreCase("NO")) forceConnect = false;
2012         else ci.println("Please enter YES or NO.");
2013         ci.println("Current ForceConnect State : "+forceConnect);
2014         return;
2015     }
2016
2017     @Override
2018     public String getHelp() {
2019         StringBuffer help = new StringBuffer();
2020         help.append("---OVSDB CLI---\n");
2021         help.append("\t ovsconnect <ConnectionName> <ip-address>                        - Connect to OVSDB\n");
2022         help.append("\t addBridge <Node> <BridgeName>                                   - Add Bridge\n");
2023         help.append("\t getBridgeDomains <Node>                                         - Get Bridges\n");
2024         help.append("\t deleteBridgeDomain <Node> <BridgeName>                          - Delete a Bridge\n");
2025         help.append("\t addPort <Node> <BridgeName> <PortName> <type> <options pairs>   - Add Port\n");
2026         help.append("\t deletePort <Node> <BridgeName> <PortName>                       - Delete Port\n");
2027         help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan>               - Add Port, Vlan\n");
2028         help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip>      - Add Tunnel\n");
2029         help.append("\t printCache <Node>                                               - Prints Table Cache");
2030         return help.toString();
2031     }
2032 }
2033