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