fuel-plugin-contrail/plugin_test/vapor/vapor/helpers/connectivity.py

159 lines
5.6 KiB
Python

# 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.
import contextlib
import time
from hamcrest import assert_that, is_, greater_than, has_value
from stepler.third_party import ping
from stepler.third_party import tcpdump
from stepler.third_party import waiter
CONNECTED = 'CONNECTED'
def check_connection_status(ip,
remote,
port=22,
udp=False,
answer=CONNECTED,
must_available=True,
timeout=0):
"""Check TCP/UDP port connection availability (or not).
Note:
This method doesn't work on ubuntu-based servers due another `nc`
variant.
UDP checking requires an server on remote side. Simple server example:
```while true; do nc -u -l -p 1235 -e echo Reply; done```
Args:
ip (str): IP address to check connectivity to.
remote (obj): Connected instance of
'stepler.third_party.ssh.SshClient'.
port (int, optional): Port to check.
udp (bool, optional): Check UDP instead of TCP
must_available (bool, optional): Flag whether port should be available
or not.
timeout (int, optional): Time in seconds to wait expected port
condition.
"""
proto_flag = ''
if udp:
proto_flag = '-u'
def _predicate():
result = remote.execute(
'echo "" | nc {proto} -w1 {ip} {port} | grep {answer}'.format(
ip=ip, port=port, proto=proto_flag, answer=answer))
msg = ("Expected that {proto} connection for {port}"
" will be {status}").format(
proto='UDP' if udp else 'TCP',
port=port,
status='available' if must_available else 'unavailable')
return waiter.expect_that(result.exit_code == 0,
is_(must_available), msg)
return waiter.wait(_predicate, timeout_seconds=timeout, sleep_seconds=2)
def check_icmp_connection_status(ip, remote, must_available=True, timeout=0):
"""Check that icmp connection to ip is `must_available`."""
def predicate():
ping_result = ping.Pinger(ip, remote=remote).ping(count=3)
if must_available:
value = ping_result.loss
else:
value = ping_result.received
return waiter.expect_that(value, is_(0))
return waiter.wait(predicate, timeout_seconds=timeout)
def start_port_listener(server_ssh,
port,
udp=False,
answer=CONNECTED,
socat=False):
"""Start background netcat listener on remote server.
Note:
Netcat call syntax is valid only for cirros. For ubuntu use socat.
"""
if socat:
if not server_ssh.execute('which socat').is_ok:
raise RuntimeError('socat is not installed on remote server')
proto = 'UDP4' if udp else 'TCP4'
cmd = "socat {proto}-LISTEN:{port},fork EXEC:'echo {answer}'".format(
proto=proto, port=port, answer=answer)
else:
proto = '-u' if udp else ''
listener_cmd = 'nc {proto} -l -p {port} -e echo "{answer}"'.format(
proto=proto, port=port, answer=answer)
cmd = "while true; do {}; done".format(listener_cmd)
server_ssh.background_call(cmd)
@contextlib.contextmanager
def calc_packets_count(os_faults_steps, nodes, iface, filters,
max_packets=10000):
"""CM to calc packages count on nodes' iface.
Returns dict: fqdn -> captured packets count.
"""
tcpdump_base_path = os_faults_steps.start_tcpdump(
nodes, '-i {0} {1} -c {2}'.format(iface, filters, max_packets))
result = {node.fqdn: 0 for node in nodes}
yield result
os_faults_steps.stop_tcpdump(nodes, tcpdump_base_path)
for fqdn, pcap in os_faults_steps.download_tcpdump_results(
nodes, tcpdump_base_path).items():
packets = list(tcpdump.read_pcap(pcap))
result[fqdn] = len(packets)
def start_iperf_pair(client_ssh, server_ssh, ip, port, udp=False, timeout=10):
"""Start iperf client/server."""
if not server_ssh.execute('which iperf').is_ok:
raise RuntimeError('iperf is not installed on server')
if not client_ssh.execute('which iperf').is_ok:
raise RuntimeError('iperf is not installed on server')
proto = '-u' if udp else ''
server_cmd = "iperf {proto} -s -p {port}"
client_cmd = "iperf {proto} -c {ip} -p {port} -t {time}"
server_ssh.background_call(server_cmd.format(proto=proto, port=port))
# if not udp:
time.sleep(10)
client_ssh.background_call(
client_cmd.format(proto=proto, ip=ip, port=port, time=timeout))
def check_packets_on_iface(os_faults_steps, node, iface, filters,
should_be=True):
with calc_packets_count(os_faults_steps, node, iface,
filters) as tcp_counts:
time.sleep(1)
if should_be:
matcher = greater_than(0)
else:
matcher = is_(0)
assert_that(tcp_counts, has_value(matcher), 'Wrong packets count')