CNlucius
Committed by Gerrit Code Review

ONOS-2708

Add implementation of getting ovsdb ports or bridges in the ovsdb node.

Change-Id: If31af08ccb90a29bc800a79f332dae2bc497b105
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.behaviour;
import java.util.Collection;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.HandlerBehaviour;
/**
* Behaviour for handling various drivers for bridge configurations.
*/
public interface BridgeConfig extends HandlerBehaviour {
/**
* Add a bridge.
*
* @param bridgeName bridge name
*/
void addBridge(BridgeName bridgeName);
/**
* Remove a bridge.
*
* @param bridgeName bridge name
*/
void deleteBridge(BridgeName bridgeName);
/**
* Remove a bridge.
*
* @return bridge collection
*/
Collection<BridgeDescription> getBridges();
/**
* Add a logical/virtual port.
*
* @param port port number
*/
void addPort(PortDescription port);
/**
* Delete a logical/virtual port.
*
* @param port port number
*/
void deletePort(PortDescription port);
/**
* Delete a logical/virtual port.
*
* @return collection of port
*/
Collection<PortDescription> getPorts();
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.behaviour;
import java.util.Collection;
import java.util.Set;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.HandlerBehaviour;
/**
* Behaviour for handling various drivers for bridge configurations.
*/
public interface BridgeConfig extends HandlerBehaviour {
/**
* Add a bridge.
*
* @param bridgeName bridge name
*/
void addBridge(BridgeName bridgeName);
/**
* Remove a bridge.
*
* @param bridgeName bridge name
*/
void deleteBridge(BridgeName bridgeName);
/**
* Remove a bridge.
*
* @return bridge collection
*/
Collection<BridgeDescription> getBridges();
/**
* Add a logical/virtual port.
*
* @param port port number
*/
void addPort(PortDescription port);
/**
* Delete a logical/virtual port.
*
* @param port port number
*/
void deletePort(PortDescription port);
/**
* Delete a logical/virtual port.
*
* @return collection of port
*/
Collection<PortDescription> getPorts();
/**
* Get a collection of port.
*
* @return portNumbers set of PortNumber
*/
Set<PortNumber> getPortNumbers();
}
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.ovsdb;
import java.util.Collection;
import java.util.Set;
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.DefaultBridgeDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import com.google.common.collect.Sets;
/**
* The implementation of BridageConfig.
*/
public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
implements BridgeConfig {
@Override
public void addBridge(BridgeName bridgeName) {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
ovsdbNode.createBridge(bridgeName.name());
}
@Override
public void deleteBridge(BridgeName bridgeName) {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
ovsdbNode.dropBridge(bridgeName.name());
}
@Override
public Collection<BridgeDescription> getBridges() {
DriverHandler handler = handler();
DeviceId deviceId = handler.data().deviceId();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
Set<OvsdbBridge> ovsdbSet = ovsdbNode.getBridges();
Collection<BridgeDescription> bridges = Sets.newHashSet();
ovsdbSet.forEach(o -> {
BridgeName bridgeName = BridgeName.bridgeName(o.bridgeName()
.toString());
DeviceId ownDeviceId = DeviceId.deviceId(o.datapathId().toString());
BridgeDescription description = new DefaultBridgeDescription(
bridgeName,
deviceId,
ownDeviceId);
bridges.add(description);
});
return bridges;
}
@Override
public void addPort(PortDescription port) {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
Set<OvsdbBridge> ovsdbSet = ovsdbNode.getBridges();
if (ovsdbSet != null && ovsdbSet.size() > 0) {
OvsdbBridge bridge = ovsdbSet.iterator().next();
ovsdbNode.createPort(bridge.bridgeName().toString(), port
.portNumber().toString());
}
}
@Override
public void deletePort(PortDescription port) {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
Set<OvsdbBridge> ovsdbSet = ovsdbNode.getBridges();
if (ovsdbSet != null && ovsdbSet.size() > 0) {
OvsdbBridge bridge = ovsdbSet.iterator().next();
ovsdbNode.dropPort(bridge.bridgeName().toString(), port
.portNumber().toString());
}
}
@Override
public Collection<PortDescription> getPorts() {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
Set<OvsdbPort> ovsdbSet = ovsdbNode.getPorts();
Collection<PortDescription> ports = Sets.newHashSet();
ovsdbSet.forEach(o -> {
PortNumber port = PortNumber.portNumber(o.portNumber().value());
PortDescription description = new DefaultPortDescription(port, true);
ports.add(description);
});
return ports;
}
// OvsdbNodeId(IP:port) is used in the adaptor while DeviceId(ovsdb:IP:port)
// is used in the core. So DeviceId need be changed to OvsdbNodeId.
private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
int lastColon = deviceId.toString().lastIndexOf(":");
int fistColon = deviceId.toString().indexOf(":");
String ip = deviceId.toString().substring(fistColon + 1, lastColon);
String port = deviceId.toString().substring(lastColon + 1);
IpAddress ipAddress = IpAddress.valueOf(ip);
long portL = Long.valueOf(port).longValue();
return new OvsdbNodeId(ipAddress, portL);
}
private OvsdbClientService getOvsdbNode(DriverHandler handler) {
OvsdbController ovsController = handler.get(OvsdbController.class);
DeviceId deviceId = handler.data().deviceId();
OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId);
return ovsController.getOvsdbClient(nodeId);
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.driver.ovsdb;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.DefaultBridgeDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import com.google.common.collect.Sets;
/**
* The implementation of BridageConfig.
*/
public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
implements BridgeConfig {
@Override
public void addBridge(BridgeName bridgeName) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
clientService.createBridge(bridgeName.name());
}
@Override
public void deleteBridge(BridgeName bridgeName) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
clientService.dropBridge(bridgeName.name());
}
@Override
public Collection<BridgeDescription> getBridges() {
DriverHandler handler = handler();
DeviceId deviceId = handler.data().deviceId();
OvsdbClientService clientService = getOvsdbClientService(handler);
Set<OvsdbBridge> ovsdbSet = clientService.getBridges();
Collection<BridgeDescription> bridges = Sets.newHashSet();
ovsdbSet.forEach(o -> {
BridgeName bridgeName = BridgeName
.bridgeName(o.bridgeName().value());
DeviceId ownDeviceId = DeviceId.deviceId("of:" + o.datapathId().value());
BridgeDescription description = new DefaultBridgeDescription(bridgeName,
deviceId,
ownDeviceId);
bridges.add(description);
});
return bridges == null ? Collections.emptySet() : bridges;
}
@Override
public void addPort(PortDescription port) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
Set<OvsdbBridge> ovsdbSet = clientService.getBridges();
if (ovsdbSet != null && ovsdbSet.size() > 0) {
OvsdbBridge bridge = ovsdbSet.iterator().next();
clientService.createPort(bridge.bridgeName().toString(), port
.portNumber().toString());
}
}
@Override
public void deletePort(PortDescription port) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
Set<OvsdbBridge> ovsdbSet = clientService.getBridges();
if (ovsdbSet != null && ovsdbSet.size() > 0) {
OvsdbBridge bridge = ovsdbSet.iterator().next();
clientService.dropPort(bridge.bridgeName().toString(), port
.portNumber().toString());
}
}
@Override
public Collection<PortDescription> getPorts() {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
Set<OvsdbPort> ovsdbSet = clientService.getPorts();
Collection<PortDescription> ports = Sets.newHashSet();
ovsdbSet.forEach(o -> {
PortNumber port = PortNumber.portNumber(o.portNumber().value());
PortDescription description = new DefaultPortDescription(port, true);
ports.add(description);
});
return ports;
}
// OvsdbNodeId(IP:port) is used in the adaptor while DeviceId(ovsdb:IP:port)
// is used in the core. So DeviceId need be changed to OvsdbNodeId.
private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
int lastColon = deviceId.toString().lastIndexOf(":");
int fistColon = deviceId.toString().indexOf(":");
String ip = deviceId.toString().substring(fistColon + 1, lastColon);
String port = deviceId.toString().substring(lastColon + 1);
IpAddress ipAddress = IpAddress.valueOf(ip);
long portL = Long.valueOf(port).longValue();
return new OvsdbNodeId(ipAddress, portL);
}
// Used for getting OvsdbClientService.
private OvsdbClientService getOvsdbClientService(DriverHandler handler) {
OvsdbController ovsController = handler.get(OvsdbController.class);
DeviceId deviceId = handler.data().deviceId();
OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId);
return ovsController.getOvsdbClient(nodeId);
}
@Override
public Set<PortNumber> getPortNumbers() {
Set<PortNumber> ports = new HashSet<>();
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
Set<OvsdbPort> ovsdbSet = clientService.getPorts();
ovsdbSet.forEach(o -> {
PortNumber port = PortNumber.portNumber(o.portNumber().value(),
o.portName().value());
ports.add(port);
});
return ports;
}
}
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<drivers>
<driver name="default"
manufacturer="ON.Lab" hwVersion="0.0.1" swVersion="0.0.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.DefaultSwitchHandshaker"/>
</driver>
<driver name="ovs" extends="default"
manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/>
<behaviour api="org.onosproject.net.behaviour.TunnelConfig"
impl="org.onosproject.driver.ovsdb.OvsdbTunnelConfig"/>
<behaviour api="org.onosproject.net.behaviour.BridgeConfig"
impl="org.onosproject.driver.ovsdb.OvsdbBridgeConfig"/>
</driver>
<driver name="ovs-corsa" extends="ovs"
manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
</driver>
<driver name="spring-open-cpqd" extends="default"
manufacturer="Stanford University, Ericsson Research and CPqD Research"
hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTP"/>
</driver>
<driver name="spring-open" extends="default"
manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0"
swVersion="OpenFlow switch SW ver. 1.0 and 1.3">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/>
</driver>
<driver name="linc-oe" extends="default"
manufacturer="FlowForwarding.org" hwVersion="Unknown"
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/>
</driver>
<driver name="corsa"
manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CorsaPipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CorsaSwitchHandshaker"/>
</driver>
<driver name="ofdpa" extends="default"
manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/>
</driver>
<driver name="pmc-olt" extends="default"
manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OLTPipeline"/>
</driver>
<driver name="g.fast" extends="default"
manufacturer="TEST1" hwVersion="TEST2" swVersion="TEST3">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OLTPipeline"/>
</driver>
<!-- The SoftRouter driver is meant to be used by any software/NPU based
~ switch that wishes to implement a simple 2-table router. To use this
~ driver, configure ONOS with the dpid of the device, or extend the
~ driver declaration with the manufacturer/hwVersion/swVersion of the
~ device (see 'noviflow' example).
-->
<driver name="softrouter" extends="default"
manufacturer="Various" hwVersion="various" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SoftRouterPipeline"/>
</driver>
<driver name="centec-V350" extends="default"
manufacturer=".*Centec.*" hwVersion=".*" swVersion="3.1.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CentecV350Pipeline"/>
</driver>
<driver name="pica" extends="default"
manufacturer="Pica8, Inc." hwVersion=".*" swVersion="PicOS 2.6">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.PicaPipeline"/>
</driver>
<driver name="noviflow" extends="softrouter"
manufacturer="NoviFlow Inc" hwVersion="NS.*" swVersion="NW.*">
</driver>
<!-- Emulation of the ofdpa pipeline using a CPqD OF 1.3 software switch.
~ To use this driver, configure ONOS with the dpid of the device.
-->
<driver name="ofdpa-cpqd" extends="default"
manufacturer="ONF"
hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CpqdOFDPA1Pipeline"/>
</driver>
<driver name="calient" extends="default"
manufacturer="calient inc" hwVersion="calient hardware"
swVersion="ocs switch">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
</driver>
</drivers>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<drivers>
<driver name="default"
manufacturer="ON.Lab" hwVersion="0.0.1" swVersion="0.0.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OpenVSwitchPipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.DefaultSwitchHandshaker"/>
<behaviour api="org.onosproject.net.behaviour.TunnelConfig"
impl="org.onosproject.driver.ovsdb.OvsdbTunnelConfig"/>
<behaviour api="org.onosproject.net.behaviour.BridgeConfig"
impl="org.onosproject.driver.ovsdb.OvsdbBridgeConfig"/>
</driver>
<driver name="ovs" extends="default"
manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/>
</driver>
<driver name="ovs-corsa" extends="ovs"
manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
</driver>
<driver name="spring-open-cpqd" extends="default"
manufacturer="Stanford University, Ericsson Research and CPqD Research"
hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTP"/>
</driver>
<driver name="spring-open" extends="default"
manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0"
swVersion="OpenFlow switch SW ver. 1.0 and 1.3">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/>
</driver>
<driver name="linc-oe" extends="default"
manufacturer="FlowForwarding.org" hwVersion="Unknown"
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/>
</driver>
<driver name="corsa"
manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CorsaPipeline"/>
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CorsaSwitchHandshaker"/>
</driver>
<driver name="ofdpa" extends="default"
manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/>
</driver>
<driver name="pmc-olt" extends="default"
manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OLTPipeline"/>
</driver>
<driver name="g.fast" extends="default"
manufacturer="TEST1" hwVersion="TEST2" swVersion="TEST3">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OLTPipeline"/>
</driver>
<!-- The SoftRouter driver is meant to be used by any software/NPU based
~ switch that wishes to implement a simple 2-table router. To use this
~ driver, configure ONOS with the dpid of the device, or extend the
~ driver declaration with the manufacturer/hwVersion/swVersion of the
~ device (see 'noviflow' example).
-->
<driver name="softrouter" extends="default"
manufacturer="Various" hwVersion="various" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SoftRouterPipeline"/>
</driver>
<driver name="centec-V350" extends="default"
manufacturer=".*Centec.*" hwVersion=".*" swVersion="3.1.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CentecV350Pipeline"/>
</driver>
<driver name="pica" extends="default"
manufacturer="Pica8, Inc." hwVersion=".*" swVersion="PicOS 2.6">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.PicaPipeline"/>
</driver>
<driver name="noviflow" extends="softrouter"
manufacturer="NoviFlow Inc" hwVersion="NS.*" swVersion="NW.*">
</driver>
<!-- Emulation of the ofdpa pipeline using a CPqD OF 1.3 software switch.
~ To use this driver, configure ONOS with the dpid of the device.
-->
<driver name="ofdpa-cpqd" extends="default"
manufacturer="ONF"
hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.CpqdOFDPA1Pipeline"/>
</driver>
<driver name="calient" extends="default"
manufacturer="calient inc" hwVersion="calient hardware"
swVersion="ocs switch">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
</driver>
</drivers>
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ovsdb.controller.driver;
import io.netty.channel.Channel;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import org.onlab.packet.IpAddress;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbConstant;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import org.onosproject.ovsdb.controller.OvsdbRowStore;
import org.onosproject.ovsdb.controller.OvsdbStore;
import org.onosproject.ovsdb.controller.OvsdbTableStore;
import org.onosproject.ovsdb.controller.OvsdbTunnel;
import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
import org.onosproject.ovsdb.rfc.message.OperationResult;
import org.onosproject.ovsdb.rfc.message.TableUpdates;
import org.onosproject.ovsdb.rfc.notation.Condition;
import org.onosproject.ovsdb.rfc.notation.Mutation;
import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
import org.onosproject.ovsdb.rfc.notation.Row;
import org.onosproject.ovsdb.rfc.notation.UUID;
import org.onosproject.ovsdb.rfc.operations.Delete;
import org.onosproject.ovsdb.rfc.operations.Insert;
import org.onosproject.ovsdb.rfc.operations.Mutate;
import org.onosproject.ovsdb.rfc.operations.Operation;
import org.onosproject.ovsdb.rfc.operations.Update;
import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
import org.onosproject.ovsdb.rfc.schema.TableSchema;
import org.onosproject.ovsdb.rfc.table.Bridge;
import org.onosproject.ovsdb.rfc.table.Controller;
import org.onosproject.ovsdb.rfc.table.Interface;
import org.onosproject.ovsdb.rfc.table.OvsdbTable;
import org.onosproject.ovsdb.rfc.table.Port;
import org.onosproject.ovsdb.rfc.table.TableGenerator;
import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
import org.onosproject.ovsdb.rfc.utils.MutationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
/**
* An representation of an ovsdb client.
*/
public class DefaultOvsdbClient
implements OvsdbProviderService, OvsdbClientService {
private final Logger log = LoggerFactory
.getLogger(DefaultOvsdbClient.class);
private Channel channel;
private OvsdbAgent agent;
private boolean connected;
private OvsdbNodeId nodeId;
private Callback monitorCallBack;
private OvsdbStore ovsdbStore = new OvsdbStore();
private final Map<String, String> requestMethod = Maps.newHashMap();
private final Map<String, SettableFuture<? extends Object>> requestResult = Maps
.newHashMap();
private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
private final Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
private final Set<OvsdbBridge> ovsdbBridges = new HashSet<OvsdbBridge>();
/**
* Creates an OvsdbClient.
*
* @param nodeId ovsdb node id
*/
public DefaultOvsdbClient(OvsdbNodeId nodeId) {
this.nodeId = nodeId;
}
@Override
public OvsdbNodeId nodeId() {
return nodeId;
}
@Override
public void setAgent(OvsdbAgent agent) {
if (this.agent == null) {
this.agent = agent;
}
}
@Override
public void setChannel(Channel channel) {
this.channel = channel;
}
@Override
public void setConnection(boolean connected) {
this.connected = connected;
}
@Override
public boolean isConnected() {
return this.connected;
}
@Override
public void nodeAdded() {
this.agent.addConnectedNode(nodeId, this);
}
@Override
public void nodeRemoved() {
this.agent.removeConnectedNode(nodeId);
channel.disconnect();
}
/**
* Gets the ovsdb table store.
*
* @param dbName the ovsdb database name
* @return ovsTableStore, empty if table store is find
*/
private OvsdbTableStore getTableStore(String dbName) {
if (ovsdbStore == null) {
return null;
}
return ovsdbStore.getOvsdbTableStore(dbName);
}
/**
* Gets the ovsdb row store.
*
* @param dbName the ovsdb database name
* @param tableName the ovsdb table name
*
* @return ovsRowStore, empty if row store is find
*/
private OvsdbRowStore getRowStore(String dbName, String tableName) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return null;
}
return tableStore.getRows(tableName);
}
/**
* Gets the ovsdb row.
*
* @param dbName the ovsdb database name
* @param tableName the ovsdb table name
* @param uuid the key of the row
* @return row, empty if row is find
*/
@Override
public Row getRow(String dbName, String tableName, String uuid) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return null;
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
return null;
}
return rowStore.getRow(uuid);
}
@Override
public void removeRow(String dbName, String tableName, String uuid) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return;
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
return;
}
rowStore.deleteRow(uuid);
}
@Override
public void updateOvsdbStore(String dbName, String tableName, String uuid,
Row row) {
OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
if (tableStore == null) {
tableStore = new OvsdbTableStore();
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
rowStore = new OvsdbRowStore();
}
rowStore.insertRow(uuid, row);
tableStore.createOrUpdateTable(tableName, rowStore);
ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
}
@Override
public String getPortUuid(String portName, String bridgeUuid) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Row bridgeRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.BRIDGE, bridgeUuid);
Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
OvsdbTable.BRIDGE);
if (bridge != null) {
OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
@SuppressWarnings("unchecked")
Set<UUID> ports = setPorts.set();
if (ports == null || ports.size() == 0) {
log.warn("The port uuid is null");
return null;
}
for (UUID uuid : ports) {
Row portRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.PORT, uuid.value());
if (portRow == null) {
continue;
}
Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
OvsdbTable.PORT);
if (port != null && portName.equalsIgnoreCase(port.getName())) {
return uuid.value();
}
}
}
return null;
}
@Override
public String getInterfaceUuid(String portUuid, String portName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Row portRow = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.PORT,
portUuid);
Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
OvsdbTable.PORT);
if (port != null) {
OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
@SuppressWarnings("unchecked")
Set<UUID> interfaces = setInterfaces.set();
if (interfaces == null || interfaces.size() == 0) {
log.warn("The interface uuid is null");
return null;
}
for (UUID uuid : interfaces) {
Row intfRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.INTERFACE, uuid.value());
if (intfRow == null) {
continue;
}
Interface intf = (Interface) TableGenerator
.getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
return uuid.value();
}
}
}
return null;
}
@Override
public String getBridgeUuid(String bridgeName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.BRIDGE);
if (rowStore == null) {
log.debug("The bridge uuid is null");
return null;
}
ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
if (bridgeTableRows == null) {
log.debug("The bridge uuid is null");
return null;
}
for (String uuid : bridgeTableRows.keySet()) {
Bridge bridge = (Bridge) TableGenerator
.getTable(dbSchema, bridgeTableRows.get(uuid),
OvsdbTable.BRIDGE);
if (bridge.getName().equals(bridgeName)) {
return uuid;
}
}
return null;
}
@Override
public String getControllerUuid(String controllerName,
String controllerTarget) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.CONTROLLER);
if (rowStore == null) {
log.debug("The controller uuid is null");
return null;
}
ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
if (controllerTableRows != null) {
for (String uuid : controllerTableRows.keySet()) {
Controller controller = (Controller) TableGenerator
.getTable(dbSchema, controllerTableRows.get(uuid),
OvsdbTable.CONTROLLER);
String target = (String) controller.getTargetColumn().data();
if (target.equalsIgnoreCase(controllerTarget)) {
return uuid;
}
}
}
return null;
}
@Override
public String getOvsUuid(String dbName) {
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.DATABASENAME);
if (rowStore == null) {
log.debug("The bridge uuid is null");
return null;
}
ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
if (ovsTableRows != null) {
for (String uuid : ovsTableRows.keySet()) {
Row row = ovsTableRows.get(uuid);
String tableName = row.tableName();
if (tableName.equals(dbName)) {
return uuid;
}
}
}
return null;
}
@Override
public void createPort(String bridgeName, String portName) {
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.error("Can't find bridge {} in {}", bridgeName,
nodeId.getIpAddress());
return;
}
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
String portUuid = getPortUuid(portName, bridgeUuid);
Port port = (Port) TableGenerator
.createTable(dbSchema, OvsdbTable.PORT);
port.setName(portName);
if (portUuid == null) {
insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
"ports", bridgeUuid, port.getRow());
} else {
updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
}
return;
}
@Override
public void dropPort(String bridgeName, String portName) {
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
return;
}
String portUuid = getPortUuid(portName, bridgeUuid);
if (portUuid != null) {
log.info("Port {} delete", portName);
deleteConfig(OvsdbConstant.PORT, "_uuid", portUuid,
OvsdbConstant.BRIDGE, "ports");
}
}
@Override
public void createBridge(String bridgeName) {
log.debug("create bridge {}", bridgeName);
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
if (dbSchema == null) {
log.warn("The schema is null");
return;
}
Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
OvsdbTable.BRIDGE);
if (bridge == null) {
log.debug("Can not create bridge");
return;
}
Set<String> failModes = new HashSet<>();
failModes.add("secure");
bridge.setFailMode(failModes);
Set<String> protocols = new HashSet<>();
protocols.add(OvsdbConstant.OPENFLOW13);
bridge.setProtocols(protocols);
String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
if (ovsUuid == null) {
log.warn("The Open_vSwitch is null");
return;
}
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.debug("Create a new bridge");
bridge.setName(bridgeName);
bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
OvsdbConstant.DATABASENAME, "bridges",
ovsUuid, bridge.getRow());
if (bridgeUuid != null) {
Port port = (Port) TableGenerator.createTable(dbSchema,
OvsdbTable.PORT);
if (port != null) {
log.debug("the port is not null");
port.setName(bridgeName);
insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
port.getRow());
}
}
} else {
log.info("Update a bridge");
updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
}
setController(bridgeUuid);
log.info("Create bridge success");
}
/**
* Sets the Controller.
*
* @param bridgeUuid bridge uuid
*/
private void setController(String bridgeUuid) {
String controllerUuid = null;
String iPAddress = IpAddress.valueOf(((InetSocketAddress) channel
.localAddress())
.getAddress()
.getHostAddress())
.toString();
String target = "tcp:" + iPAddress + ":" + OvsdbConstant.OFPORT;
log.debug("controller IP {}: port {}", iPAddress, OvsdbConstant.OFPORT);
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Controller controller = (Controller) TableGenerator
.createTable(dbSchema, OvsdbTable.CONTROLLER);
if (controller != null) {
controller.setTarget(target);
controllerUuid = getControllerUuid(OvsdbConstant.CONTROLLER, target);
if (controllerUuid == null) {
insertConfig(OvsdbConstant.CONTROLLER, "_uuid",
OvsdbConstant.BRIDGE, "controller", bridgeUuid,
controller.getRow());
} else {
Bridge bridge = (Bridge) TableGenerator
.createTable(dbSchema, OvsdbTable.BRIDGE);
Set<UUID> controllerUuids = new HashSet<>();
controllerUuids.add(UUID.uuid(controllerUuid));
bridge.setController(controllerUuids);
updateConfig(OvsdbConstant.CONTROLLER, "_uuid", bridgeUuid, bridge.getRow());
}
}
}
@Override
public void dropBridge(String bridgeName) {
String bridgeUUID = getBridgeUuid(bridgeName);
if (bridgeUUID == null) {
log.warn("Could not find bridge in node", nodeId.getIpAddress());
return;
}
deleteConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUUID,
OvsdbConstant.DATABASENAME, "bridges");
}
@Override
public void createTunnel(IpAddress srcIp, IpAddress dstIp) {
String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
if (bridgeUuid == null) {
log.warn("Could not find bridge {} and Could not create tunnel. ",
OvsdbConstant.INTEGRATION_BRIDGE);
return;
}
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
String portUuid = getPortUuid(portName, bridgeUuid);
Port port = (Port) TableGenerator
.createTable(dbSchema, OvsdbTable.PORT);
if (port != null) {
port.setName(portName);
}
if (portUuid == null) {
portUuid = insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
"ports", bridgeUuid, port.getRow());
} else {
updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
}
// When a tunnel is created, A row is inserted into port table and
// interface table of the ovsdb node.
// and the following step is to get the interface uuid from local store
// in controller node.
// but it need spend some time synchronising data between node and
// controller.
// so loop to judge if interfaceUUid is null is necessary.
String interfaceUuid = null;
for (int i = 0; i < 10; i++) {
interfaceUuid = getInterfaceUuid(portUuid, portName);
if (interfaceUuid == null) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.warn("Interrupted while waiting to get interfaceUuid");
Thread.currentThread().interrupt();
}
} else {
break;
}
}
if (interfaceUuid != null) {
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.INTERFACE);
if (rowStore == null) {
log.debug("The bridge uuid is null");
return;
}
ConcurrentMap<String, Row> intfTableRows = rowStore.getRowStore();
if (intfTableRows == null) {
log.debug("The bridge uuid is null");
return;
}
Interface tunInterface = (Interface) TableGenerator
.getTable(dbSchema, intfTableRows.get(interfaceUuid),
OvsdbTable.INTERFACE);
if (tunInterface != null) {
tunInterface.setType(OvsdbConstant.TYPEVXLAN);
Map<String, String> options = Maps.newHashMap();
options.put("key", "flow");
options.put("local_ip", srcIp.toString());
options.put("remote_ip", dstIp.toString());
tunInterface.setOptions(options);
updateConfig(OvsdbConstant.INTERFACE, "_uuid", interfaceUuid,
tunInterface.getRow());
log.info("Tunnel added success", tunInterface);
}
}
return;
}
@Override
public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE;
String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
if (bridgeUuid == null) {
log.warn("Could not find bridge {} in {}", bridgeName,
nodeId.getIpAddress());
return;
}
String portUUID = getPortUuid(portName, bridgeUuid);
if (portUUID != null) {
log.info("Delete tunnel");
deleteConfig(OvsdbConstant.PORT, "_uuid", portUUID,
OvsdbConstant.BRIDGE, "ports");
}
return;
}
/**
* Delete transact config.
*
* @param childTableName child table name
* @param childColumnName child column name
* @param childUuid child row uuid
* @param parentTableName parent table name
* @param parentColumnName parent column
*
*/
private void deleteConfig(String childTableName, String childColumnName,
String childUuid, String parentTableName,
String parentColumnName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
ArrayList<Operation> operations = Lists.newArrayList();
if (parentTableName != null && parentColumnName != null) {
TableSchema parentTableSchema = dbSchema
.getTableSchema(parentTableName);
ColumnSchema parentColumnSchema = parentTableSchema
.getColumnSchema(parentColumnName);
List<Mutation> mutations = Lists.newArrayList();
Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
UUID.uuid(childUuid));
mutations.add(mutation);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.includes(parentColumnName,
UUID.uuid(childUuid));
conditions.add(condition);
Mutate op = new Mutate(parentTableSchema, conditions, mutations);
operations.add(op);
}
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals(childColumnName, UUID.uuid(childUuid));
conditions.add(condition);
Delete del = new Delete(childTableSchema, conditions);
operations.add(del);
transactConfig(OvsdbConstant.DATABASENAME, operations);
return;
}
/**
* Update transact config.
*
* @param tableName table name
* @param columnName column name
* @param uuid uuid
* @param row the config data
*
*/
private void updateConfig(String tableName, String columnName, String uuid,
Row row) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema tableSchema = dbSchema.getTableSchema(tableName);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals(columnName, UUID.uuid(uuid));
conditions.add(condition);
Update update = new Update(tableSchema, row, conditions);
ArrayList<Operation> operations = Lists.newArrayList();
operations.add(update);
transactConfig(OvsdbConstant.DATABASENAME, operations);
}
/**
* Insert transact config.
*
* @param childTableName child table name
* @param childColumnName child column name
* @param parentTableName parent table name
* @param parentColumnName parent column
* @param parentUuid parent uuid
* @param row the config data
*
* @return uuid, empty if no uuid is find
*/
private String insertConfig(String childTableName, String childColumnName,
String parentTableName, String parentColumnName,
String parentUuid, Row row) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
String namedUuid = childTableName;
Insert insert = new Insert(tableSchema, namedUuid, row);
ArrayList<Operation> operations = Lists.newArrayList();
operations.add(insert);
if (parentTableName != null && parentColumnName != null) {
TableSchema parentTableSchema = dbSchema
.getTableSchema(parentTableName);
ColumnSchema parentColumnSchema = parentTableSchema
.getColumnSchema(parentColumnName);
List<Mutation> mutations = Lists.newArrayList();
Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
UUID.uuid(namedUuid));
mutations.add(mutation);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals("_uuid",
UUID.uuid(parentUuid));
conditions.add(condition);
Mutate op = new Mutate(parentTableSchema, conditions, mutations);
operations.add(op);
}
if (childTableName.equalsIgnoreCase(OvsdbConstant.PORT)) {
log.info("Handle port insert");
Insert intfInsert = handlePortInsertTable(OvsdbConstant.INTERFACE,
row);
if (intfInsert != null) {
operations.add(intfInsert);
}
Insert ins = (Insert) operations.get(0);
ins.getRow().put("interfaces",
UUID.uuid(OvsdbConstant.INTERFACE));
}
List<OperationResult> results;
try {
results = transactConfig(OvsdbConstant.DATABASENAME, operations)
.get();
return results.get(0).getUuid().value();
} catch (InterruptedException e) {
log.warn("Interrupted while waiting to get result");
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
log.error("Exception thrown while to get result");
}
return null;
}
/**
* Handles port insert.
*
* @param tableName ovsdb table interface
* @param portRow row of port
*
* @return insert, empty if null
*/
private Insert handlePortInsertTable(String tableName, Row portRow) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema portTableSchema = dbSchema
.getTableSchema(OvsdbConstant.PORT);
ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Interface inf = (Interface) TableGenerator
.createTable(dbSchema, OvsdbTable.INTERFACE);
inf.setName(portName);
TableSchema intfTableSchema = dbSchema
.getTableSchema(OvsdbConstant.INTERFACE);
Insert insert = new Insert(intfTableSchema, OvsdbConstant.INTERFACE,
inf.getRow());
return insert;
}
/**
* Gets tunnel name.
*
* @param tunnelType
* @param dstIp the remote ip address
*
* @return tunnel name
*/
private String getTunnelName(String tunnelType, IpAddress dstIp) {
return tunnelType + "-" + dstIp.toString();
}
@Override
public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
if (dbName == null) {
return null;
}
DatabaseSchema databaseSchema = schema.get(dbName);
if (databaseSchema == null) {
List<String> dbNames = new ArrayList<String>();
dbNames.add(dbName);
Function<JsonNode, DatabaseSchema> rowFunction = new Function<JsonNode, DatabaseSchema>() {
@Override
public DatabaseSchema apply(JsonNode input) {
log.info("Get ovsdb database schema", dbName);
DatabaseSchema dbSchema = FromJsonUtil
.jsonNodeToDbSchema(dbName, input);
if (dbSchema == null) {
log.debug("Get ovsdb database schema error");
return null;
}
schema.put(dbName, dbSchema);
return dbSchema;
}
};
ListenableFuture<JsonNode> input = getSchema(dbNames);
if (input != null) {
try {
log.info("input message: {}", input.get().toString());
} catch (InterruptedException e) {
log.warn("Interrupted while waiting to get message");
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
log.error("Exception thrown while to get message");
}
}
return Futures.transform(input, rowFunction);
} else {
return Futures.immediateFuture(databaseSchema);
}
}
@Override
public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
if (dbName == null) {
return null;
}
DatabaseSchema dbSchema = schema.get(dbName);
if (dbSchema != null) {
Function<JsonNode, TableUpdates> rowFunction = new Function<JsonNode, TableUpdates>() {
@Override
public TableUpdates apply(JsonNode input) {
log.info("Get table updates");
TableUpdates updates = FromJsonUtil
.jsonNodeToTableUpdates(input, dbSchema);
if (updates == null) {
log.debug("Get table updates error");
return null;
}
return updates;
}
};
return Futures.transform(monitor(dbSchema, id), rowFunction);
}
return null;
}
@Override
public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
List<Operation> operations) {
if (dbName == null) {
return null;
}
DatabaseSchema dbSchema = schema.get(dbName);
if (dbSchema != null) {
Function<List<JsonNode>, List<OperationResult>> rowFunction =
new Function<List<JsonNode>, List<OperationResult>>() {
@Override
public List<OperationResult> apply(List<JsonNode> input) {
log.info("Get ovsdb operation result");
List<OperationResult> result = FromJsonUtil
.jsonNodeToOperationResult(input, operations);
if (result == null) {
log.debug("The operation result is null");
return null;
}
return result;
}
};
return Futures.transform(transact(dbSchema, operations),
rowFunction);
}
return null;
}
@Override
public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
String id = java.util.UUID.randomUUID().toString();
String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
SettableFuture<JsonNode> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "getSchema");
channel.writeAndFlush(getSchemaString);
return sf;
}
@Override
public ListenableFuture<List<String>> echo() {
String id = java.util.UUID.randomUUID().toString();
String echoString = JsonRpcWriterUtil.echoStr(id);
SettableFuture<List<String>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "echo");
channel.writeAndFlush(echoString);
return sf;
}
@Override
public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
String monitorId) {
String id = java.util.UUID.randomUUID().toString();
String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
dbSchema);
SettableFuture<JsonNode> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "monitor");
channel.writeAndFlush(monitorString);
return sf;
}
@Override
public ListenableFuture<List<String>> listDbs() {
String id = java.util.UUID.randomUUID().toString();
String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
SettableFuture<List<String>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "listDbs");
channel.writeAndFlush(listDbsString);
return sf;
}
@Override
public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
List<Operation> operations) {
String id = java.util.UUID.randomUUID().toString();
String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
operations);
SettableFuture<List<JsonNode>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "transact");
channel.writeAndFlush(transactString);
return sf;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void processResult(JsonNode response) {
log.debug("Handle result");
String requestId = response.get("id").asText();
SettableFuture sf = requestResult.get(requestId);
if (sf == null) {
log.debug("No such future to process");
return;
}
String methodName = requestMethod.get(requestId);
Object result;
result = FromJsonUtil.jsonResultParser(response, methodName);
sf.set(result);
return;
}
@Override
public void processRequest(JsonNode requestJson) {
log.debug("Handle request");
if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
log.debug("handle echo request");
String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
channel.writeAndFlush(replyString);
return;
} else {
FromJsonUtil
.jsonCallbackRequestParser(requestJson, monitorCallBack);
return;
}
}
@Override
public void setCallback(Callback monitorCallback) {
this.monitorCallBack = monitorCallback;
}
@Override
public Set<OvsdbTunnel> getTunnels() {
return ovsdbTunnels;
}
@Override
public Set<OvsdbBridge> getBridges() {
return ovsdbBridges;
}
@Override
public Set<OvsdbPort> getPorts() {
return ovsdbPorts;
}
@Override
public DatabaseSchema getDatabaseSchema(String dbName) {
return schema.get(dbName);
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ovsdb.controller.driver;
import io.netty.channel.Channel;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import org.onlab.packet.IpAddress;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbBridgeName;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbConstant;
import org.onosproject.ovsdb.controller.OvsdbDatapathId;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import org.onosproject.ovsdb.controller.OvsdbPortName;
import org.onosproject.ovsdb.controller.OvsdbPortNumber;
import org.onosproject.ovsdb.controller.OvsdbRowStore;
import org.onosproject.ovsdb.controller.OvsdbStore;
import org.onosproject.ovsdb.controller.OvsdbTableStore;
import org.onosproject.ovsdb.controller.OvsdbTunnel;
import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
import org.onosproject.ovsdb.rfc.message.OperationResult;
import org.onosproject.ovsdb.rfc.message.TableUpdates;
import org.onosproject.ovsdb.rfc.notation.Condition;
import org.onosproject.ovsdb.rfc.notation.Mutation;
import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
import org.onosproject.ovsdb.rfc.notation.Row;
import org.onosproject.ovsdb.rfc.notation.UUID;
import org.onosproject.ovsdb.rfc.operations.Delete;
import org.onosproject.ovsdb.rfc.operations.Insert;
import org.onosproject.ovsdb.rfc.operations.Mutate;
import org.onosproject.ovsdb.rfc.operations.Operation;
import org.onosproject.ovsdb.rfc.operations.Update;
import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
import org.onosproject.ovsdb.rfc.schema.TableSchema;
import org.onosproject.ovsdb.rfc.table.Bridge;
import org.onosproject.ovsdb.rfc.table.Controller;
import org.onosproject.ovsdb.rfc.table.Interface;
import org.onosproject.ovsdb.rfc.table.OvsdbTable;
import org.onosproject.ovsdb.rfc.table.Port;
import org.onosproject.ovsdb.rfc.table.TableGenerator;
import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
import org.onosproject.ovsdb.rfc.utils.MutationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
/**
* An representation of an ovsdb client.
*/
public class DefaultOvsdbClient
implements OvsdbProviderService, OvsdbClientService {
private final Logger log = LoggerFactory
.getLogger(DefaultOvsdbClient.class);
private Channel channel;
private OvsdbAgent agent;
private boolean connected;
private OvsdbNodeId nodeId;
private Callback monitorCallBack;
private OvsdbStore ovsdbStore = new OvsdbStore();
private final Map<String, String> requestMethod = Maps.newHashMap();
private final Map<String, SettableFuture<? extends Object>> requestResult = Maps
.newHashMap();
private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
/**
* Creates an OvsdbClient.
*
* @param nodeId ovsdb node id
*/
public DefaultOvsdbClient(OvsdbNodeId nodeId) {
this.nodeId = nodeId;
}
@Override
public OvsdbNodeId nodeId() {
return nodeId;
}
@Override
public void setAgent(OvsdbAgent agent) {
if (this.agent == null) {
this.agent = agent;
}
}
@Override
public void setChannel(Channel channel) {
this.channel = channel;
}
@Override
public void setConnection(boolean connected) {
this.connected = connected;
}
@Override
public boolean isConnected() {
return this.connected;
}
@Override
public void nodeAdded() {
this.agent.addConnectedNode(nodeId, this);
}
@Override
public void nodeRemoved() {
this.agent.removeConnectedNode(nodeId);
channel.disconnect();
}
/**
* Gets the ovsdb table store.
*
* @param dbName the ovsdb database name
* @return ovsTableStore, empty if table store is find
*/
private OvsdbTableStore getTableStore(String dbName) {
if (ovsdbStore == null) {
return null;
}
return ovsdbStore.getOvsdbTableStore(dbName);
}
/**
* Gets the ovsdb row store.
*
* @param dbName the ovsdb database name
* @param tableName the ovsdb table name
*
* @return ovsRowStore, empty if row store is find
*/
private OvsdbRowStore getRowStore(String dbName, String tableName) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return null;
}
return tableStore.getRows(tableName);
}
/**
* Gets the ovsdb row.
*
* @param dbName the ovsdb database name
* @param tableName the ovsdb table name
* @param uuid the key of the row
* @return row, empty if row is find
*/
@Override
public Row getRow(String dbName, String tableName, String uuid) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return null;
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
return null;
}
return rowStore.getRow(uuid);
}
@Override
public void removeRow(String dbName, String tableName, String uuid) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return;
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
return;
}
rowStore.deleteRow(uuid);
}
@Override
public void updateOvsdbStore(String dbName, String tableName, String uuid,
Row row) {
OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
if (tableStore == null) {
tableStore = new OvsdbTableStore();
}
OvsdbRowStore rowStore = tableStore.getRows(tableName);
if (rowStore == null) {
rowStore = new OvsdbRowStore();
}
rowStore.insertRow(uuid, row);
tableStore.createOrUpdateTable(tableName, rowStore);
ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
}
@Override
public String getPortUuid(String portName, String bridgeUuid) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Row bridgeRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.BRIDGE, bridgeUuid);
Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
OvsdbTable.BRIDGE);
if (bridge != null) {
OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
@SuppressWarnings("unchecked")
Set<UUID> ports = setPorts.set();
if (ports == null || ports.size() == 0) {
log.warn("The port uuid is null");
return null;
}
for (UUID uuid : ports) {
Row portRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.PORT, uuid.value());
Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
OvsdbTable.PORT);
if (port != null && portName.equalsIgnoreCase(port.getName())) {
return uuid.value();
}
}
}
return null;
}
@Override
public String getInterfaceUuid(String portUuid, String portName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Row portRow = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.PORT,
portUuid);
Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
OvsdbTable.PORT);
if (port != null) {
OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
@SuppressWarnings("unchecked")
Set<UUID> interfaces = setInterfaces.set();
if (interfaces == null || interfaces.size() == 0) {
log.warn("The interface uuid is null");
return null;
}
for (UUID uuid : interfaces) {
Row intfRow = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.INTERFACE, uuid.value());
Interface intf = (Interface) TableGenerator
.getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
return uuid.value();
}
}
}
return null;
}
@Override
public String getBridgeUuid(String bridgeName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.BRIDGE);
if (rowStore == null) {
log.debug("The bridge uuid is null");
return null;
}
ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
if (bridgeTableRows == null) {
log.debug("The bridge uuid is null");
return null;
}
for (String uuid : bridgeTableRows.keySet()) {
Bridge bridge = (Bridge) TableGenerator
.getTable(dbSchema, bridgeTableRows.get(uuid),
OvsdbTable.BRIDGE);
if (bridge.getName().equals(bridgeName)) {
return uuid;
}
}
return null;
}
@Override
public String getControllerUuid(String controllerName,
String controllerTarget) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.CONTROLLER);
if (rowStore == null) {
log.debug("The controller uuid is null");
return null;
}
ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
if (controllerTableRows != null) {
for (String uuid : controllerTableRows.keySet()) {
Controller controller = (Controller) TableGenerator
.getTable(dbSchema, controllerTableRows.get(uuid),
OvsdbTable.CONTROLLER);
String target = (String) controller.getTargetColumn().data();
if (target.equalsIgnoreCase(controllerTarget)) {
return uuid;
}
}
}
return null;
}
@Override
public String getOvsUuid(String dbName) {
OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
OvsdbConstant.DATABASENAME);
if (rowStore == null) {
log.debug("The bridge uuid is null");
return null;
}
ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
if (ovsTableRows != null) {
for (String uuid : ovsTableRows.keySet()) {
Row row = ovsTableRows.get(uuid);
String tableName = row.tableName();
if (tableName.equals(dbName)) {
return uuid;
}
}
}
return null;
}
@Override
public void createPort(String bridgeName, String portName) {
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.error("Can't find bridge {} in {}", bridgeName,
nodeId.getIpAddress());
return;
}
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
String portUuid = getPortUuid(portName, bridgeUuid);
Port port = (Port) TableGenerator
.createTable(dbSchema, OvsdbTable.PORT);
port.setName(portName);
if (portUuid == null) {
insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
"ports", bridgeUuid, port.getRow());
} else {
updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
}
return;
}
@Override
public void dropPort(String bridgeName, String portName) {
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
return;
}
String portUuid = getPortUuid(portName, bridgeUuid);
if (portUuid != null) {
log.info("Port {} delete", portName);
deleteConfig(OvsdbConstant.PORT, "_uuid", portUuid,
OvsdbConstant.BRIDGE, "ports");
}
}
@Override
public void createBridge(String bridgeName) {
log.debug("create bridge {}", bridgeName);
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
if (dbSchema == null) {
log.warn("The schema is null");
return;
}
Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
OvsdbTable.BRIDGE);
if (bridge == null) {
log.debug("Can not create bridge");
return;
}
Set<String> failModes = new HashSet<>();
failModes.add("secure");
bridge.setFailMode(failModes);
Set<String> protocols = new HashSet<>();
protocols.add(OvsdbConstant.OPENFLOW13);
bridge.setProtocols(protocols);
String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
if (ovsUuid == null) {
log.warn("The Open_vSwitch is null");
return;
}
String bridgeUuid = getBridgeUuid(bridgeName);
if (bridgeUuid == null) {
log.debug("Create a new bridge");
bridge.setName(bridgeName);
bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
OvsdbConstant.DATABASENAME, "bridges",
ovsUuid, bridge.getRow());
if (bridgeUuid != null) {
Port port = (Port) TableGenerator.createTable(dbSchema,
OvsdbTable.PORT);
if (port != null) {
log.debug("the port is not null");
port.setName(bridgeName);
insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
port.getRow());
}
}
} else {
log.info("Update a bridge");
updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
}
setController(bridgeUuid);
log.info("Create bridge success");
}
/**
* Sets the Controller.
*
* @param bridgeUuid bridge uuid
*/
private void setController(String bridgeUuid) {
String controllerUuid = null;
String iPAddress = IpAddress.valueOf(((InetSocketAddress) channel
.localAddress())
.getAddress()
.getHostAddress())
.toString();
String target = "tcp:" + iPAddress + ":" + OvsdbConstant.OFPORT;
log.debug("controller IP {}: port {}", iPAddress, OvsdbConstant.OFPORT);
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
Controller controller = (Controller) TableGenerator
.createTable(dbSchema, OvsdbTable.CONTROLLER);
if (controller != null) {
controller.setTarget(target);
controllerUuid = getControllerUuid(OvsdbConstant.CONTROLLER, target);
if (controllerUuid == null) {
insertConfig(OvsdbConstant.CONTROLLER, "_uuid",
OvsdbConstant.BRIDGE, "controller", bridgeUuid,
controller.getRow());
} else {
Bridge bridge = (Bridge) TableGenerator
.createTable(dbSchema, OvsdbTable.BRIDGE);
Set<UUID> controllerUuids = new HashSet<>();
controllerUuids.add(UUID.uuid(controllerUuid));
bridge.setController(controllerUuids);
updateConfig(OvsdbConstant.CONTROLLER, "_uuid", bridgeUuid, bridge.getRow());
}
}
}
@Override
public void dropBridge(String bridgeName) {
String bridgeUUID = getBridgeUuid(bridgeName);
if (bridgeUUID == null) {
log.warn("Could not find bridge in node", nodeId.getIpAddress());
return;
}
deleteConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUUID,
OvsdbConstant.DATABASENAME, "bridges");
}
@Override
public void createTunnel(IpAddress srcIp, IpAddress dstIp) {
String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
if (bridgeUuid == null) {
log.warn("Could not find bridge {} and Could not create tunnel. ",
OvsdbConstant.INTEGRATION_BRIDGE);
return;
}
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
String portUuid = getPortUuid(portName, bridgeUuid);
Port port = (Port) TableGenerator
.createTable(dbSchema, OvsdbTable.PORT);
if (port != null) {
port.setName(portName);
}
if (portUuid == null) {
portUuid = insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
"ports", bridgeUuid, port.getRow());
} else {
updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
}
// When a tunnel is created, A row is inserted into port table and
// interface table of the ovsdb node.
// and the following step is to get the interface uuid from local store
// in controller node.
// but it need spend some time synchronising data between node and
// controller.
// so loop to judge if interfaceUUid is null is necessary.
String interfaceUuid = null;
for (int i = 0; i < 10; i++) {
interfaceUuid = getInterfaceUuid(portUuid, portName);
if (interfaceUuid == null) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.warn("Interrupted while waiting to get interfaceUuid");
Thread.currentThread().interrupt();
}
} else {
break;
}
}
if (interfaceUuid != null) {
Interface tunInterface = (Interface) TableGenerator
.createTable(dbSchema, OvsdbTable.INTERFACE);
if (tunInterface != null) {
tunInterface.setType(OvsdbConstant.TYPEVXLAN);
Map<String, String> options = Maps.newHashMap();
options.put("key", "flow");
options.put("local_ip", srcIp.toString());
options.put("remote_ip", dstIp.toString());
tunInterface.setOptions(options);
updateConfig(OvsdbConstant.INTERFACE, "_uuid", interfaceUuid,
tunInterface.getRow());
log.info("Tunnel added success", tunInterface);
}
}
return;
}
@Override
public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE;
String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
if (bridgeUuid == null) {
log.warn("Could not find bridge {} in {}", bridgeName,
nodeId.getIpAddress());
return;
}
String portUUID = getPortUuid(portName, bridgeUuid);
if (portUUID != null) {
log.info("Delete tunnel");
deleteConfig(OvsdbConstant.PORT, "_uuid", portUUID,
OvsdbConstant.BRIDGE, "ports");
}
return;
}
/**
* Delete transact config.
*
* @param childTableName child table name
* @param childColumnName child column name
* @param childUuid child row uuid
* @param parentTableName parent table name
* @param parentColumnName parent column
*
*/
private void deleteConfig(String childTableName, String childColumnName,
String childUuid, String parentTableName,
String parentColumnName) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
ArrayList<Operation> operations = Lists.newArrayList();
if (parentTableName != null && parentColumnName != null) {
TableSchema parentTableSchema = dbSchema
.getTableSchema(parentTableName);
ColumnSchema parentColumnSchema = parentTableSchema
.getColumnSchema(parentColumnName);
List<Mutation> mutations = Lists.newArrayList();
Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
UUID.uuid(childUuid));
mutations.add(mutation);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.includes(parentColumnName,
UUID.uuid(childUuid));
conditions.add(condition);
Mutate op = new Mutate(parentTableSchema, conditions, mutations);
operations.add(op);
}
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals(childColumnName, UUID.uuid(childUuid));
conditions.add(condition);
Delete del = new Delete(childTableSchema, conditions);
operations.add(del);
transactConfig(OvsdbConstant.DATABASENAME, operations);
return;
}
/**
* Update transact config.
*
* @param tableName table name
* @param columnName column name
* @param uuid uuid
* @param row the config data
*
*/
private void updateConfig(String tableName, String columnName, String uuid,
Row row) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema tableSchema = dbSchema.getTableSchema(tableName);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals(columnName, UUID.uuid(uuid));
conditions.add(condition);
Update update = new Update(tableSchema, row, conditions);
ArrayList<Operation> operations = Lists.newArrayList();
operations.add(update);
transactConfig(OvsdbConstant.DATABASENAME, operations);
}
/**
* Insert transact config.
*
* @param childTableName child table name
* @param childColumnName child column name
* @param parentTableName parent table name
* @param parentColumnName parent column
* @param parentUuid parent uuid
* @param row the config data
*
* @return uuid, empty if no uuid is find
*/
private String insertConfig(String childTableName, String childColumnName,
String parentTableName, String parentColumnName,
String parentUuid, Row row) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
String namedUuid = childTableName;
Insert insert = new Insert(tableSchema, namedUuid, row);
ArrayList<Operation> operations = Lists.newArrayList();
operations.add(insert);
if (parentTableName != null && parentColumnName != null) {
TableSchema parentTableSchema = dbSchema
.getTableSchema(parentTableName);
ColumnSchema parentColumnSchema = parentTableSchema
.getColumnSchema(parentColumnName);
List<Mutation> mutations = Lists.newArrayList();
Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
UUID.uuid(namedUuid));
mutations.add(mutation);
List<Condition> conditions = Lists.newArrayList();
Condition condition = ConditionUtil.equals("_uuid",
UUID.uuid(parentUuid));
conditions.add(condition);
Mutate op = new Mutate(parentTableSchema, conditions, mutations);
operations.add(op);
}
if (childTableName.equalsIgnoreCase(OvsdbConstant.PORT)) {
log.info("Handle port insert");
Insert intfInsert = handlePortInsertTable(OvsdbConstant.INTERFACE,
row);
if (intfInsert != null) {
operations.add(intfInsert);
}
Insert ins = (Insert) operations.get(0);
ins.getRow().put("interfaces",
UUID.uuid(OvsdbConstant.INTERFACE));
}
List<OperationResult> results;
try {
results = transactConfig(OvsdbConstant.DATABASENAME, operations)
.get();
return results.get(0).getUuid().value();
} catch (InterruptedException e) {
log.warn("Interrupted while waiting to get result");
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
log.error("Exception thrown while to get result");
}
return null;
}
/**
* Handles port insert.
*
* @param tableName ovsdb table interface
* @param portRow row of port
*
* @return insert, empty if null
*/
private Insert handlePortInsertTable(String tableName, Row portRow) {
DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
TableSchema portTableSchema = dbSchema
.getTableSchema(OvsdbConstant.PORT);
ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Interface inf = (Interface) TableGenerator
.createTable(dbSchema, OvsdbTable.INTERFACE);
inf.setName(portName);
TableSchema intfTableSchema = dbSchema
.getTableSchema(OvsdbConstant.INTERFACE);
Insert insert = new Insert(intfTableSchema, OvsdbConstant.INTERFACE,
inf.getRow());
return insert;
}
/**
* Gets tunnel name.
*
* @param tunnelType
* @param dstIp the remote ip address
*
* @return tunnel name
*/
private String getTunnelName(String tunnelType, IpAddress dstIp) {
return tunnelType + "-" + dstIp.toString();
}
@Override
public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
if (dbName == null) {
return null;
}
DatabaseSchema databaseSchema = schema.get(dbName);
if (databaseSchema == null) {
List<String> dbNames = new ArrayList<String>();
dbNames.add(dbName);
Function<JsonNode, DatabaseSchema> rowFunction = new Function<JsonNode, DatabaseSchema>() {
@Override
public DatabaseSchema apply(JsonNode input) {
log.info("Get ovsdb database schema", dbName);
DatabaseSchema dbSchema = FromJsonUtil
.jsonNodeToDbSchema(dbName, input);
if (dbSchema == null) {
log.debug("Get ovsdb database schema error");
return null;
}
schema.put(dbName, dbSchema);
return dbSchema;
}
};
ListenableFuture<JsonNode> input = getSchema(dbNames);
if (input != null) {
return Futures.transform(input, rowFunction);
}
return null;
} else {
return Futures.immediateFuture(databaseSchema);
}
}
@Override
public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
if (dbName == null) {
return null;
}
DatabaseSchema dbSchema = schema.get(dbName);
if (dbSchema != null) {
Function<JsonNode, TableUpdates> rowFunction = new Function<JsonNode, TableUpdates>() {
@Override
public TableUpdates apply(JsonNode input) {
log.info("Get table updates");
TableUpdates updates = FromJsonUtil
.jsonNodeToTableUpdates(input, dbSchema);
if (updates == null) {
log.debug("Get table updates error");
return null;
}
return updates;
}
};
return Futures.transform(monitor(dbSchema, id), rowFunction);
}
return null;
}
@Override
public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
List<Operation> operations) {
if (dbName == null) {
return null;
}
DatabaseSchema dbSchema = schema.get(dbName);
if (dbSchema != null) {
Function<List<JsonNode>, List<OperationResult>> rowFunction =
new Function<List<JsonNode>, List<OperationResult>>() {
@Override
public List<OperationResult> apply(List<JsonNode> input) {
log.info("Get ovsdb operation result");
List<OperationResult> result = FromJsonUtil
.jsonNodeToOperationResult(input, operations);
if (result == null) {
log.debug("The operation result is null");
return null;
}
return result;
}
};
return Futures.transform(transact(dbSchema, operations),
rowFunction);
}
return null;
}
@Override
public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
String id = java.util.UUID.randomUUID().toString();
String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
SettableFuture<JsonNode> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "getSchema");
channel.writeAndFlush(getSchemaString);
return sf;
}
@Override
public ListenableFuture<List<String>> echo() {
String id = java.util.UUID.randomUUID().toString();
String echoString = JsonRpcWriterUtil.echoStr(id);
SettableFuture<List<String>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "echo");
channel.writeAndFlush(echoString);
return sf;
}
@Override
public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
String monitorId) {
String id = java.util.UUID.randomUUID().toString();
String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
dbSchema);
SettableFuture<JsonNode> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "monitor");
channel.writeAndFlush(monitorString);
return sf;
}
@Override
public ListenableFuture<List<String>> listDbs() {
String id = java.util.UUID.randomUUID().toString();
String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
SettableFuture<List<String>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "listDbs");
channel.writeAndFlush(listDbsString);
return sf;
}
@Override
public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
List<Operation> operations) {
String id = java.util.UUID.randomUUID().toString();
String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
operations);
SettableFuture<List<JsonNode>> sf = SettableFuture.create();
requestResult.put(id, sf);
requestMethod.put(id, "transact");
channel.writeAndFlush(transactString);
return sf;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void processResult(JsonNode response) {
log.debug("Handle result");
String requestId = response.get("id").asText();
SettableFuture sf = requestResult.get(requestId);
if (sf == null) {
log.debug("No such future to process");
return;
}
String methodName = requestMethod.get(requestId);
Object result;
result = FromJsonUtil.jsonResultParser(response, methodName);
sf.set(result);
return;
}
@Override
public void processRequest(JsonNode requestJson) {
log.debug("Handle request");
if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
log.debug("handle echo request");
String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
channel.writeAndFlush(replyString);
return;
} else {
FromJsonUtil
.jsonCallbackRequestParser(requestJson, monitorCallBack);
return;
}
}
@Override
public void setCallback(Callback monitorCallback) {
this.monitorCallBack = monitorCallback;
}
@Override
public Set<OvsdbTunnel> getTunnels() {
return ovsdbTunnels;
}
@Override
public Set<OvsdbBridge> getBridges() {
Set<OvsdbBridge> ovsdbBridges = new HashSet<OvsdbBridge>();
OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
if (tableStore == null) {
return null;
}
OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.BRIDGE);
if (rowStore == null) {
return null;
}
ConcurrentMap<String, Row> rows = rowStore.getRowStore();
for (String uuid : rows.keySet()) {
Row row = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.BRIDGE,
uuid);
OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
if (ovsdbBridge != null) {
ovsdbBridges.add(ovsdbBridge);
}
}
return ovsdbBridges;
}
@Override
public Set<OvsdbPort> getPorts() {
Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
if (tableStore == null) {
return null;
}
OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.INTERFACE);
if (rowStore == null) {
return null;
}
ConcurrentMap<String, Row> rows = rowStore.getRowStore();
for (String uuid : rows.keySet()) {
Row row = getRow(OvsdbConstant.DATABASENAME,
OvsdbConstant.INTERFACE, uuid);
OvsdbPort ovsdbPort = getOvsdbPort(row);
if (ovsdbPort != null) {
ovsdbPorts.add(ovsdbPort);
}
}
return ovsdbPorts;
}
@Override
public DatabaseSchema getDatabaseSchema(String dbName) {
return schema.get(dbName);
}
//Gets ovsdb port.
private OvsdbPort getOvsdbPort(Row row) {
DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
Interface intf = (Interface) TableGenerator
.getTable(dbSchema, row, OvsdbTable.INTERFACE);
if (intf == null) {
return null;
}
long ofPort = getOfPort(intf);
String portName = intf.getName();
if ((ofPort < 0) || (portName == null)) {
return null;
}
OvsdbPort ovsdbPort = new OvsdbPort(new OvsdbPortNumber(ofPort),
new OvsdbPortName(portName));
return ovsdbPort;
}
////Gets ovsdb bridge.
private OvsdbBridge getOvsdbBridge(Row row) {
DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row,
OvsdbTable.BRIDGE);
if (bridge == null) {
return null;
}
OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
@SuppressWarnings("unchecked")
Set<String> datapathIds = datapathIdSet.set();
if (datapathIds == null || datapathIds.size() == 0) {
return null;
}
String datapathId = (String) datapathIds.toArray()[0];
String bridgeName = bridge.getName();
if ((datapathId == null) || (bridgeName == null)) {
return null;
}
OvsdbBridge ovsdbBridge = new OvsdbBridge(new OvsdbBridgeName(bridgeName),
new OvsdbDatapathId(datapathId));
return ovsdbBridge;
}
//Gets ofPort in the interface.
private long getOfPort(Interface intf) {
OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
@SuppressWarnings("unchecked")
Set<Integer> ofPorts = ofPortSet.set();
while (ofPorts == null || ofPorts.size() <= 0) {
log.debug("The ofport is null in {}", intf.getName());
return -1;
}
// return (long) ofPorts.toArray()[0];
Iterator<Integer> it = ofPorts.iterator();
return Long.parseLong(it.next().toString());
}
}
......