1 package org.opendaylight.ovsdb.plugin;
3 import java.net.InetAddress;
4 import java.net.NetworkInterface;
5 import java.net.SocketException;
8 import org.eclipse.osgi.framework.console.CommandInterpreter;
9 import org.eclipse.osgi.framework.console.CommandProvider;
10 import org.opendaylight.ovsdb.lib.database.OVSBridge;
11 import org.opendaylight.ovsdb.lib.database.OVSInstance;
12 import org.opendaylight.ovsdb.lib.database.OvsdbType;
13 import org.opendaylight.ovsdb.lib.message.TransactBuilder;
14 import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
15 import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
16 import org.opendaylight.ovsdb.lib.message.operations.Operation;
17 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
18 import org.opendaylight.ovsdb.lib.notation.Condition;
19 import org.opendaylight.ovsdb.lib.notation.Function;
20 import org.opendaylight.ovsdb.lib.notation.Mutation;
21 import org.opendaylight.ovsdb.lib.notation.Mutator;
22 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
23 import org.opendaylight.ovsdb.lib.notation.UUID;
24 import org.opendaylight.ovsdb.lib.table.Bridge;
25 import org.opendaylight.ovsdb.lib.table.Interface;
26 import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
27 import org.opendaylight.ovsdb.lib.table.Port;
28 import org.opendaylight.ovsdb.lib.table.internal.Table;
29 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
30 import org.opendaylight.controller.sal.connection.ConnectionConstants;
31 import org.opendaylight.controller.sal.core.Node;
32 import org.opendaylight.controller.sal.core.NodeConnector;
33 import org.opendaylight.controller.sal.networkconfig.bridgedomain.ConfigConstants;
34 import org.opendaylight.controller.sal.networkconfig.bridgedomain.IPluginInBridgeDomainConfigService;
35 import org.opendaylight.controller.sal.utils.NetUtils;
36 import org.opendaylight.controller.sal.utils.Status;
37 import org.opendaylight.controller.sal.utils.StatusCode;
38 import org.osgi.framework.BundleContext;
39 import org.osgi.framework.FrameworkUtil;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.google.common.util.concurrent.ListenableFuture;
45 public class ConfigurationService implements IPluginInBridgeDomainConfigService, CommandProvider
47 private static final Logger logger = LoggerFactory
48 .getLogger(ConfigurationService.class);
50 IConnectionServiceInternal connectionService;
51 InventoryServiceInternal inventoryServiceInternal;
52 private IClusterGlobalServices clusterServices;
53 boolean forceConnect = false;
59 * Function called by the dependency manager when at least one dependency
60 * become unsatisfied or when the component is shutting down because for
61 * example bundle is being stopped.
68 * Function called by dependency manager after "init ()" is called and after
69 * the services provided by the class are registered in the service registry
73 registerWithOSGIConsole();
76 private void registerWithOSGIConsole() {
77 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
79 bundleContext.registerService(CommandProvider.class.getName(), this,
84 * Function called by the dependency manager before the services exported by
85 * the component are unregistered, this will be followed by a "destroy ()"
92 public void setConnectionServiceInternal(IConnectionServiceInternal connectionService) {
93 this.connectionService = connectionService;
96 public void unsetConnectionServiceInternal(IConnectionServiceInternal connectionService) {
97 if (this.connectionService == connectionService) {
98 this.connectionService = null;
102 public void setInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
103 this.inventoryServiceInternal = inventoryServiceInternal;
106 public void unsetInventoryServiceInternal(InventoryServiceInternal inventoryServiceInternal) {
107 if (this.inventoryServiceInternal == inventoryServiceInternal) {
108 this.inventoryServiceInternal = null;
112 public void setClusterServices(IClusterGlobalServices i) {
113 this.clusterServices = i;
116 public void unsetClusterServices(IClusterGlobalServices i) {
117 if (this.clusterServices == i) {
118 this.clusterServices = null;
122 private Connection getConnection (Node node) {
123 Connection connection = connectionService.getConnection(node);
124 if (connection == null || !connection.getChannel().isActive()) {
133 * @param node Node serving this configuration service
134 * @param bridgeConnectorIdentifier String representation of a Bridge Connector
135 * @return Bridge Connector configurations
138 public Status createBridgeDomain(Node node, String bridgeIdentifier,
139 Map<ConfigConstants, Object> configs) throws Throwable {
141 if (connectionService == null) {
142 logger.error("Couldn't refer to the ConnectionService");
143 return new Status(StatusCode.NOSERVICE);
146 Connection connection = this.getConnection(node);
147 if (connection == null) {
148 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
151 Map<String, Table<?>> ovsTable = inventoryServiceInternal.getTableCache(node, Open_vSwitch.NAME.getName());
152 String newBridge = "new_bridge";
153 String newInterface = "new_interface";
154 String newPort = "new_port";
155 String newSwitch = "new_switch";
157 Operation addSwitchRequest = null;
159 if(ovsTable != null){
160 String ovsTableUUID = (String) ovsTable.keySet().toArray()[0];
161 UUID bridgeUuidPair = new UUID(newBridge);
162 Mutation bm = new Mutation("bridges", Mutator.INSERT, bridgeUuidPair);
163 List<Mutation> mutations = new ArrayList<Mutation>();
166 UUID uuid = new UUID(ovsTableUUID);
167 Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
168 List<Condition> where = new ArrayList<Condition>();
169 where.add(condition);
170 addSwitchRequest = new MutateOperation(Open_vSwitch.NAME.getName(), where, mutations);
173 Open_vSwitch ovsTableRow = new Open_vSwitch();
174 OvsDBSet<UUID> bridges = new OvsDBSet<UUID>();
175 UUID bridgeUuidPair = new UUID(newBridge);
176 bridges.add(bridgeUuidPair);
177 ovsTableRow.setBridges(bridges);
178 addSwitchRequest = new InsertOperation(Open_vSwitch.NAME.getName(), newSwitch, ovsTableRow);
181 Bridge bridgeRow = new Bridge();
182 bridgeRow.setName(bridgeIdentifier);
183 OvsDBSet<UUID> ports = new OvsDBSet<UUID>();
184 UUID port = new UUID(newPort);
186 bridgeRow.setPorts(ports);
187 InsertOperation addBridgeRequest = new InsertOperation(Bridge.NAME.getName(), newBridge, bridgeRow);
189 Port portRow = new Port();
190 portRow.setName(bridgeIdentifier);
191 OvsDBSet<UUID> interfaces = new OvsDBSet<UUID>();
192 UUID interfaceid = new UUID(newInterface);
193 interfaces.add(interfaceid);
194 portRow.setInterfaces(interfaces);
195 InsertOperation addPortRequest = new InsertOperation(Port.NAME.getName(), newPort, portRow);
197 Interface interfaceRow = new Interface();
198 interfaceRow.setName(bridgeIdentifier);
199 interfaceRow.setType("internal");
200 InsertOperation addIntfRequest = new InsertOperation(Interface.NAME.getName(), newInterface, interfaceRow);
202 TransactBuilder transaction = new TransactBuilder();
203 transaction.addOperations(new ArrayList<Operation>(
204 Arrays.asList(addSwitchRequest, addIntfRequest, addPortRequest, addBridgeRequest)));
206 ListenableFuture<List<OperationResult>> transResponse = connection.getRpc().transact(transaction);
207 List<OperationResult> tr = transResponse.get();
208 List<Operation> requests = transaction.getRequests();
209 Status status = new Status(StatusCode.SUCCESS);
210 for (int i = 0; i < tr.size() ; i++) {
211 if (i < requests.size()) requests.get(i).setResult(tr.get(i));
212 if (tr.get(i).getError() != null && tr.get(i).getError().trim().length() > 0) {
213 OperationResult result = tr.get(i);
214 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
218 if (tr.size() > requests.size()) {
219 OperationResult result = tr.get(tr.size()-1);
220 logger.error("Error creating Bridge : {}\n Error : {}\n Details : {}", bridgeIdentifier,
222 result.getDetails());
223 status = new Status(StatusCode.BADREQUEST, result.getError() + " : " + result.getDetails());
226 } catch(Exception e){
229 return new Status(StatusCode.INTERNALERROR);
233 * Create a Port Attached to a Bridge
234 * Ex. ovs-vsctl add-port br0 vif0
235 * @param node Node serving this configuration service
236 * @param bridgeDomainIdentifier String representation of a Bridge Domain
237 * @param portIdentifier String representation of a user defined Port Name
240 public Status addPort(Node node, String bridgeIdentifier, String portIdentifier, Map<ConfigConstants, Object> configs) {
242 if (connectionService == null) {
243 logger.error("Couldn't refer to the ConnectionService");
244 return new Status(StatusCode.NOSERVICE);
246 Connection connection = this.getConnection(node);
247 if (connection == null) {
248 return new Status(StatusCode.NOSERVICE, "Connection to ovsdb-server not available");
251 if (connection != null) {
252 String newInterface = "new_interface";
253 String newPort = "new_port";
255 Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
257 OVSBridge bridge = existingBridges.get(bridgeIdentifier);
259 List<String> portUuidPair = new ArrayList<String>();
260 portUuidPair.add("named-uuid");
261 portUuidPair.add(newPort);
263 List<Object> mutation = new ArrayList<Object>();
264 mutation.add("ports");
265 mutation.add("insert");
266 mutation.add(portUuidPair);
267 List<Object> mutations = new ArrayList<Object>();
268 mutations.add(mutation);
270 List<String> bridgeUuidPair = new ArrayList<String>();
271 bridgeUuidPair.add("uuid");
272 bridgeUuidPair.add(bridge.getUuid());
274 List<Object> whereInner = new ArrayList<Object>();
275 whereInner.add("_uuid");
276 whereInner.add("==");
277 whereInner.add(bridgeUuidPair);
279 List<Object> where = new ArrayList<Object>();
280 where.add(whereInner);
282 MutateRequest mutateBridgeRequest = new MutateRequest("Bridge", where, mutations);
284 Map<String, Object> portRow = new HashMap<String, Object>();
285 portRow.put("name", portIdentifier);
286 String portType = null;
287 if (configs != null) {
288 portType = (String)configs.get(ConfigConstants.TYPE);
289 if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.VLAN.name())) {
291 portRow.put("tag", Integer.parseInt((String)configs.get(ConfigConstants.VLAN)));
292 } catch (Exception e) {
296 ArrayList<String> interfaces = new ArrayList<String>();
297 interfaces.add("named-uuid");
298 interfaces.add(newInterface);
299 portRow.put("interfaces", interfaces);
300 InsertRequest addPortRequest = new InsertRequest("insert", "Port", newPort, portRow);
302 Map<String, Object> interfaceRow = new HashMap<String, Object>();
303 interfaceRow.put("name", portIdentifier);
306 if (portType != null && portType.equalsIgnoreCase(OvsdbType.PortType.TUNNEL.name())) {
307 interfaceRow.put("type", configs.get(ConfigConstants.TUNNEL_TYPE));
308 ArrayList<Object> intopt = new ArrayList<Object>();
309 interfaceRow.put("options", intopt);
310 ArrayList<Object> intoptmap = new ArrayList<Object>();
311 ArrayList<String> intoptep = new ArrayList<String>();
313 intopt.add(intoptmap);
314 intoptmap.add(intoptep);
315 intoptep.add("remote_ip");
316 intoptep.add((String)configs.get(ConfigConstants.DEST_IP));
318 InsertRequest addIntfRequest = new InsertRequest("insert", "Interface", newInterface, interfaceRow);
320 Object[] params = {"Open_vSwitch", mutateBridgeRequest, addIntfRequest, addPortRequest};
321 OvsdbMessage msg = new OvsdbMessage("transact", params);
323 //connection.sendMessage(msg);
328 return new Status(StatusCode.SUCCESS);
331 * Implements the OVS Connection for Managers
333 * @param node Node serving this configuration service
334 * @param String with IP and connection types
336 @SuppressWarnings("unchecked")
337 public boolean setManager(Node node, String managerip) throws Throwable{
339 if (connectionService == null) {
340 logger.error("Couldn't refer to the ConnectionService");
343 Connection connection = this.getConnection(node);
344 if (connection == null) {
348 if (connection != null) {
349 String newmanager = "new_manager";
351 OVSInstance instance = OVSInstance.monitorOVS(connection);
353 Map ovsoutter = new LinkedHashMap();
354 Map ovsinner = new LinkedHashMap();
355 ArrayList ovsalist1 = new ArrayList();
356 ArrayList ovsalist2 = new ArrayList();
357 ArrayList ovsalist3 = new ArrayList();
358 ArrayList ovsalist4 = new ArrayList();
361 ovsoutter.put("where", ovsalist1);
362 ovsalist1.add(ovsalist2);
363 ovsalist2.add("_uuid");
365 ovsalist2.add(ovsalist3);
366 ovsalist3.add("uuid");
367 ovsalist3.add(instance.getUuid());
368 ovsoutter.put("op", "update");
369 ovsoutter.put("table", "Open_vSwitch");
370 ovsoutter.put("row", ovsinner);
371 ovsinner.put("manager_options", ovsalist4);
372 ovsalist4.add("named-uuid");
373 ovsalist4.add(newmanager);
375 Map mgroutside = new LinkedHashMap();
376 Map mgrinside = new LinkedHashMap();
378 //Manager Table Insert
379 mgroutside.put("uuid-name", newmanager);
380 mgroutside.put("op", "insert");
381 mgroutside.put("table","Manager");
382 mgroutside.put("row", mgrinside);
383 mgrinside.put("target", managerip);
385 Object[] params = {"Open_vSwitch", ovsoutter, mgroutside};
386 OvsdbMessage msg = new OvsdbMessage("transact", params);
388 //connection.sendMessage(msg);
398 public Status addBridgeDomainConfig(Node node, String bridgeIdentfier,
399 Map<ConfigConstants, Object> configs) {
400 String mgmt = (String)configs.get(ConfigConstants.MGMT);
403 if (setManager(node, mgmt)) return new Status(StatusCode.SUCCESS);
404 } catch (Throwable e) {
405 // TODO Auto-generated catch block
407 return new Status(StatusCode.INTERNALERROR);
410 return new Status(StatusCode.BADREQUEST);
414 public Status addPortConfig(Node node, String bridgeIdentifier, String portIdentifier,
415 Map<ConfigConstants, Object> configs) {
416 // TODO Auto-generated method stub
421 public Status deletePort(Node node, String bridgeIdentifier, String portIdentifier) {
422 // TODO Auto-generated method stub
427 public Node getBridgeDomainNode(Node node, String bridgeIdentifier) {
428 // TODO Auto-generated method stub
433 public Map<ConfigConstants, Object> getPortConfigs(Node node, String bridgeIdentifier,
434 String portIdentifier) {
435 // TODO Auto-generated method stub
440 public Status removeBridgeDomainConfig(Node node, String bridgeIdentifier,
441 Map<ConfigConstants, Object> configs) {
442 // TODO Auto-generated method stub
447 public Status removePortConfig(Node node, String bridgeIdentifier, String portIdentifier,
448 Map<ConfigConstants, Object> configs) {
449 // TODO Auto-generated method stub
454 public Status deleteBridgeDomain(Node node, String bridgeIdentifier) {
455 // TODO Auto-generated method stub
460 public Map<ConfigConstants, Object> getBridgeDomainConfigs(Node node, String bridgeIdentifier) {
461 // TODO Auto-generated method stub
466 public List<String> getBridgeDomains(Node node) {
468 Connection connection = connectionService.getConnection(node);
469 Map<String, OVSBridge> existingBridges = OVSBridge.monitorBridge(connection);
470 List<String> bridgeDomains = new ArrayList<String>(existingBridges.keySet());
471 return bridgeDomains;
475 public NodeConnector getNodeConnector(Node arg0, String arg1, String arg2) {
479 private short getControllerOFPort() {
480 Short defaultOpenFlowPort = 6633;
481 Short openFlowPort = defaultOpenFlowPort;
482 String portString = System.getProperty("of.listenPort");
483 if (portString != null) {
485 openFlowPort = Short.decode(portString).shortValue();
486 } catch (NumberFormatException e) {
487 logger.warn("Invalid port:{}, use default({})", portString,
494 private List<InetAddress> getControllerIPAddresses() {
495 List<InetAddress> controllers = null;
496 if (clusterServices != null) {
497 controllers = clusterServices.getClusteredControllers();
498 if (controllers != null && controllers.size() > 0) {
499 if (controllers.size() == 1) {
500 InetAddress controller = controllers.get(0);
501 if (!controller.equals(InetAddress.getLoopbackAddress())) {
510 controllers = new ArrayList<InetAddress>();
511 InetAddress controllerIP;
512 Enumeration<NetworkInterface> nets;
514 nets = NetworkInterface.getNetworkInterfaces();
515 for (NetworkInterface netint : Collections.list(nets)) {
516 Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
517 for (InetAddress inetAddress : Collections.list(inetAddresses)) {
518 if (!inetAddress.isLoopbackAddress() &&
519 NetUtils.isIPv4AddressValid(inetAddress.getHostAddress())) {
520 controllers.add(inetAddress);
524 } catch (SocketException e) {
525 controllers.add(InetAddress.getLoopbackAddress());
530 public void _ovsconnect (CommandInterpreter ci) {
531 String bridgeName = ci.nextArgument();
532 if (bridgeName == null) {
533 ci.println("Please enter Bridge Name");
537 String ovsdbserver = ci.nextArgument();
538 if (ovsdbserver == null) {
539 ci.println("Please enter valid IP-Address");
543 InetAddress.getByName(ovsdbserver);
544 } catch (Exception e) {
546 ci.println("Please enter valid IP-Address");
549 String port = ci.nextArgument();
554 ci.println("connecting to ovsdb server : "+ovsdbserver+":"+port+" ... ");
555 Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
556 params.put(ConnectionConstants.ADDRESS, ovsdbserver);
557 params.put(ConnectionConstants.PORT, port);
558 Node node = connectionService.connect(bridgeName, params);
559 if (node != null) ci.println("Node Name: "+node.toString());
560 else ci.println("Could not connect to Node");
563 public void _addBridge (CommandInterpreter ci) {
564 String nodeName = ci.nextArgument();
565 if (nodeName == null) {
566 ci.println("Please enter Node Name");
570 String bridgeName = ci.nextArgument();
571 if (bridgeName == null) {
572 ci.println("Please enter Bridge Name");
577 status = this.createBridgeDomain(Node.fromString(nodeName), bridgeName, null);
578 ci.println("Bridge creation status : "+status.toString());
579 } catch (Throwable e) {
580 // TODO Auto-generated catch block
582 ci.println("Failed to create Bridge "+bridgeName);
586 public void _addPort (CommandInterpreter ci) {
587 String nodeName = ci.nextArgument();
588 if (nodeName == null) {
589 ci.println("Please enter Node Name");
593 String bridgeName = ci.nextArgument();
594 if (bridgeName == null) {
595 ci.println("Please enter Bridge Name");
599 String portName = ci.nextArgument();
600 if (portName == null) {
601 ci.println("Please enter Port Name");
607 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, null);
608 ci.println("Port creation status : "+status.toString());
609 } catch (Throwable e) {
610 // TODO Auto-generated catch block
612 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
616 public void _addPortVlan (CommandInterpreter ci) {
617 String nodeName = ci.nextArgument();
618 if (nodeName == null) {
619 ci.println("Please enter Node Name");
623 String bridgeName = ci.nextArgument();
624 if (bridgeName == null) {
625 ci.println("Please enter Bridge Name");
629 String portName = ci.nextArgument();
630 if (portName == null) {
631 ci.println("Please enter Port Name");
635 String vlan = ci.nextArgument();
637 ci.println("Please enter Valid Vlan");
641 Integer.parseInt(vlan);
642 } catch (Exception e) {
643 ci.println("Please enter Valid Vlan");
648 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
649 configs.put(ConfigConstants.TYPE, "VLAN");
650 configs.put(ConfigConstants.VLAN, vlan);
654 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
655 ci.println("Port creation status : "+status.toString());
656 } catch (Throwable e) {
657 // TODO Auto-generated catch block
659 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
663 public void _addTunnel (CommandInterpreter ci) {
664 String nodeName = ci.nextArgument();
665 if (nodeName == null) {
666 ci.println("Please enter Node Name");
670 String bridgeName = ci.nextArgument();
671 if (bridgeName == null) {
672 ci.println("Please enter Bridge Name");
676 String portName = ci.nextArgument();
677 if (portName == null) {
678 ci.println("Please enter Port Name");
682 String tunnelType = ci.nextArgument();
683 if (tunnelType == null) {
684 ci.println("Please enter Tunnel Type");
688 String remoteIp = ci.nextArgument();
689 if (remoteIp == null) {
690 ci.println("Please enter valid Remote IP Address");
695 InetAddress.getByName(remoteIp);
696 } catch (Exception e) {
698 ci.println("Please enter valid Remote IP Address");
702 Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
703 configs.put(ConfigConstants.TYPE, "TUNNEL");
704 configs.put(ConfigConstants.TUNNEL_TYPE, tunnelType);
705 configs.put(ConfigConstants.DEST_IP, remoteIp);
709 status = this.addPort(Node.fromString(nodeName), bridgeName, portName, configs);
710 ci.println("Port creation status : "+status.toString());
711 } catch (Throwable e) {
712 // TODO Auto-generated catch block
714 ci.println("Failed to create Port "+portName+" in Bridge "+bridgeName);
718 public void _printCache (CommandInterpreter ci) {
719 String nodeName = ci.nextArgument();
720 if (nodeName == null) {
721 ci.println("Please enter Node Name");
724 inventoryServiceInternal.printCache(Node.fromString(nodeName));
727 public void _forceConnect (CommandInterpreter ci) {
728 String force = ci.nextArgument();
729 if (force.equalsIgnoreCase("YES")) forceConnect = true;
730 else if (force.equalsIgnoreCase("NO")) forceConnect = false;
731 else ci.println("Please enter YES or NO.");
732 ci.println("Current ForceConnect State : "+forceConnect);
737 public String getHelp() {
738 StringBuffer help = new StringBuffer();
739 help.append("---OVSDB CLI---\n");
740 help.append("\t ovsconnect <ConnectionName> <ip-address> - Connect to OVSDB\n");
741 help.append("\t addBridge <Node> <BridgeName> - Add Bridge\n");
742 help.append("\t addPort <Node> <BridgeName> <PortName> - Add Port\n");
743 help.append("\t addPortVlan <Node> <BridgeName> <PortName> <vlan> - Add Port, Vlan\n");
744 help.append("\t addTunnel <Node> <Bridge> <Port> <tunnel-type> <remote-ip> - Add Tunnel\n");
745 help.append("\t printCache <Node> - Prints Table Cache");
746 return help.toString();