Hyunsun Moon
Committed by Gerrit Code Review

CORD-524 Added a state to set data plane IP to br-int

Added new config fields
- SSH port, user, private key file
- localManagementIp for connection b/w a compute node and VM

Renamed some config fields and methods
- phyPortName is changed to dataPlaneIntf
- localIp is changed to dataPlaneIp
- ovsdbIp is changed to hostManagementIp and it is used to SSH as well
- checkXXX methods with boolean return are renamed to isXXX

Removed unnecessary OVSDB_CONNECTED state
Removed cordvtn-node-add CLI due to too many arguments

Change-Id: If5efb65fc58bfa8a10767047f01598dc2ac02a04
......@@ -265,7 +265,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
SparseAnnotations annotations = DefaultAnnotations.builder()
.set(OPENSTACK_VM_ID, vPort.deviceId())
.set(SERVICE_ID, vPort.networkId())
.set(LOCATION_IP, node.localIp().toString())
.set(LOCATION_IP, node.dpIp().ip().toString())
.build();
HostDescription hostDesc = new DefaultHostDescription(
......
......@@ -17,7 +17,6 @@ package org.onosproject.cordvtn;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Sets;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
......@@ -37,14 +36,19 @@ public class CordVtnConfig extends Config<ApplicationId> {
protected final Logger log = getLogger(getClass());
public static final String GATEWAY_MAC = "gatewayMac";
public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
public static final String OVSDB_PORT = "ovsdbPort";
public static final String SSH_PORT = "sshPort";
public static final String SSH_USER = "sshUser";
public static final String SSH_KEY_FILE = "sshKeyFile";
public static final String CORDVTN_NODES = "nodes";
public static final String HOSTNAME = "hostname";
public static final String OVSDB_IP = "ovsdbIp";
public static final String OVSDB_PORT = "ovsdbPort";
public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
public static final String DATA_PLANE_IP = "dataPlaneIp";
public static final String DATA_PLANE_INTF = "dataPlaneIntf";
public static final String BRIDGE_ID = "bridgeId";
public static final String PHYSICAL_PORT_NAME = "phyPortName";
public static final String LOCAL_IP = "localIp";
public static final String GATEWAY_MAC = "gatewayMac";
/**
* Returns the set of nodes read from network config.
......@@ -58,13 +62,19 @@ public class CordVtnConfig extends Config<ApplicationId> {
if (jsonNodes == null) {
return null;
}
jsonNodes.forEach(jsonNode -> nodes.add(new CordVtnNodeConfig(
jsonNode.path(HOSTNAME).asText(),
IpAddress.valueOf(jsonNode.path(OVSDB_IP).asText()),
TpPort.tpPort(jsonNode.path(OVSDB_PORT).asInt()),
DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText()),
jsonNode.path(PHYSICAL_PORT_NAME).asText(),
IpAddress.valueOf(jsonNode.path(LOCAL_IP).asText()))));
jsonNodes.forEach(jsonNode -> {
try {
nodes.add(new CordVtnNodeConfig(
jsonNode.path(HOSTNAME).asText(),
NetworkAddress.valueOf(jsonNode.path(HOST_MANAGEMENT_IP).asText()),
NetworkAddress.valueOf(jsonNode.path(DATA_PLANE_IP).asText()),
jsonNode.path(DATA_PLANE_INTF).asText(),
DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText())));
} catch (IllegalArgumentException | NullPointerException e) {
log.error("Failed to read {}", e.toString());
}
});
return nodes;
}
......@@ -89,25 +99,108 @@ public class CordVtnConfig extends Config<ApplicationId> {
}
/**
* Returns local management network address.
*
* @return network address
*/
public NetworkAddress localMgmtIp() {
JsonNode jsonNode = object.get(LOCAL_MANAGEMENT_IP);
if (jsonNode == null) {
return null;
}
try {
return NetworkAddress.valueOf(jsonNode.asText());
} catch (IllegalArgumentException e) {
log.error("Wrong address format {}", jsonNode.asText());
return null;
}
}
/**
* Returns the port number used for OVSDB connection.
*
* @return port number, or null
*/
public TpPort ovsdbPort() {
JsonNode jsonNode = object.get(OVSDB_PORT);
if (jsonNode == null) {
return null;
}
try {
return TpPort.tpPort(jsonNode.asInt());
} catch (IllegalArgumentException e) {
log.error("Wrong TCP port format {}", jsonNode.asText());
return null;
}
}
/**
* Returns the port number used for SSH connection.
*
* @return port number, or null
*/
public TpPort sshPort() {
JsonNode jsonNode = object.get(SSH_PORT);
if (jsonNode == null) {
return null;
}
try {
return TpPort.tpPort(jsonNode.asInt());
} catch (IllegalArgumentException e) {
log.error("Wrong TCP port format {}", jsonNode.asText());
return null;
}
}
/**
* Returns the user name for SSH connection.
*
* @return user name, or null
*/
public String sshUser() {
JsonNode jsonNode = object.get(SSH_USER);
if (jsonNode == null) {
return null;
}
return jsonNode.asText();
}
/**
* Returns the private key file for SSH connection.
*
* @return file path, or null
*/
public String sshKeyFile() {
JsonNode jsonNode = object.get(SSH_KEY_FILE);
if (jsonNode == null) {
return null;
}
return jsonNode.asText();
}
/**
* Configuration for CordVtn node.
*/
public static class CordVtnNodeConfig {
private final String hostname;
private final IpAddress ovsdbIp;
private final TpPort ovsdbPort;
private final NetworkAddress hostMgmtIp;
private final NetworkAddress dpIp;
private final String dpIntf;
private final DeviceId bridgeId;
private final String phyPortName;
private final IpAddress localIp;
public CordVtnNodeConfig(String hostname, IpAddress ovsdbIp, TpPort ovsdbPort,
DeviceId bridgeId, String phyPortName, IpAddress localIp) {
public CordVtnNodeConfig(String hostname, NetworkAddress hostMgmtIp, NetworkAddress dpIp,
String dpIntf, DeviceId bridgeId) {
this.hostname = checkNotNull(hostname);
this.ovsdbIp = checkNotNull(ovsdbIp);
this.ovsdbPort = checkNotNull(ovsdbPort);
this.hostMgmtIp = checkNotNull(hostMgmtIp);
this.dpIp = checkNotNull(dpIp);
this.dpIntf = checkNotNull(dpIntf);
this.bridgeId = checkNotNull(bridgeId);
this.phyPortName = checkNotNull(phyPortName);
this.localIp = checkNotNull(localIp);
}
/**
......@@ -120,48 +213,39 @@ public class CordVtnConfig extends Config<ApplicationId> {
}
/**
* Returns OVSDB ip address of the node.
* Returns the host management network address of the node.
*
* @return OVSDB server IP address
* @return management network address
*/
public IpAddress ovsdbIp() {
return this.ovsdbIp;
public NetworkAddress hostMgmtIp() {
return this.hostMgmtIp;
}
/**
* Returns OVSDB port number of the node.
* Returns the data plane network address.
*
* @return port number
* @return network address
*/
public TpPort ovsdbPort() {
return this.ovsdbPort;
public NetworkAddress dpIp() {
return this.dpIp;
}
/**
* Returns integration bridge id of the node.
* Returns the data plane interface name.
*
* @return device id
* @return interface name
*/
public DeviceId bridgeId() {
return this.bridgeId;
public String dpIntf() {
return this.dpIntf;
}
/**
* Returns physical port name.
*
* @return physical port name
*/
public String phyPortName() {
return this.phyPortName;
}
/**
* Returns local IP address.
* Returns integration bridge id of the node.
*
* @return ip address
* @return device id
*/
public IpAddress localIp() {
return this.localIp;
public DeviceId bridgeId() {
return this.bridgeId;
}
}
}
......
......@@ -16,7 +16,6 @@
package org.onosproject.cordvtn;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.net.DeviceId;
......@@ -31,11 +30,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
public final class CordVtnNode {
private final String hostname;
private final IpAddress ovsdbIp;
private final NetworkAddress hostMgmtIp;
private final NetworkAddress localMgmtIp;
private final NetworkAddress dpIp;
private final TpPort ovsdbPort;
private final SshAccessInfo sshInfo;
private final DeviceId bridgeId;
private final String phyPortName;
private final IpAddress localIp;
private final String dpIntf;
public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
(node1, node2) -> node1.hostname().compareTo(node2.hostname());
......@@ -44,33 +45,65 @@ public final class CordVtnNode {
* Creates a new node.
*
* @param hostname hostname
* @param ovsdbIp OVSDB server IP address
* @param ovsdbPort OVSDB server port number
* @param hostMgmtIp host management network address
* @param localMgmtIp local management network address
* @param dpIp data plane network address
* @param ovsdbPort port number for OVSDB connection
* @param sshInfo SSH access information
* @param bridgeId integration bridge identifier
* @param phyPortName physical port name
* @param localIp local ip address of data plane
* @param dpIntf data plane interface name
*/
public CordVtnNode(String hostname, IpAddress ovsdbIp, TpPort ovsdbPort,
DeviceId bridgeId, String phyPortName, IpAddress localIp) {
this.hostname = checkNotNull(hostname);
this.ovsdbIp = checkNotNull(ovsdbIp);
this.ovsdbPort = checkNotNull(ovsdbPort);
this.bridgeId = checkNotNull(bridgeId);
this.phyPortName = checkNotNull(phyPortName);
this.localIp = checkNotNull(localIp);
public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp,
NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo,
DeviceId bridgeId, String dpIntf) {
this.hostname = checkNotNull(hostname, "hostname cannot be null");
this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null");
this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null");
this.dpIp = checkNotNull(dpIp, "dpIp cannot be null");
this.ovsdbPort = checkNotNull(ovsdbPort, "ovsdbPort cannot be null");
this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null");
this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null");
this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null");
}
/**
* Returns the OVSDB server IP address.
* Returns the hostname.
*
* @return hostname
*/
public String hostname() {
return this.hostname;
}
/**
* Returns the host management network address.
*
* @return network address
*/
public NetworkAddress hostMgmtIp() {
return this.hostMgmtIp;
}
/**
* Returns the local management network address.
*
* @return ip address
* @return network address
*/
public IpAddress ovsdbIp() {
return this.ovsdbIp;
public NetworkAddress localMgmtIp() {
return this.localMgmtIp;
}
/**
* Returns the OVSDB server port number.
* Returns the data plane network address.
*
* @return network address
*/
public NetworkAddress dpIp() {
return this.dpIp;
}
/**
* Returns the port number used for OVSDB connection.
*
* @return port number
*/
......@@ -79,12 +112,12 @@ public final class CordVtnNode {
}
/**
* Returns the hostname.
* Returns the SSH access information.
*
* @return hostname
* @return ssh access information
*/
public String hostname() {
return this.hostname;
public SshAccessInfo sshInfo() {
return this.sshInfo;
}
/**
......@@ -102,25 +135,16 @@ public final class CordVtnNode {
* @return device id
*/
public DeviceId ovsdbId() {
return DeviceId.deviceId("ovsdb:" + this.ovsdbIp.toString());
}
/**
* Returns physical port name.
*
* @return physical port name
*/
public String phyPortName() {
return this.phyPortName;
return DeviceId.deviceId("ovsdb:" + this.hostMgmtIp.ip().toString());
}
/**
* Returns local IP address.
* Returns data plane interface name.
*
* @return ip address
* @return data plane interface name
*/
public IpAddress localIp() {
return this.localIp;
public String dpIntf() {
return this.dpIntf;
}
@Override
......@@ -129,6 +153,8 @@ public final class CordVtnNode {
return true;
}
// hostname here is a network hostname and it is intended to be
// unique throughout the service.
if (obj instanceof CordVtnNode) {
CordVtnNode that = (CordVtnNode) obj;
if (Objects.equals(hostname, that.hostname)) {
......@@ -146,12 +172,14 @@ public final class CordVtnNode {
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("host", hostname)
.add("ip", ovsdbIp)
.add("hostname", hostname)
.add("hostMgmtIp", hostMgmtIp)
.add("localMgmtIp", localMgmtIp)
.add("dpIp", dpIp)
.add("port", ovsdbPort)
.add("sshInfo", sshInfo)
.add("bridgeId", bridgeId)
.add("phyPortName", phyPortName)
.add("localIp", localIp)
.add("dpIntf", dpIntf)
.toString();
}
}
......
......@@ -96,6 +96,7 @@ public class CordVtnRuleInstaller {
protected final Logger log = getLogger(getClass());
private static final String PORT_NAME = "portName";
private static final int TABLE_FIRST = 0;
private static final int TABLE_IN_PORT = 1;
private static final int TABLE_ACCESS_TYPE = 2;
......@@ -150,18 +151,18 @@ public class CordVtnRuleInstaller {
* Installs table miss rule to a give device.
*
* @param deviceId device id to install the rules
* @param phyPortName physical port name
* @param localIp local data plane ip address
* @param dpIntf data plane interface name
* @param dpIp data plane ip address
*/
public void init(DeviceId deviceId, String phyPortName, IpAddress localIp) {
public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
// default is drop packets which can be accomplished without
// a table miss entry for all table.
PortNumber tunnelPort = getTunnelPort(deviceId);
PortNumber phyPort = getPhyPort(deviceId, phyPortName);
PortNumber dpPort = getDpPort(deviceId, dpIntf);
processFirstTable(deviceId, phyPort, localIp);
processInPortTable(deviceId, tunnelPort, phyPort);
processAccessTypeTable(deviceId, phyPort);
processFirstTable(deviceId, dpPort, dpIp);
processInPortTable(deviceId, tunnelPort, dpPort);
processAccessTypeTable(deviceId, dpPort);
}
/**
......@@ -510,21 +511,21 @@ public class CordVtnRuleInstaller {
/**
* Populates default rules on the first table.
* The rules are for shuttling vxlan-encapped packets and supporting physical
* network connectivity.
* It includes the rules for shuttling vxlan-encapped packets between ovs and
* linux stack,and external network connectivity.
*
* @param deviceId device id
* @param phyPort physical port number
* @param localIp local data plane ip address
* @param dpPort data plane interface port number
* @param dpIp data plane ip address
*/
private void processFirstTable(DeviceId deviceId, PortNumber phyPort, IpAddress localIp) {
private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
// take vxlan packet out onto the physical port
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchInPort(PortNumber.LOCAL)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(phyPort)
.setOutput(dpPort)
.build();
FlowRule flowRule = DefaultFlowRule.builder()
......@@ -541,7 +542,7 @@ public class CordVtnRuleInstaller {
// take a vxlan encap'd packet through the Linux stack
selector = DefaultTrafficSelector.builder()
.matchInPort(phyPort)
.matchInPort(dpPort)
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_UDP)
.matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
......@@ -563,11 +564,11 @@ public class CordVtnRuleInstaller {
processFlowRule(true, flowRule);
// take a packet to the local ip through Linux stack
// take a packet to the data plane ip through Linux stack
selector = DefaultTrafficSelector.builder()
.matchInPort(phyPort)
.matchInPort(dpPort)
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(localIp.toIpPrefix())
.matchIPDst(dpIp.toIpPrefix())
.build();
treatment = DefaultTrafficTreatment.builder()
......@@ -588,7 +589,7 @@ public class CordVtnRuleInstaller {
// take an arp packet from physical through Linux stack
selector = DefaultTrafficSelector.builder()
.matchInPort(phyPort)
.matchInPort(dpPort)
.matchEthType(Ethernet.TYPE_ARP)
.build();
......@@ -630,17 +631,17 @@ public class CordVtnRuleInstaller {
}
/**
* Forward table miss packets in ACCESS_TYPE table to physical port.
* Forward table miss packets in ACCESS_TYPE table to data plane port.
*
* @param deviceId device id
* @param phyPort physical port number
* @param dpPort data plane interface port number
*/
private void processAccessTypeTable(DeviceId deviceId, PortNumber phyPort) {
private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(phyPort)
.setOutput(dpPort)
.build();
FlowRule flowRule = DefaultFlowRule.builder()
......@@ -659,13 +660,13 @@ public class CordVtnRuleInstaller {
/**
* Populates default rules for IN_PORT table.
* All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
* from physical port to ACCESS_TYPE table.
* from data plane interface port to ACCESS_TYPE table.
*
* @param deviceId device id to install the rules
* @param tunnelPort tunnel port number
* @param phyPort physical port number
* @param dpPort data plane interface port number
*/
private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber phyPort) {
private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
checkNotNull(tunnelPort);
TrafficSelector selector = DefaultTrafficSelector.builder()
......@@ -689,7 +690,7 @@ public class CordVtnRuleInstaller {
processFlowRule(true, flowRule);
selector = DefaultTrafficSelector.builder()
.matchInPort(phyPort)
.matchInPort(dpPort)
.build();
treatment = DefaultTrafficTreatment.builder()
......@@ -1027,22 +1028,22 @@ public class CordVtnRuleInstaller {
*/
private PortNumber getTunnelPort(DeviceId deviceId) {
Port port = deviceService.getPorts(deviceId).stream()
.filter(p -> p.annotations().value("portName").contains(tunnelType))
.filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
.findFirst().orElse(null);
return port == null ? null : port.number();
}
/**
* Returns physical port name of a given device.
* Returns data plane interface port name of a given device.
*
* @param deviceId device id
* @param phyPortName physical port name
* @return physical port number, or null if no physical port exists
* @param dpIntf data plane interface port name
* @return data plane interface port number, or null if no such port exists
*/
private PortNumber getPhyPort(DeviceId deviceId, String phyPortName) {
private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Port port = deviceService.getPorts(deviceId).stream()
.filter(p -> p.annotations().value("portName").contains(phyPortName) &&
.filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
p.isEnabled())
.findFirst().orElse(null);
......
/*
* Copyright 2016 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.cordvtn;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Representation of a network address, which consists of IP address and prefix.
*/
public final class NetworkAddress {
private final IpAddress ip;
private final IpPrefix prefix;
/**
* Constructor for a given IP address and prefix.
*
* @param ip ip address
* @param prefix ip prefix
*/
public NetworkAddress(IpAddress ip, IpPrefix prefix) {
this.ip = ip;
this.prefix = prefix;
}
/**
* Converts a CIDR notation string into a network address.
*
* @param cidr cidr
* @return network address
* @throws IllegalArgumentException if the cidr is not valid
*/
public static NetworkAddress valueOf(String cidr) {
checkArgument(cidr.contains("/"));
IpAddress ipAddress = IpAddress.valueOf(cidr.split("/")[0]);
IpPrefix ipPrefix = IpPrefix.valueOf(cidr);
return new NetworkAddress(ipAddress, ipPrefix);
}
/**
* Returns the IP address value of the network address.
*
* @return ip address
*/
public IpAddress ip() {
return this.ip;
}
/**
* Returns the IP prefix value of the network address.
*
* @return ip prefix
*/
public IpPrefix prefix() {
return this.prefix;
}
/**
* Converts a network address to a CIDR notation.
*
* @return cidr notation string
*/
public String cidr() {
return ip.toString() + "/" + prefix.prefixLength();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NetworkAddress) {
NetworkAddress that = (NetworkAddress) obj;
if (Objects.equals(ip, that.ip) && Objects.equals(prefix, that.prefix)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(ip, prefix);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("IpAddress", ip)
.add("IpPrefix", prefix)
.toString();
}
}
......@@ -22,7 +22,7 @@ import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.IpAddress;
import org.slf4j.Logger;
import java.io.IOException;
......@@ -48,8 +48,10 @@ public final class RemoteIpCommandUtil {
private static final String DEFAULT_STRICT_HOST_CHECKING = "no";
private static final int DEFAULT_SESSION_TIMEOUT = 60000; // milliseconds
private static final String IP_PATTERN = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.)" +
"{3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$";
private static final String IP_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
private static final String IP_ADDR_SHOW = "sudo ip addr show %s";
private static final String IP_ADDR_FLUSH = "sudo ip addr flush %s";
......@@ -68,18 +70,18 @@ public final class RemoteIpCommandUtil {
* Adds a given IP address to a given device.
*
* @param session ssh connection
* @param ip ip address
* @param ip network address
* @param device device name to assign the ip address
* @return true if the command succeeds, or false
*/
public static boolean addIp(Session session, IpPrefix ip, String device) {
public static boolean addIp(Session session, NetworkAddress ip, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_ADDR_ADD, ip, device));
Set<IpPrefix> result = getCurrentIps(session, device);
return result.contains(ip);
executeCommand(session, String.format(IP_ADDR_ADD, ip.cidr(), device));
Set<IpAddress> result = getCurrentIps(session, device);
return result.contains(ip.ip());
}
/**
......@@ -90,13 +92,13 @@ public final class RemoteIpCommandUtil {
* @param device device name
* @return true if the command succeeds, or false
*/
public static boolean deleteIp(Session session, IpPrefix ip, String device) {
public static boolean deleteIp(Session session, IpAddress ip, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_ADDR_DELETE, ip, device));
Set<IpPrefix> result = getCurrentIps(session, device);
Set<IpAddress> result = getCurrentIps(session, device);
return !result.contains(ip);
}
......@@ -123,16 +125,16 @@ public final class RemoteIpCommandUtil {
* @param device device name
* @return set of IP prefix or empty set
*/
public static Set<IpPrefix> getCurrentIps(Session session, String device) {
public static Set<IpAddress> getCurrentIps(Session session, String device) {
if (session == null || !session.isConnected()) {
return Sets.newHashSet();
}
String output = executeCommand(session, String.format(IP_ADDR_SHOW, device));
Set<IpPrefix> result = Pattern.compile(" ")
Set<IpAddress> result = Pattern.compile(" |/")
.splitAsStream(output)
.filter(s -> s.matches(IP_PATTERN))
.map(IpPrefix::valueOf)
.map(IpAddress::valueOf)
.collect(Collectors.toSet());
return result;
......
/*
* 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.cordvtn.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.CordVtnNodeManager;
import org.onosproject.cordvtn.CordVtnNode;
import org.onosproject.net.DeviceId;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Adds a new node to the service.
*/
@Command(scope = "onos", name = "cordvtn-node-add",
description = "Adds a new node to CORD VTN service")
public class CordVtnNodeAddCommand extends AbstractShellCommand {
@Argument(index = 0, name = "hostname", description = "Hostname",
required = true, multiValued = false)
private String hostname = null;
@Argument(index = 1, name = "ovsdb",
description = "OVSDB server listening address (ip:port)",
required = true, multiValued = false)
private String ovsdb = null;
@Argument(index = 2, name = "bridgeId",
description = "Device ID of integration bridge",
required = true, multiValued = false)
private String bridgeId = null;
@Argument(index = 3, name = "phyPortName",
description = "Physical port name",
required = true, multiValued = false)
private String phyPortName = null;
@Argument(index = 4, name = "localIp",
description = "Local data plane IP address",
required = true, multiValued = false)
private String localIp = null;
@Override
protected void execute() {
checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format");
checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format");
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
String[] ipPort = ovsdb.split(":");
CordVtnNode node = new CordVtnNode(hostname,
IpAddress.valueOf(ipPort[0]),
TpPort.tpPort(Integer.parseInt(ipPort[1])),
DeviceId.deviceId(bridgeId),
phyPortName,
IpAddress.valueOf(localIp));
nodeManager.addNode(node);
}
}
......@@ -34,6 +34,9 @@ import java.util.List;
description = "Lists all nodes registered in CORD VTN service")
public class CordVtnNodeListCommand extends AbstractShellCommand {
private static final String COMPLETE = "COMPLETE";
private static final String INCOMPLETE = "INCOMPLETE";
@Override
protected void execute() {
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
......@@ -44,12 +47,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand {
print("%s", json(nodeManager, nodes));
} else {
for (CordVtnNode node : nodes) {
print("hostname=%s, ovsdb=%s, br-int=%s, phyPort=%s, localIp=%s, init=%s",
print("hostname=%s, hostMgmtIp=%s, dpIp=%s, br-int=%s, dpIntf=%s, init=%s",
node.hostname(),
node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString(),
node.hostMgmtIp().cidr(),
node.dpIp().cidr(),
node.intBrId().toString(),
node.phyPortName(),
node.localIp().toString(),
node.dpIntf(),
getState(nodeManager, node));
}
print("Total %s nodes", nodeManager.getNodeCount());
......@@ -60,19 +63,18 @@ public class CordVtnNodeListCommand extends AbstractShellCommand {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (CordVtnNode node : nodes) {
String ipPort = node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString();
result.add(mapper.createObjectNode()
.put("hostname", node.hostname())
.put("ovsdb", ipPort)
.put("brInt", node.intBrId().toString())
.put("phyPort", node.phyPortName())
.put("localIp", node.localIp().toString())
.put("hostManagementIp", node.hostMgmtIp().cidr())
.put("dataPlaneIp", node.dpIp().cidr())
.put("bridgeId", node.intBrId().toString())
.put("dataPlaneInterface", node.dpIntf())
.put("init", getState(nodeManager, node)));
}
return result;
}
private String getState(CordVtnNodeManager nodeManager, CordVtnNode node) {
return nodeManager.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE";
return nodeManager.isNodeInitComplete(node) ? COMPLETE : INCOMPLETE;
}
}
......
......@@ -20,9 +20,6 @@
<action class="org.onosproject.cordvtn.cli.CordVtnNodeListCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnNodeAddCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnNodeDeleteCommand"/>
</command>
<command>
......