[ONOS-7752] check single VM-to-VM east-west reachability

Change-Id: I0f27cefb1c70a0b05c4e71e156d81bc041c1d885
This commit is contained in:
Jian Li 2018-08-08 15:55:08 +09:00
parent 78d3ed3727
commit e189c1c261
7 changed files with 152 additions and 25 deletions

View File

@ -2,6 +2,7 @@ COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:org.apache.karaf.shell.console',
'//cli:onos-cli',
'//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
]
TEST_DEPS = [

View File

@ -1,4 +1,6 @@
COMPILE_DEPS = CORE_DEPS + CLI
COMPILE_DEPS = CORE_DEPS + CLI + [
"//apps/openstacknetworking/api:onos-apps-openstacknetworking-api",
]
TEST_DEPS = TEST_ADAPTERS + [
"//core/api:onos-api-tests",

View File

@ -16,6 +16,7 @@
package org.onosproject.openstacktroubleshoot.api;
import org.onlab.packet.IpAddress;
import org.onosproject.openstacknetworking.api.InstancePort;
import java.util.Map;
@ -34,14 +35,12 @@ public interface OpenstackTroubleshootService {
/**
* Checks a single VM-to-Vm connectivity.
*
* @param srcNetId source network ID
* @param srcIp source IP address
* @param dstNetId destination network ID
* @param dstIp destination IP address
* @param srcInstancePort source instance port
* @param dstInstancePort destination instance port
* @return reachability
*/
Reachability probeEastWest(String srcNetId, IpAddress srcIp,
String dstNetId, IpAddress dstIp);
Reachability probeEastWest(InstancePort srcInstancePort,
InstancePort dstInstancePort);
/**
* Checks all north-south router to VMs' connectivity.

View File

@ -0,0 +1,48 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* 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.openstacktroubleshoot.cli;
import org.apache.karaf.shell.console.Completer;
import org.apache.karaf.shell.console.completer.StringsCompleter;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.openstacknetworking.api.InstancePort;
import org.onosproject.openstacknetworking.api.InstancePortService;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.stream.Collectors;
/**
* Active VM IP address completer.
*/
public class ActiveVmIpCompleter implements Completer {
@Override
public int complete(String buffer, int cursor, List<String> candidates) {
StringsCompleter delegate = new StringsCompleter();
InstancePortService service = AbstractShellCommand.get(InstancePortService.class);
Set<String> set = service.instancePorts().stream()
.filter(p -> p.state() == InstancePort.State.ACTIVE)
.map(p -> p.ipAddress().getIp4Address().toString())
.collect(Collectors.toSet());
SortedSet<String> strings = delegate.getStrings();
strings.addAll(set);
return delegate.complete(buffer, cursor, candidates);
}
}

View File

@ -15,12 +15,21 @@
*/
package org.onosproject.openstacktroubleshoot.cli;
import com.google.common.collect.Sets;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onlab.packet.IpAddress;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.openstacknetworking.api.InstancePort;
import org.onosproject.openstacknetworking.api.InstancePortService;
import org.onosproject.openstacktroubleshoot.api.OpenstackTroubleshootService;
import org.onosproject.openstacktroubleshoot.api.Reachability;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Checks the east-west VMs connectivity.
@ -35,23 +44,90 @@ public class OpenstackEastWestProbeCommand extends AbstractShellCommand {
private static final String FORMAT = "%-20s%-5s%-20s%-20s";
@Option(name = "-a", aliases = "--all", description = "Apply this command to all VMs",
required = false, multiValued = false)
private boolean isAll = false;
@Argument(index = 0, name = "vmIps", description = "VMs' IP addresses",
required = false, multiValued = true)
private String[] vmIps = null;
@Override
protected void execute() {
OpenstackTroubleshootService troubleshootService =
AbstractShellCommand.get(OpenstackTroubleshootService.class);
OpenstackTroubleshootService tsService =
get(OpenstackTroubleshootService.class);
if (troubleshootService == null) {
InstancePortService instPortService =
get(InstancePortService.class);
if (tsService == null) {
error("Failed to troubleshoot openstack networking.");
return;
}
if ((!isAll && vmIps == null) || (isAll && vmIps != null)) {
print("Please specify one of VM IP address or -a option.");
return;
}
if (isAll) {
printHeader();
Map<String, Reachability> map = tsService.probeEastWestBulk();
map.values().forEach(this::printReachability);
} else {
if (vmIps.length > 2) {
print("Too many VM IPs. The number of IP should be limited to 2.");
return;
}
IpAddress srcIp = IpAddress.valueOf(vmIps[0]);
InstancePort srcPort = instPort(instPortService, srcIp);
if (srcPort == null) {
print("Specified source IP is not existing.");
return;
}
final Set<IpAddress> dstIps = Sets.newConcurrentHashSet();
if (vmIps.length == 2) {
dstIps.add(IpAddress.valueOf(vmIps[1]));
}
if (vmIps.length == 1) {
dstIps.addAll(instPortService.instancePorts().stream()
.filter(p -> !p.ipAddress().equals(srcIp))
.filter(p -> p.state().equals(InstancePort.State.ACTIVE))
.map(InstancePort::ipAddress)
.collect(Collectors.toSet()));
}
printHeader();
dstIps.stream()
.filter(ip -> instPort(instPortService, ip) != null)
.map(ip -> instPort(instPortService, ip))
.forEach(port -> printReachability(tsService.probeEastWest(srcPort, port)));
}
}
private InstancePort instPort(InstancePortService service, IpAddress ip) {
Optional<InstancePort> port = service.instancePorts().stream()
.filter(p -> p.ipAddress().equals(ip)).findFirst();
if (port.isPresent()) {
return port.get();
} else {
print("Specified destination IP is not existing.");
return null;
}
}
private void printHeader() {
print(FORMAT, "Source IP", "", "Destination IP", "Reachability");
}
Map<String, Reachability> map = troubleshootService.probeEastWestBulk();
map.values().forEach(r -> {
String result = r.isReachable() ? REACHABLE : UNREACHABLE;
print(FORMAT, r.srcIp().toString(), ARROW, r.dstIp().toString(), result);
});
private void printReachability(Reachability r) {
String result = r.isReachable() ? REACHABLE : UNREACHABLE;
print(FORMAT, r.srcIp().toString(), ARROW, r.dstIp().toString(), result);
}
}

View File

@ -257,21 +257,17 @@ public class OpenstackTroubleshootManager implements OpenstackTroubleshootServic
}
@Override
public Reachability probeEastWest(String srcNetId, IpAddress srcIp,
String dstNetId, IpAddress dstIp) {
public Reachability probeEastWest(InstancePort srcPort, InstancePort dstPort) {
Reachability.Builder rBuilder = DefaultReachability.builder()
.srcIp(srcIp)
.dstIp(dstIp);
.srcIp(srcPort.ipAddress())
.dstIp(dstPort.ipAddress());
if (srcIp.equals(dstIp)) {
if (srcPort.equals(dstPort)) {
// self probing should always return true
rBuilder.isReachable(true);
return rBuilder.build();
} else {
InstancePort srcPort = instancePortService.instancePort(srcIp, srcNetId);
InstancePort dstPort = instancePortService.instancePort(dstIp, dstNetId);
if (srcPort.state() == ACTIVE && dstPort.state() == ACTIVE) {
// install flow rules to enforce ICMP_REQUEST to be tagged and direct to ACL table

View File

@ -1,5 +1,5 @@
<!--
~ Copyright 2017-present Open Networking Foundation
~ Copyright 2018-present Open Networking Foundation
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@ -17,6 +17,11 @@
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.openstacktroubleshoot.cli.OpenstackEastWestProbeCommand"/>
<completers>
<ref component-id="activeVmIpCompleter"/>
</completers>
</command>
</command-bundle>
<bean id="activeVmIpCompleter" class="org.onosproject.openstacktroubleshoot.cli.ActiveVmIpCompleter"/>
</blueprint>