2 * Copyright (C) 2013 Red Hat, Inc.
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
8 * Authors : Madhu Venugopal, Brent Salisbury, Keith Burns
10 package org.opendaylight.ovsdb.plugin.impl;
12 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
22 import java.util.concurrent.ConcurrentMap;
23 import java.util.concurrent.ExecutionException;
25 import org.eclipse.osgi.framework.console.CommandInterpreter;
26 import org.eclipse.osgi.framework.console.CommandProvider;
27 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
28 import org.opendaylight.controller.sal.connection.ConnectionConstants;
29 import org.opendaylight.controller.sal.core.Node;
30 import org.opendaylight.controller.sal.core.NodeConnector;
31 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
32 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
33 import org.opendaylight.controller.sal.utils.Status;
34 import org.opendaylight.controller.sal.utils.StatusCode;
35 import org.opendaylight.ovsdb.lib.OvsdbClient;
36 import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
37 import org.opendaylight.ovsdb.lib.notation.Column;
38 import org.opendaylight.ovsdb.lib.notation.Mutator;
39 import org.opendaylight.ovsdb.lib.notation.OvsdbSet;
40 import org.opendaylight.ovsdb.lib.notation.Row;
41 import org.opendaylight.ovsdb.lib.notation.UUID;
42 import org.opendaylight.ovsdb.lib.operations.Insert;
43 import org.opendaylight.ovsdb.lib.operations.Operation;
44 import org.opendaylight.ovsdb.lib.operations.OperationResult;
45 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
46 import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
47 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
48 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
49 import org.opendaylight.ovsdb.lib.schema.TableSchema;
50 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
51 import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
52 import org.opendaylight.ovsdb.plugin.api.Connection;
53 import org.opendaylight.ovsdb.plugin.api.OvsVswitchdSchemaConstants;
54 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
55 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
56 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
57 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
58 import org.opendaylight.ovsdb.plugin.error.OvsdbPluginException;
59 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
60 import org.opendaylight.ovsdb.schema.openvswitch.Controller;
61 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
62 import org.opendaylight.ovsdb.schema.openvswitch.Manager;
63 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
64 import org.opendaylight.ovsdb.schema.openvswitch.Port;
65 import org.osgi.framework.BundleContext;
66 import org.osgi.framework.FrameworkUtil;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 import com.google.common.collect.ImmutableSet;
71 import com.google.common.util.concurrent.ListenableFuture;
73 public class ConfigurationServiceImpl implements IPluginInBridgeDomainConfigService,
74 OvsdbConfigurationService,
78 private static final Logger logger = LoggerFactory
79 .getLogger(ConfigurationServiceImpl.class);
81 OvsdbConnectionService connectionService;
82 OvsdbInventoryService ovsdbInventoryService;
83 boolean forceConnect = false;
84 protected static final String OPENFLOW_10 = "1.0";
85 protected static final String OPENFLOW_13 = "1.3";
91 * Function called by the dependency manager when at least one dependency
92 * become unsatisfied or when the component is shutting down because for
93 * example bundle is being stopped.
100 * Function called by dependency manager after "init ()" is called and after
101 * the services provided by the class are registered in the service registry
105 registerWithOSGIConsole();
108 private void registerWithOSGIConsole() {
109 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
111 bundleContext.registerService(CommandProvider.class.getName(), this,
116 * Function called by the dependency manager before the services exported by
117 * the component are unregistered, this will be followed by a "destroy ()"
124 public void setConnectionServiceInternal(OvsdbConnectionService connectionService) {
125 this.connectionService = connectionService;
128 public void unsetConnectionServiceInternal(OvsdbConnectionService connectionService) {
129 if (this.connectionService == connectionService) {
130 this.connectionService = null;
134 public void setOvsdbInventoryService(OvsdbInventoryService ovsdbInventoryService) {
135 this.ovsdbInventoryService = ovsdbInventoryService;
138 public void unsetInventoryServiceInternal(OvsdbInventoryService ovsdbInventoryService) {
139 if (this.ovsdbInventoryService == ovsdbInventoryService) {
140 this.ovsdbInventoryService = null;
144 private IClusterGlobalServices clusterServices;
146 public void setClusterServices(IClusterGlobalServices i) {
147 this.clusterServices = i;
150 public void unsetClusterServices(IClusterGlobalServices i) {
151 if (this.clusterServices == i) {
152 this.clusterServices = null;
156 private Connection getConnection (Node node) {
157 Connection connection = connectionService.getConnection(node);
158 if (connection == null || !connection.getClient().isActive()) {
165 * There are a few Open_vSwitch schema specific special case handling to be done for
166 * the older API (such as by inserting a mandatory Interface row automatically upon inserting
169 private void handleSpecialInsertCase(OvsdbClient client, String databaseName,
170 String tableName, String uuid, Row<GenericTableSchema> row, TransactionBuilder transactionBuilder) {
171 Port port = client.getTypedRowWrapper(Port.class, null);
172 if (databaseName.equals(OvsVswitchdSchemaConstants.DATABASE_NAME) && tableName.equals(port.getSchema().getName())) {
173 port = client.getTypedRowWrapper(Port.class, row);
174 DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
175 TableSchema<GenericTableSchema> tableSchema = dbSchema.table(tableName, GenericTableSchema.class);
176 ColumnSchema<GenericTableSchema, Set<UUID>> columnSchema = tableSchema.multiValuedColumn("interfaces", UUID.class);
177 String namedUuid = "Special_"+tableName;
178 List<Operation> priorOperations = transactionBuilder.getOperations();
179 Insert portOperation = (Insert)priorOperations.get(0);
180 portOperation.value(columnSchema, new UUID(namedUuid));
182 Column<GenericTableSchema, ?> nameColumn = port.getNameColumn();
183 List<Column<GenericTableSchema, ?>> columns = new ArrayList<Column<GenericTableSchema, ?>>();
184 columns.add(nameColumn);
185 Row<GenericTableSchema> intfRow = new Row<GenericTableSchema>(tableSchema, columns);
186 this.processInsertTransaction(client, databaseName, "Interface", null, null, null, namedUuid, intfRow, transactionBuilder);
191 * A common Transaction that takes in old API style Parent_uuid and inserts a mutation on
192 * the parent table for the newly inserted Child.
193 * Due to some additional special case(s), the Transaction is further amended by handleSpecialInsertCase
195 private void processInsertTransaction(OvsdbClient client, String databaseName, String childTable,
196 String parentTable, String parentUuid, String parentColumn, String namedUuid,
197 Row<GenericTableSchema> row, TransactionBuilder transactionBuilder) {
198 DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
199 TableSchema<GenericTableSchema> childTableSchema = dbSchema.table(childTable, GenericTableSchema.class);
200 transactionBuilder.add(op.insert(childTableSchema, row)
203 if (parentColumn != null) {
204 TableSchema<GenericTableSchema> parentTableSchema = dbSchema.table(parentTable, GenericTableSchema.class);
205 ColumnSchema<GenericTableSchema, UUID> parentColumnSchema = parentTableSchema.column(parentColumn, UUID.class);
206 ColumnSchema<GenericTableSchema, UUID> _uuid = parentTableSchema.column("_uuid", UUID.class);
209 .add(op.mutate(parentTableSchema)
210 .addMutation(parentColumnSchema, Mutator.INSERT, new UUID(namedUuid))
211 .where(_uuid.opEqual(new UUID(parentUuid)))
215 * There are a few Open_vSwitch schema specific special case handling to be done for
216 * the older API (such as by inserting a mandatory Interface row automatically upon inserting
219 handleSpecialInsertCase(client, databaseName, childTable, namedUuid, row, transactionBuilder);
223 * TODO : Move all the Special Cases out of ConfigurationService and into the Schema specific bundles.
224 * But that makes plugin more reliant on the Typed Bundles more than just API wrapper.
225 * Keeping these Special Handling locally till we introduce the full schema independent APIs in the
228 public String getSpecialCaseParentUUID(Node node, String databaseName, String childTableName) {
229 if (!databaseName.equals(OvsVswitchdSchemaConstants.DATABASE_NAME)) return null;
230 String[] parentColumn = OvsVswitchdSchemaConstants.getParentColumnToMutate(childTableName);
231 if (parentColumn != null && parentColumn[0].equals(OvsVswitchdSchemaConstants.DATABASE_NAME)) {
232 Connection connection = connectionService.getConnection(node);
233 OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
234 ConcurrentMap<String, Row> row = this.getRows(node, openVSwitch.getSchema().getName());
235 if (row == null || row.size() == 0) return null;
236 return (String)row.keySet().toArray()[0];
242 * Though this is a New API that takes in Row object, this still is considered a
243 * Deprecated call because of the assumption with a Single Row insertion.
244 * An ideal insertRow must be able to take in multiple Rows, which includes the
245 * Row being inserted in one Table and other Rows that needs mutate in other Tables.
248 public StatusWithUuid insertRow(Node node, String tableName, String parentUuid, Row<GenericTableSchema> row) {
249 String[] parentColumn = OvsVswitchdSchemaConstants.getParentColumnToMutate(tableName);
250 if (parentColumn == null) {
251 parentColumn = new String[]{null, null};
254 Connection connection = connectionService.getConnection(node);
255 OvsdbClient client = connection.getClient();
257 if (parentUuid == null) {
258 parentUuid = this.getSpecialCaseParentUUID(node, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
260 logger.debug("insertRow Connection : {} Table : {} ParentTable : {} Parent Column: {} Parent UUID : {} Row : {}",
261 client.getConnectionInfo(), tableName, parentColumn[0], parentColumn[1], parentUuid, row);
263 DatabaseSchema dbSchema = client.getDatabaseSchema(OvsVswitchdSchemaConstants.DATABASE_NAME);
264 TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
266 String namedUuid = "Transaction_"+ tableName;
267 this.processInsertTransaction(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName,
268 parentColumn[0], parentUuid, parentColumn[1], namedUuid,
269 row, transactionBuilder);
271 ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
272 List<OperationResult> operationResults;
274 operationResults = results.get();
275 if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
276 return new StatusWithUuid(StatusCode.INTERNALERROR);
278 for (OperationResult result : operationResults) {
279 if (result.getError() != null) {
280 return new StatusWithUuid(StatusCode.BADREQUEST, result.getError());
283 UUID uuid = operationResults.get(0).getUuid();
284 return new StatusWithUuid(StatusCode.SUCCESS, uuid);
285 } catch (InterruptedException | ExecutionException e) {
286 // TODO Auto-generated catch block
287 return new StatusWithUuid(StatusCode.INTERNALERROR, e.getLocalizedMessage());
293 public Status updateRow (Node node, String tableName, String parentUUID, String rowUUID, Row row) {
294 String databaseName = OvsVswitchdSchemaConstants.DATABASE_NAME;
295 Connection connection = connectionService.getConnection(node);
296 OvsdbClient client = connection.getClient();
298 logger.debug("updateRow : Connection : {} databaseName : {} tableName : {} rowUUID : {} row : {}",
299 client.getConnectionInfo(), databaseName, tableName, rowUUID, row.toString());
301 DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
302 TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
303 TableSchema<GenericTableSchema> tableSchema = dbSchema.table(tableName, GenericTableSchema.class);
304 ColumnSchema<GenericTableSchema, UUID> _uuid = tableSchema.column("_uuid", UUID.class);
305 transactionBuilder.add(op.update(tableSchema, row)
306 .where(_uuid.opEqual(new UUID(rowUUID)))
309 ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
310 List<OperationResult> operationResults = results.get();
311 if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
312 return new StatusWithUuid(StatusCode.INTERNALERROR);
314 for (OperationResult result : operationResults) {
315 if (result.getError() != null) {
316 return new StatusWithUuid(StatusCode.BADREQUEST, result.getError());
319 return new StatusWithUuid(StatusCode.SUCCESS);
320 } catch(Exception e){
321 logger.error("Error in updateRow(): ",e);
323 return new Status(StatusCode.INTERNALERROR);
326 private void processDeleteTransaction(OvsdbClient client, String databaseName, String childTable,
327 String parentTable, String parentColumn, String uuid, TransactionBuilder transactionBuilder) {
328 DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
329 TableSchema<GenericTableSchema> childTableSchema = dbSchema.table(childTable, GenericTableSchema.class);
331 if (parentColumn != null) {
332 TableSchema<GenericTableSchema> parentTableSchema = dbSchema.table(parentTable, GenericTableSchema.class);
333 ColumnSchema<GenericTableSchema, UUID> parentColumnSchema = parentTableSchema.column(parentColumn, UUID.class);
335 .add(op.mutate(parentTableSchema)
336 .addMutation(parentColumnSchema, Mutator.DELETE, new UUID(uuid))
337 .where(parentColumnSchema.opIncludes(new UUID(uuid)))
341 ColumnSchema<GenericTableSchema, UUID> _uuid = childTableSchema.column("_uuid", UUID.class);
342 transactionBuilder.add(op.delete(childTableSchema)
343 .where(_uuid.opEqual(new UUID(uuid)))
348 public Status deleteRow(Node node, String tableName, String uuid) {
349 String databaseName = OvsVswitchdSchemaConstants.DATABASE_NAME;
350 Connection connection = connectionService.getConnection(node);
351 OvsdbClient client = connection.getClient();
353 String[] parentColumn = OvsVswitchdSchemaConstants.getParentColumnToMutate(tableName);
354 if (parentColumn == null) {
355 parentColumn = new String[]{null, null};
358 logger.debug("deleteRow : Connection : {} databaseName : {} tableName : {} Uuid : {} ParentTable : {} ParentColumn : {}",
359 client.getConnectionInfo(), databaseName, tableName, uuid, parentColumn[0], parentColumn[1]);
361 DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
362 TransactionBuilder transactionBuilder = client.transactBuilder(dbSchema);
363 this.processDeleteTransaction(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName,
364 parentColumn[0], parentColumn[1], uuid, transactionBuilder);
366 ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
367 List<OperationResult> operationResults;
369 operationResults = results.get();
370 if (operationResults.isEmpty() || (transactionBuilder.getOperations().size() != operationResults.size())) {
371 return new StatusWithUuid(StatusCode.INTERNALERROR);
373 for (OperationResult result : operationResults) {
374 if (result.getError() != null) {
375 return new StatusWithUuid(StatusCode.BADREQUEST, result.getError());
378 } catch (InterruptedException | ExecutionException e) {
379 // TODO Auto-generated catch block
383 return new Status(StatusCode.SUCCESS);
387 public ConcurrentMap<String, Row> getRows(Node node, String tableName) {
388 ConcurrentMap<String, Row> ovsTable = ovsdbInventoryService.getTableCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
393 public Row getRow(Node node, String tableName, String uuid) {
394 Map<String, Row> ovsTable = ovsdbInventoryService.getTableCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
395 if (ovsTable == null) return null;
396 return ovsTable.get(uuid);
400 public List<String> getTables(Node node) {
401 ConcurrentMap<String, ConcurrentMap<String, Row>> cache = ovsdbInventoryService.getCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME);
402 if (cache == null) return null;
403 return new ArrayList<String>(cache.keySet());
406 private List<InetAddress> getControllerIPAddresses(Connection connection) {
407 List<InetAddress> controllers = null;
408 InetAddress controllerIP = null;
410 controllers = new ArrayList<InetAddress>();
411 String addressString = System.getProperty("ovsdb.controller.address");
413 if (addressString != null) {
415 controllerIP = InetAddress.getByName(addressString);
416 if (controllerIP != null) {
417 controllers.add(controllerIP);
420 } catch (UnknownHostException e) {
421 logger.error("Host {} is invalid", addressString);
425 if (clusterServices != null) {
426 controllers = clusterServices.getClusteredControllers();
427 if (controllers != null && controllers.size() > 0) {
428 if (controllers.size() == 1) {
429 InetAddress controller = controllers.get(0);
430 if (!controller.equals(InetAddress.getLoopbackAddress())) {
439 addressString = System.getProperty("of.address");
441 if (addressString != null) {
443 controllerIP = InetAddress.getByName(addressString);
444 if (controllerIP != null) {
445 controllers.add(controllerIP);
448 } catch (UnknownHostException e) {
449 logger.error("Host {} is invalid", addressString);
454 controllerIP = connection.getClient().getConnectionInfo().getLocalAddress();
455 controllers.add(controllerIP);
457 } catch (Exception e) {
458 logger.debug("Invalid connection provided to getControllerIPAddresses", e);
463 private short getControllerOFPort() {
464 Short defaultOpenFlowPort = 6633;
465 Short openFlowPort = defaultOpenFlowPort;
466 String portString = System.getProperty("of.listenPort");
467 if (portString != null) {
469 openFlowPort = Short.decode(portString).shortValue();
470 } catch (NumberFormatException e) {
471 logger.warn("Invalid port:{}, use default({})", portString,
479 public Boolean setOFController(Node node, String bridgeUUID) throws InterruptedException, ExecutionException {
480 Connection connection = this.getConnection(node);
481 if (connection == null) {
485 Bridge bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
487 Status updateOperationStatus = null;
489 OvsdbSet<String> protocols = new OvsdbSet<String>();
491 String ofVersion = System.getProperty("ovsdb.of.version", OPENFLOW_10);
494 protocols.add("OpenFlow13");
499 protocols.add("OpenFlow10");
502 bridge.setProtocols(protocols);
503 updateOperationStatus = this.updateRow(node, bridge.getSchema().getName(),
504 null, bridgeUUID, bridge.getRow());
505 logger.debug("Bridge {} updated to {} with Status {}", bridgeUUID,
506 protocols.toArray()[0],updateOperationStatus);
508 } catch (SchemaVersionMismatchException e){
509 logger.debug(e.toString());
512 // If we fail to update the protocols
513 if (updateOperationStatus != null && !updateOperationStatus.isSuccess()) {
514 return updateOperationStatus.isSuccess();
517 Status status = null;
518 List<InetAddress> ofControllerAddrs = this.getControllerIPAddresses(connection);
519 short ofControllerPort = getControllerOFPort();
520 for (InetAddress ofControllerAddress : ofControllerAddrs) {
521 String newController = "tcp:"+ofControllerAddress.getHostAddress()+":"+ofControllerPort;
522 Controller controllerRow = connection.getClient().createTypedRowWrapper(Controller.class);
523 controllerRow.setTarget(newController);
524 //ToDo: Status gets overwritten on each iteration. If any operation other than the last fails it's ignored.
525 status = this.insertRow(node, controllerRow.getSchema().getName(), bridgeUUID, controllerRow.getRow());
528 if (status != null) {
529 return status.isSuccess();
536 public Boolean setBridgeOFController(Node node, String bridgeIdentifier) {
537 if (connectionService == null) {
538 logger.error("Couldn't refer to the ConnectionService");
543 Connection connection = connectionService.getConnection(node);
544 Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
546 Map<String, Row> brTableCache = ovsdbInventoryService.getTableCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME, bridge.getSchema().getName());
547 for (String uuid : brTableCache.keySet()) {
548 bridge = connection.getClient().getTypedRowWrapper(Bridge.class, brTableCache.get(uuid));
549 if (bridge.getName().contains(bridgeIdentifier)) {
550 return setOFController(node, uuid);
553 } catch(Exception e) {
554 logger.error("Error in setBridgeOFController()",e);
560 public <T extends TypedBaseTable<?>> String getTableName(Node node, Class<T> typedClass) {
561 Connection connection = connectionService.getConnection(node);
562 if (connection == null) return null;
563 OvsdbClient client = connection.getClient();
564 TypedBaseTable<?> typedTable = client.getTypedRowWrapper(typedClass, null);
565 if (typedTable == null) return null;
566 return typedTable.getSchema().getName();
570 public <T extends TypedBaseTable<?>> T getTypedRow(Node node, Class<T> typedClass, Row row) {
571 Connection connection = connectionService.getConnection(node);
572 if (connection == null) return null;
573 OvsdbClient client = connection.getClient();
574 return (T)client.getTypedRowWrapper(typedClass, row);
578 public <T extends TypedBaseTable<?>> T createTypedRow(Node node, Class<T> typedClass) {
579 Connection connection = connectionService.getConnection(node);
580 if (connection == null) return null;
581 OvsdbClient client = connection.getClient();
582 return client.createTypedRowWrapper(typedClass);
585 public void _ovsconnect (CommandInterpreter ci) {
586 String bridgeName = ci.nextArgument();
587 if (bridgeName == null) {
588 ci.println("Please enter Bridge Name");
592 String ovsdbserver = ci.nextArgument();
593 if (ovsdbserver == null) {
594 ci.println("Please enter valid IP-Address");
598 InetAddress.getByName(ovsdbserver);
599 } catch (UnknownHostException e) {
600 logger.error("Unable to resolve " + ovsdbserver, e);
601 ci.println("Please enter valid IP-Address");
604 String port = ci.nextArgument();
609 ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
610 Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
611 params.put(ConnectionConstants.ADDRESS, ovsdbserver);
612 params.put(ConnectionConstants.PORT, port);
613 Node node = connectionService.connect(bridgeName, params);
614 if (node != null) ci.println("Node Name: "+node.toString());
615 else ci.println("Could not connect to Node");
618 public void _addBridge (CommandInterpreter ci) {
619 String nodeName = ci.nextArgument();
620 if (nodeName == null) {
621 ci.println("Please enter Node Name");
624 String bridgeName = ci.nextArgument();
625 if (bridgeName == null) {
626 ci.println("Please enter Bridge Name");
631 Node node = Node.fromString(nodeName);
633 ci.println("Invalid Node");
636 status = this.createBridgeDomain(node, bridgeName, null);
637 ci.println("Bridge creation status : "+status.toString());
640 public void _getBridgeDomains (CommandInterpreter ci) {
641 String nodeName = ci.nextArgument();
642 if (nodeName == null) {
643 ci.println("Please enter Node Name");
647 List<String> brlist = new ArrayList<String>();
648 Node node = Node.fromString(nodeName);
649 brlist = this.getBridgeDomains(node);
651 ci.println("Invalid Node");
654 ci.println("Existing Bridges: "+brlist.toString());
657 public void _deleteBridgeDomain (CommandInterpreter ci) {
658 String nodeName = ci.nextArgument();
659 if (nodeName == null) {
660 ci.println("Please enter Node Name");
663 String bridgeName = ci.nextArgument();
664 if (bridgeName == null) {
665 ci.println("Please enter Bridge Name");
669 Node node = Node.fromString(nodeName);
671 ci.println("Invalid Node");
674 status = this.deleteBridgeDomain(node, bridgeName);
675 ci.println("Bridge deletion status : "+status.toString());
678 public void _addPort (CommandInterpreter ci) {
679 String nodeName = ci.nextArgument();
680 if (nodeName == null) {
681 ci.println("Please enter Node Name");
685 String bridgeName = ci.nextArgument();
686 if (bridgeName == null) {
687 ci.println("Please enter Bridge Name");
691 String portName = ci.nextArgument();
692 if (portName == null) {
693 ci.println("Please enter Port Name");
697 String type = ci.nextArgument();
699 Map<String, String> configs = new HashMap<String, String>();
701 String configKey = ci.nextArgument();
702 if (configKey == null) break;
703 String configValue = ci.nextArgument();
704 if (configValue == null) break;
705 configs.put(configKey, configValue);
708 Map<ConfigConstants, Object> customConfigs = null;
710 customConfigs = new HashMap<ConfigConstants, Object>();
711 customConfigs.put(ConfigConstants.TYPE, type);
714 if (configs.size() > 0) {
715 if (customConfigs == null) customConfigs = new HashMap<ConfigConstants, Object>();
716 customConfigs.put(ConfigConstants.CUSTOM, configs);
717 ci.println(customConfigs.toString());
720 Node node = Node.fromString(nodeName);
722 ci.println("Invalid Node");
725 status = this.addPort(node, bridgeName, portName, customConfigs);
726 ci.println("Port creation status : "+status.toString());
729 public void _deletePort (CommandInterpreter ci) {
730 String nodeName = ci.nextArgument();
731 if (nodeName == null) {
732 ci.println("Please enter Node Name");
736 String bridgeName = ci.nextArgument();
737 if (bridgeName == null) {
738 ci.println("Please enter Bridge Name");
742 String portName = ci.nextArgument();
743 if (portName == null) {
744 ci.println("Please enter Port Name");
749 Node node = Node.fromString(nodeName);
751 ci.println("Invalid Node");
754 status = this.deletePort(node, bridgeName, portName);
755 ci.println("Port deletion status : "+status.toString());
758 public void _addPortVlan (CommandInterpreter ci) {
759 String nodeName = ci.nextArgument();
760 if (nodeName == null) {
761 ci.println("Please enter Node Name");
765 String bridgeName = ci.nextArgument();
766 if (bridgeName == null) {
767 ci.println("Please enter Bridge Name");
771 String portName = ci.nextArgument();
772 if (portName == null) {
773 ci.println("Please enter Port Name");
777 String vlan = ci.nextArgument();
779 ci.println("Please enter Valid Vlan");
783 Integer.parseInt(vlan);
784 } catch (NumberFormatException e) {
785 ci.println("Please enter Valid Vlan");
790 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
791 configs.put(ConfigConstants.TYPE, "VLAN");
792 configs.put(ConfigConstants.VLAN, vlan);
795 Node node = Node.fromString(nodeName);
797 ci.println("Invalid Node");
800 status = this.addPort(node, bridgeName, portName, configs);
801 ci.println("Port creation status : "+status.toString());
804 public void _addTunnel (CommandInterpreter ci) {
805 String nodeName = ci.nextArgument();
806 if (nodeName == null) {
807 ci.println("Please enter Node Name");
811 String bridgeName = ci.nextArgument();
812 if (bridgeName == null) {
813 ci.println("Please enter Bridge Name");
817 String portName = ci.nextArgument();
818 if (portName == null) {
819 ci.println("Please enter Port Name");
823 String tunnelType = ci.nextArgument();
824 if (tunnelType == null) {
825 ci.println("Please enter Tunnel Type");
829 String remoteIp = ci.nextArgument();
830 if (remoteIp == null) {
831 ci.println("Please enter valid Remote IP Address");
836 InetAddress.getByName(remoteIp);
837 } catch (Exception e) {
838 logger.error("Unable to resolve " + remoteIp, e);
839 ci.println("Please enter valid Remote IP Address");
843 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
844 configs.put(ConfigConstants.TYPE, "TUNNEL");
845 configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
846 configs.put(ConfigConstants.DEST_IP, remoteIp);
849 Node node = Node.fromString(nodeName);
851 ci.println("Invalid Node");
854 status = this.addPort(node, bridgeName, portName, configs);
855 ci.println("Port creation status : "+status.toString());
858 public void _printCache (CommandInterpreter ci) {
859 String nodeName = ci.nextArgument();
860 if (nodeName == null) {
861 ci.println("Please enter Node Name");
864 Node node = Node.fromString(nodeName);
866 ci.println("Invalid Node");
869 ovsdbInventoryService.printCache(node);
872 public void _forceConnect (CommandInterpreter ci) {
873 String force = ci.nextArgument();
874 if (force.equalsIgnoreCase("YES")) {
877 else if (force.equalsIgnoreCase("NO")) {
878 forceConnect = false;
881 ci.println("Please enter YES or NO.");
883 ci.println("Current ForceConnect State : "+forceConnect);
887 public String getHelp() {
888 StringBuilder help = new StringBuilder();
889 help.append("---OVSDB CLI---\n");
890 help.append("\t ovsconnect <ConnectionName> <ip-address> - Connect to OVSDB\n");
891 help.append("\t addBridge <Node> <BridgeName> - Add Bridge\n");
892 help.append("\t getBridgeDomains <Node> - Get Bridges\n");
893 help.append("\t deleteBridgeDomain <Node> <BridgeName> - Delete a Bridge\n");
894 help.append("\t addPort <Node> <BridgeName> <PortName> <type> <options pairs> - Add Port\n");
895 help.append("\t deletePort <Node> <BridgeName> <PortName> - Delete Port\n");
896 help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan> - Add Port, Vlan\n");
897 help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip> - Add Tunnel\n");
898 help.append("\t printCache <Node> - Prints Table Cache");
899 return help.toString();
905 * @param node Node serving this configuration service
906 * @param bridgeIdentifier String representation of a Bridge Connector
907 * @return Bridge Connector configurations
911 public Status createBridgeDomain(Node node, String bridgeIdentifier, Map<ConfigConstants, Object> configs) {
912 Connection connection = connectionService.getConnection(node);
913 OvsdbClient client = connection.getClient();
914 Bridge bridge = client.createTypedRowWrapper(Bridge.class);
915 bridge.setName(bridgeIdentifier);
917 String ovsTableUuid = this.getSpecialCaseParentUUID(node, OvsVswitchdSchemaConstants.DATABASE_NAME, bridge.getSchema().getName());
918 return this.insertRow(node, bridge.getSchema().getName(), ovsTableUuid, bridge.getRow());
922 * Create a Port Attached to a Bridge
923 * Ex. ovs-vsctl add-port br0 vif0
924 * @param node Node serving this configuration service
925 * @param bridgeIdentifier String representation of a Bridge Domain
926 * @param portIdentifier String representation of a user defined Port Name
930 public Status addPort(Node node, String bridgeIdentifier, String portIdentifier,
931 Map<ConfigConstants, Object> configs) {
932 Connection connection = connectionService.getConnection(node);
933 OvsdbClient client = connection.getClient();
935 Bridge bridge = client.getTypedRowWrapper(Bridge.class, null);
936 ConcurrentMap<String, Row> rows = this.getRows(node, bridge.getSchema().getName());
937 if (rows == null || rows.size() == 0) {
938 return new Status(StatusCode.NOTFOUND);
940 for (String bridgeUuid : rows.keySet()) {
941 Row bridgeRow = rows.get(bridgeUuid);
942 bridge = client.getTypedRowWrapper(Bridge.class, bridgeRow);
943 if (bridge.getName().equals(bridgeIdentifier)) break;
945 if (bridge.getName() == null || !bridge.getName().equals(bridgeIdentifier)) {
946 return new Status(StatusCode.NOTFOUND);
949 Map<String, String> options = null;
951 Set<Long> tags = null;
952 if (configs != null) {
953 type = (String) configs.get(ConfigConstants.TYPE);
954 Map<String, String> customConfigs = (Map<String, String>) configs.get(ConfigConstants.CUSTOM);
955 if (customConfigs != null) {
956 options = new HashMap<String, String>();
957 for (String customConfig : customConfigs.keySet()) {
958 options.put(customConfig, customConfigs.get(customConfig));
964 logger.debug("Port type : " + type);
965 if (type.equalsIgnoreCase(OvsVswitchdSchemaConstants.PortType.VLAN.name())) {
966 tags = new HashSet<Long>();
967 tags.add(Long.parseLong((String)configs.get(ConfigConstants.VLAN)));
971 Port port = client.createTypedRowWrapper(Port.class);
972 port.setName(portIdentifier);
973 if (tags != null) port.setTag(tags);
974 StatusWithUuid portStatus = this.insertRow(node, port.getSchema().getName(), bridge.getUuid().toString(), port.getRow());
976 if (!portStatus.isSuccess()) return portStatus;
977 // Ugly hack by adding a sleep for the Monitor Update to catch up.
978 // TODO : Remove this once the Select operation is in place.
979 // We are currently relying on the local Cache for any GET operation and that might fail if we try to
980 // fetch the last installed entry. Hence we need the Select operation to work.
984 } catch (InterruptedException e) {
985 // TODO Auto-generated catch block
989 Interface interfaceRow = client.createTypedRowWrapper(Interface.class);
990 ConcurrentMap<String, Row> intfRows = this.getRows(node, interfaceRow.getSchema().getName());
991 if (intfRows == null || intfRows.size() == 0) {
992 return new Status(StatusCode.NOTFOUND);
994 for (String intfUuid : intfRows.keySet()) {
995 Row intfRow = rows.get(intfUuid);
996 interfaceRow = client.getTypedRowWrapper(Interface.class, intfRow);
997 if (interfaceRow == null || interfaceRow.getName() == null) continue;
998 if (interfaceRow.getName().equals(portIdentifier)) break;
1000 if (interfaceRow.getName() == null || !interfaceRow.getName().equals(portIdentifier)) {
1001 return new Status(StatusCode.NOTFOUND);
1005 logger.debug("Interface type : " + type);
1006 if (type.equalsIgnoreCase(OvsVswitchdSchemaConstants.PortType.TUNNEL.name())) {
1007 interfaceRow.setType((String)configs.get(ConfigConstants.TUNNEL_TYPE));
1008 if (options == null) options = new HashMap<String, String>();
1009 options.put("remote_ip", (String)configs.get(ConfigConstants.DEST_IP));
1010 } else if (type.equalsIgnoreCase(OvsVswitchdSchemaConstants.PortType.PATCH.name()) ||
1011 type.equalsIgnoreCase(OvsVswitchdSchemaConstants.PortType.INTERNAL.name())) {
1012 interfaceRow.setType(type.toLowerCase());
1015 if (options != null) {
1016 interfaceRow.setOptions(options);
1019 Status intfStatus = null;
1020 intfStatus = this.updateRow(node, interfaceRow.getSchema().getName(), portStatus.getUuid().toString(),
1021 interfaceRow.getUuid().toString(), interfaceRow.getRow());
1023 if (intfStatus.isSuccess()) return portStatus;
1028 * Implements the OVS Connection for Managers
1030 * @param node Node serving this configuration service
1031 * @param managerip String Representing IP and connection types
1033 @SuppressWarnings("unchecked")
1035 public boolean setManager(Node node, String managerip) {
1036 Connection connection = connectionService.getConnection(node);
1037 OvsdbClient client = connection.getClient();
1038 Manager manager = client.createTypedRowWrapper(Manager.class);
1039 manager.setTarget(ImmutableSet.of(managerip));
1041 OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
1042 ConcurrentMap<String, Row> row = this.getRows(node, openVSwitch.getSchema().getName());
1043 if (row == null || row.size() == 0) {
1046 String ovsTableUuid = (String)row.keySet().toArray()[0];
1048 Status status = this.insertRow(node, manager.getSchema().getName(), ovsTableUuid, manager.getRow());
1049 return status.isSuccess();
1054 public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
1055 Map<ConfigConstants, Object> configs) {
1056 String mgmt = (String)configs.get(ConfigConstants.MGMT);
1058 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
1060 return new Status(StatusCode.BADREQUEST);
1065 public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
1066 Connection connection = connectionService.getConnection(node);
1067 OvsdbClient client = connection.getClient();
1069 Port port = client.getTypedRowWrapper(Port.class, null);
1070 ConcurrentMap<String, Row> rows = this.getRows(node, port.getSchema().getName());
1071 if (rows == null || rows.size() == 0) {
1072 return new Status(StatusCode.NOTFOUND);
1074 for (String portUuid : rows.keySet()) {
1075 Row bridgeRow = rows.get(portUuid);
1076 port = client.getTypedRowWrapper(Port.class, bridgeRow);
1077 if (port.getName().equals(portIdentifier)) break;
1079 if (port.getName() == null || !port.getName().equals(portIdentifier)) {
1080 return new Status(StatusCode.NOTFOUND);
1082 return this.deleteRow(node, port.getSchema().getName(), port.getUuid().toString());
1087 public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
1088 Connection connection = connectionService.getConnection(node);
1089 OvsdbClient client = connection.getClient();
1091 Bridge bridge = client.getTypedRowWrapper(Bridge.class, null);
1092 ConcurrentMap<String, Row> rows = this.getRows(node, bridge.getSchema().getName());
1093 if (rows == null || rows.size() == 0) {
1094 return new Status(StatusCode.NOTFOUND);
1096 for (String bridgeUuid : rows.keySet()) {
1097 Row bridgeRow = rows.get(bridgeUuid);
1098 bridge = client.getTypedRowWrapper(Bridge.class, bridgeRow);
1099 if (bridge.getName().equals(bridgeIdentifier)) break;
1101 if (bridge.getName() == null || !bridge.getName().equals(bridgeIdentifier)) {
1102 return new Status(StatusCode.NOTFOUND);
1104 return this.deleteRow(node, bridge.getSchema().getName(), bridge.getUuid().toString());
1108 public List<String> getBridgeDomains(Node node) {
1109 if (connectionService == null) {
1110 logger.error("Couldn't refer to the ConnectionService");
1114 Connection connection = connectionService.getConnection(node);
1115 Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
1116 List<String> brlist = new ArrayList<String>();
1117 Map<String, Row> brTableCache = ovsdbInventoryService.getTableCache(node, OvsVswitchdSchemaConstants.DATABASE_NAME, bridge.getSchema().getName());
1118 if(brTableCache != null){
1119 for (String uuid : brTableCache.keySet()) {
1120 bridge = connection.getClient().getTypedRowWrapper(Bridge.class, brTableCache.get(uuid));
1121 brlist.add(bridge.getName());
1128 public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
1134 public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
1135 Map<ConfigConstants, Object> configs) {
1136 // TODO Auto-generated method stub
1142 public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
1143 // TODO Auto-generated method stub
1149 public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
1150 String portIdentifier) {
1151 // TODO Auto-generated method stub
1157 public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
1158 Map<ConfigConstants, Object> configs) {
1159 // TODO Auto-generated method stub
1165 public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
1166 Map<ConfigConstants, Object> configs) {
1167 // TODO Auto-generated method stub
1173 public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
1174 // TODO Auto-generated method stub
1179 public UUID insertRow(Node node, String databaseName, String tableName, String parentTable, UUID parentUuid,
1180 String parentColumn, Row<GenericTableSchema> row) throws OvsdbPluginException {
1181 throw new OvsdbPluginException("Not implemented Yet");
1185 public UUID insertRow(Node node, String databaseName, String tableName,
1186 UUID parentRowUuid, Row<GenericTableSchema> row)
1187 throws OvsdbPluginException {
1188 throw new OvsdbPluginException("Not implemented Yet");
1192 public Row<GenericTableSchema> insertTree(Node node, String databaseName, String tableName, String parentTable, UUID parentRowUuid,
1193 String parentColumn, Row<GenericTableSchema> row) throws OvsdbPluginException {
1194 throw new OvsdbPluginException("Not implemented Yet");
1198 public Row<GenericTableSchema> insertTree(Node node, String databaseName,
1199 String tableName, UUID parentRowUuid, Row<GenericTableSchema> row)
1200 throws OvsdbPluginException {
1201 throw new OvsdbPluginException("Not implemented Yet");
1205 public Row<GenericTableSchema> updateRow(Node node, String databaseName,
1206 String tableName, UUID rowUuid, Row<GenericTableSchema> row,
1207 boolean overwrite) throws OvsdbPluginException {
1208 throw new OvsdbPluginException("Not implemented Yet");
1212 public void deleteRow(Node node, String databaseName, String tableName, String parentTable, UUID parentRowUuid,
1213 String parentColumn, UUID rowUuid) throws OvsdbPluginException {
1214 throw new OvsdbPluginException("Not implemented Yet");
1218 public void deleteRow(Node node, String databaseName, String tableName,
1219 UUID rowUuid) throws OvsdbPluginException {
1220 throw new OvsdbPluginException("Not implemented Yet");
1224 public Row<GenericTableSchema> getRow(Node node, String databaseName,
1225 String tableName, UUID uuid) throws OvsdbPluginException {
1226 throw new OvsdbPluginException("Not implemented Yet");
1230 public ConcurrentMap<UUID, Row<GenericTableSchema>> getRows(Node node,
1231 String databaseName, String tableName) throws OvsdbPluginException {
1232 throw new OvsdbPluginException("Not implemented Yet");
1236 public ConcurrentMap<UUID, Row<GenericTableSchema>> getRows(Node node,
1237 String databaseName, String tableName, String fiqlQuery)
1238 throws OvsdbPluginException {
1239 throw new OvsdbPluginException("Not implemented Yet");
1243 public List<String> getTables(Node node, String databaseName) throws OvsdbPluginException {
1244 throw new OvsdbPluginException("Not implemented Yet");