1 package org.opendaylight.ovsdb.plugin;
3 import java.net.InetAddress;
6 import org.eclipse.osgi.framework.console.CommandInterpreter;
7 import org.eclipse.osgi.framework.console.CommandProvider;
8 import org.opendaylight.ovsdb.lib.database.OVSBridge;
9 import org.opendaylight.ovsdb.lib.database.OVSInstance;
10 import org.opendaylight.ovsdb.lib.database.OvsdbType;
11 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
12 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
13 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
14 import org.opendaylight.ovsdb.lib.message.operations.Operation;
15 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
16 import org.opendaylight.ovsdb.lib.notation.Condition;
17 import org.opendaylight.ovsdb.lib.notation.Function;
18 import org.opendaylight.ovsdb.lib.notation.Mutation;
19 import org.opendaylight.ovsdb.lib.notation.Mutator;
20 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.table.Bridge;
23 import org.opendaylight.ovsdb.lib.table.Interface;
24 import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
25 import org.opendaylight.ovsdb.lib.table.Port;
26 import org.opendaylight.ovsdb.lib.table.internal.Table;
27 import org.opendaylight.controller.sal.connection.ConnectionConstants;
28 import org.opendaylight.controller.sal.core.Node;
29 import org.opendaylight.controller.sal.core.NodeConnector;
30 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
31 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
32 import org.opendaylight.controller.sal.utils.Status;
33 import org.opendaylight.controller.sal.utils.StatusCode;
34 import org.osgi.framework.BundleContext;
35 import org.osgi.framework.FrameworkUtil;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.common.util.concurrent.ListenableFuture;
41 public class ConfigurationService implements IPluginInBridgeDomainConfigService, CommandProvider
43 private static final Logger logger = LoggerFactory
44 .getLogger(ConfigurationService.class);
46 IConnectionServiceInternal connectionService;
47 InventoryServiceInternal inventoryServiceInternal;
48 boolean forceConnect = false;
54 * Function called by the dependency manager when at least one dependency
55 * become unsatisfied or when the component is shutting down because for
56 * example bundle is being stopped.
63 * Function called by dependency manager after "init ()" is called and after
64 * the services provided by the class are registered in the service registry
68 registerWithOSGIConsole();
71 private void registerWithOSGIConsole() {
72 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
74 bundleContext.registerService(CommandProvider.class.getName(), this,
79 * Function called by the dependency manager before the services exported by
80 * the component are unregistered, this will be followed by a "destroy ()"
87 public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
88 this.connectionService = connectionService;
91 public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
92 if (this.connectionService == connectionService) {
93 this.connectionService = null;
97 public void setInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
98 this.inventoryServiceInternal = inventoryServiceInternal;
101 public void unsetInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
102 if (this.inventoryServiceInternal == inventoryServiceInternal) {
103 this.inventoryServiceInternal = null;
107 private Connection getConnection (Node node) {
108 Connection connection = connectionService.getConnection(node);
109 if (connection == null || !connection.getChannel().isActive()) {
117 * @param node Node serving this configuration service
118 * @param bridgeConnectorIdentifier String representation of a Bridge Connector
119 * @return Bridge Connector configurations
122 public Status createBridgeDomain(Node node, String bridgeIdentifier,
123 Map<ConfigConstants, Object> configs) throws Throwable {
125 if (connectionService == null) {
126 logger.error("Couldn't refer to the ConnectionService");
127 return new Status(StatusCode.NOSERVICE);
130 Connection connection = this.getConnection(node);
131 if (connection == null) {
132 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
135 Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
136 String newBridge = "new_bridge";
137 String newInterface = "new_interface";
138 String newPort = "new_port";
139 String newSwitch = "new_switch";
141 Operation addSwitchRequest = null;
143 if(ovsTable != null){
144 String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
145 UUID bridgeUuidPair = new UUID(newBridge);
146 Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuidPair);
147 List<Mutation> mutations = new ArrayList<Mutation>();
150 UUID uuid = new UUID(ovsTableUUID);
151 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
152 List<Condition> where = new ArrayList<Condition>();
153 where.add(condition);
154 addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
157 Open_vSwitch ovsTableRow = new Open_vSwitch();
158 OvsDBSet<UUID> bridges = new OvsDBSet<UUID>();
159 UUID bridgeUuidPair = new UUID(newBridge);
160 bridges.add(bridgeUuidPair);
161 ovsTableRow.setBridges(bridges);
162 addSwitchRequest = new InsertOperation(Open_vSwitch.NAME.getName(), newSwitch, ovsTableRow);
165 Bridge bridgeRow = new Bridge();
166 bridgeRow.setName(bridgeIdentifier);
167 OvsDBSet<UUID> ports = new OvsDBSet<UUID>();
168 UUID port = new UUID(newPort);
170 bridgeRow.setPorts(ports);
171 InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
173 Port portRow = new Port();
174 portRow.setName(bridgeIdentifier);
175 OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
176 UUID interfaceid = new UUID(newInterface);
177 interfaces.add(interfaceid);
178 portRow.setInterfaces(interfaces);
179 InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
181 Interface interfaceRow = new Interface();
182 interfaceRow.setName(bridgeIdentifier);
183 interfaceRow.setType("internal");
184 InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(), newInterface, interfaceRow);
186 TransactBuilder transaction = new TransactBuilder();
187 transaction.addOperations(new ArrayList<Operation>(
188 Arrays.asList(addSwitchRequest, addIntfRequest, addPortRequest, addBridgeRequest)));
190 ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
191 List<OperationResult> tr = transResponse.get();
192 List<Operation> requests = transaction.getRequests();
193 Status status = new Status(StatusCode.SUCCESS);
194 for (int i = 0; i < tr.size() ; i++) {
195 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
196 if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
197 OperationResult result = tr.get(i);
198 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
202 if (tr.size() > requests.size()) {
203 OperationResult result = tr.get(tr.size()-1);
204 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
206 result.getDetails());
207 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
210 } catch(Exception e){
213 return new Status(StatusCode.INTERNALERROR);
217 * Create a Port Attached to a Bridge
218 * Ex. ovs-vsctl add-port br0 vif0
219 * @param node Node serving this configuration service
220 * @param bridgeDomainIdentifier String representation of a Bridge Domain
221 * @param portIdentifier String representation of a user defined Port Name
224 public Status addPort(Node node, String bridgeIdentifier, String portIdentifier, Map<ConfigConstants, Object> configs) {
226 if (connectionService == null) {
227 logger.error("Couldn't refer to the ConnectionService");
228 return new Status(StatusCode.NOSERVICE);
230 Connection connection = this.getConnection(node);
231 if (connection == null) {
232 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
235 if (connection != null) {
236 String newInterface = "new_interface";
237 String newPort = "new_port";
239 Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
241 OVSBridge bridge = existingBridges.get(bridgeIdentifier);
243 List<String> portUuidPair = new ArrayList<String>();
244 portUuidPair.add("named-uuid");
245 portUuidPair.add(newPort);
247 List<Object> mutation = new ArrayList<Object>();
248 mutation.add("ports");
249 mutation.add("insert");
250 mutation.add(portUuidPair);
251 List<Object> mutations = new ArrayList<Object>();
252 mutations.add(mutation);
254 List<String> bridgeUuidPair = new ArrayList<String>();
255 bridgeUuidPair.add("uuid");
256 bridgeUuidPair.add(bridge.getUuid());
258 List<Object> whereInner = new ArrayList<Object>();
259 whereInner.add("_uuid");
260 whereInner.add("==");
261 whereInner.add(bridgeUuidPair);
263 List<Object> where = new ArrayList<Object>();
264 where.add(whereInner);
266 MutateRequest mutateBridgeRequest = new MutateRequest("Bridge", where, mutations);
268 Map<String, Object> portRow = new HashMap<String, Object>();
269 portRow.put("name", portIdentifier);
270 String portType = null;
271 if (configs != null) {
272 portType = (String)configs.get(ConfigConstants.TYPE);
273 if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
275 portRow.put("tag", Integer.parseInt((String)configs.get(ConfigConstants.VLAN)));
276 } catch (Exception e) {
280 ArrayList<String> interfaces = new ArrayList<String>();
281 interfaces.add("named-uuid");
282 interfaces.add(newInterface);
283 portRow.put("interfaces", interfaces);
284 InsertRequest addPortRequest = new InsertRequest("insert", "Port", newPort, portRow);
286 Map<String, Object> interfaceRow = new HashMap<String, Object>();
287 interfaceRow.put("name", portIdentifier);
290 if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
291 interfaceRow.put("type", configs.get(ConfigConstants.TUNNEL_TYPE));
292 ArrayList<Object> intopt = new ArrayList<Object>();
293 interfaceRow.put("options", intopt);
294 ArrayList<Object> intoptmap = new ArrayList<Object>();
295 ArrayList<String> intoptep = new ArrayList<String>();
297 intopt.add(intoptmap);
298 intoptmap.add(intoptep);
299 intoptep.add("remote_ip");
300 intoptep.add((String)configs.get(ConfigConstants.DEST_IP));
302 InsertRequest addIntfRequest = new InsertRequest("insert", "Interface", newInterface, interfaceRow);
304 Object[] params = {"Open_vSwitch", mutateBridgeRequest, addIntfRequest, addPortRequest};
305 OvsdbMessage msg = new OvsdbMessage("transact", params);
307 //connection.sendMessage(msg);
312 return new Status(StatusCode.SUCCESS);
315 * Implements the OVS Connection for Managers
317 * @param node Node serving this configuration service
318 * @param String with IP and connection types
320 @SuppressWarnings("unchecked")
321 public boolean setManager(Node node, String managerip) throws Throwable{
323 if (connectionService == null) {
324 logger.error("Couldn't refer to the ConnectionService");
327 Connection connection = this.getConnection(node);
328 if (connection == null) {
332 if (connection != null) {
333 String newmanager = "new_manager";
335 OVSInstance instance = OVSInstance.monitorOVS(connection);
337 Map ovsoutter = new LinkedHashMap();
338 Map ovsinner = new LinkedHashMap();
339 ArrayList ovsalist1 = new ArrayList();
340 ArrayList ovsalist2 = new ArrayList();
341 ArrayList ovsalist3 = new ArrayList();
342 ArrayList ovsalist4 = new ArrayList();
345 ovsoutter.put("where", ovsalist1);
346 ovsalist1.add(ovsalist2);
347 ovsalist2.add("_uuid");
349 ovsalist2.add(ovsalist3);
350 ovsalist3.add("uuid");
351 ovsalist3.add(instance.getUuid());
352 ovsoutter.put("op", "update");
353 ovsoutter.put("table", "Open_vSwitch");
354 ovsoutter.put("row", ovsinner);
355 ovsinner.put("manager_options", ovsalist4);
356 ovsalist4.add("named-uuid");
357 ovsalist4.add(newmanager);
359 Map mgroutside = new LinkedHashMap();
360 Map mgrinside = new LinkedHashMap();
362 //Manager Table Insert
363 mgroutside.put("uuid-name", newmanager);
364 mgroutside.put("op", "insert");
365 mgroutside.put("table","Manager");
366 mgroutside.put("row", mgrinside);
367 mgrinside.put("target", managerip);
369 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
370 OvsdbMessage msg = new OvsdbMessage("transact", params);
372 //connection.sendMessage(msg);
382 public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
383 Map<ConfigConstants, Object> configs) {
384 String mgmt = (String)configs.get(ConfigConstants.MGMT);
387 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
388 } catch (Throwable e) {
389 // TODO Auto-generated catch block
391 return new Status(StatusCode.INTERNALERROR);
394 return new Status(StatusCode.BADREQUEST);
398 public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
399 Map<ConfigConstants, Object> configs) {
400 // TODO Auto-generated method stub
405 public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
406 // TODO Auto-generated method stub
411 public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
412 // TODO Auto-generated method stub
417 public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
418 String portIdentifier) {
419 // TODO Auto-generated method stub
424 public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
425 Map<ConfigConstants, Object> configs) {
426 // TODO Auto-generated method stub
431 public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
432 Map<ConfigConstants, Object> configs) {
433 // TODO Auto-generated method stub
438 public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
439 // TODO Auto-generated method stub
444 public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
445 // TODO Auto-generated method stub
450 public List<String> getBridgeDomains(Node node) {
452 Connection connection = connectionService.getConnection(node);
453 Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
454 List<String> bridgeDomains = new ArrayList<String>(existingBridges.keySet());
455 return bridgeDomains;
459 public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
463 public void _ovsconnect (CommandInterpreter ci) {
464 String bridgeName = ci.nextArgument();
465 if (bridgeName == null) {
466 ci.println("Please enter Bridge Name");
470 String ovsdbserver = ci.nextArgument();
471 if (ovsdbserver == null) {
472 ci.println("Please enter valid IP-Address");
476 InetAddress.getByName(ovsdbserver);
477 } catch (Exception e) {
479 ci.println("Please enter valid IP-Address");
482 String port = ci.nextArgument();
487 ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
488 Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
489 params.put(ConnectionConstants.ADDRESS, ovsdbserver);
490 params.put(ConnectionConstants.PORT, port);
491 Node node = connectionService.connect(bridgeName, params);
492 if (node != null) ci.println("Node Name: "+node.toString());
493 else ci.println("Could not connect to Node");
496 public void _addBridge (CommandInterpreter ci) {
497 String nodeName = ci.nextArgument();
498 if (nodeName == null) {
499 ci.println("Please enter Node Name");
503 String bridgeName = ci.nextArgument();
504 if (bridgeName == null) {
505 ci.println("Please enter Bridge Name");
510 status = this.createBridgeDomain(Node.fromString(nodeName), bridgeName, null);
511 ci.println("Bridge creation status : "+status.toString());
512 } catch (Throwable e) {
513 // TODO Auto-generated catch block
515 ci.println("Failed to create Bridge "+bridgeName);
519 public void _addPort (CommandInterpreter ci) {
520 String nodeName = ci.nextArgument();
521 if (nodeName == null) {
522 ci.println("Please enter Node Name");
526 String bridgeName = ci.nextArgument();
527 if (bridgeName == null) {
528 ci.println("Please enter Bridge Name");
532 String portName = ci.nextArgument();
533 if (portName == null) {
534 ci.println("Please enter Port Name");
540 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, null);
541 ci.println("Port creation status : "+status.toString());
542 } catch (Throwable e) {
543 // TODO Auto-generated catch block
545 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
549 public void _addPortVlan (CommandInterpreter ci) {
550 String nodeName = ci.nextArgument();
551 if (nodeName == null) {
552 ci.println("Please enter Node Name");
556 String bridgeName = ci.nextArgument();
557 if (bridgeName == null) {
558 ci.println("Please enter Bridge Name");
562 String portName = ci.nextArgument();
563 if (portName == null) {
564 ci.println("Please enter Port Name");
568 String vlan = ci.nextArgument();
570 ci.println("Please enter Valid Vlan");
574 Integer.parseInt(vlan);
575 } catch (Exception e) {
576 ci.println("Please enter Valid Vlan");
581 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
582 configs.put(ConfigConstants.TYPE, "VLAN");
583 configs.put(ConfigConstants.VLAN, vlan);
587 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
588 ci.println("Port creation status : "+status.toString());
589 } catch (Throwable e) {
590 // TODO Auto-generated catch block
592 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
596 public void _addTunnel (CommandInterpreter ci) {
597 String nodeName = ci.nextArgument();
598 if (nodeName == null) {
599 ci.println("Please enter Node Name");
603 String bridgeName = ci.nextArgument();
604 if (bridgeName == null) {
605 ci.println("Please enter Bridge Name");
609 String portName = ci.nextArgument();
610 if (portName == null) {
611 ci.println("Please enter Port Name");
615 String tunnelType = ci.nextArgument();
616 if (tunnelType == null) {
617 ci.println("Please enter Tunnel Type");
621 String remoteIp = ci.nextArgument();
622 if (remoteIp == null) {
623 ci.println("Please enter valid Remote IP Address");
628 InetAddress.getByName(remoteIp);
629 } catch (Exception e) {
631 ci.println("Please enter valid Remote IP Address");
635 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
636 configs.put(ConfigConstants.TYPE, "TUNNEL");
637 configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
638 configs.put(ConfigConstants.DEST_IP, remoteIp);
642 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
643 ci.println("Port creation status : "+status.toString());
644 } catch (Throwable e) {
645 // TODO Auto-generated catch block
647 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
651 public void _printCache (CommandInterpreter ci) {
652 String nodeName = ci.nextArgument();
653 if (nodeName == null) {
654 ci.println("Please enter Node Name");
657 inventoryServiceInternal.printCache(Node.fromString(nodeName));
660 public void _forceConnect (CommandInterpreter ci) {
661 String force = ci.nextArgument();
662 if (force.equalsIgnoreCase("YES")) forceConnect = true;
663 else if (force.equalsIgnoreCase("NO")) forceConnect = false;
664 else ci.println("Please enter YES or NO.");
665 ci.println("Current ForceConnect State : "+forceConnect);
670 public String getHelp() {
671 StringBuffer help = new StringBuffer();
672 help.append("---OVSDB CLI---\n");
673 help.append("\t ovsconnect <ConnectionName> <ip-address> - Connect to OVSDB\n");
674 help.append("\t addBridge <Node> <BridgeName> - Add Bridge\n");
675 help.append("\t addPort <Node> <BridgeName> <PortName> - Add Port\n");
676 help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan> - Add Port, Vlan\n");
677 help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip> - Add Tunnel\n");
678 help.append("\t printCache <Node> - Prints Table Cache");
679 return help.toString();