Merge "Fixture updates with connectivity verification methods"

This commit is contained in:
Jenkins 2016-03-01 16:10:34 +00:00 committed by Gerrit Code Review
commit ec4869da92
1 changed files with 234 additions and 5 deletions

View File

@ -14,15 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import operator
import re
from cafe.drivers.unittest.fixtures import BaseTestFixture
from cloudcafe.common.resources import ResourcePool
from cloudcafe.common.tools.datagen import rand_name
from cloudcafe.compute.composites import ComputeComposite
from cloudcafe.compute.extensions.ip_associations_api.composites \
import IPAssociationsComposite
from cloudcafe.compute.extensions.ip_associations_api.models.response \
import IPAssociation
from cloudcafe.networking.networks.common.constants import NeutronResponseCodes
from cloudcafe.networking.networks.common.constants \
import NeutronResponseCodes, ComputeResponseCodes
from cloudcafe.networking.networks.common.models.response.network \
import Network
from cloudcafe.networking.networks.common.models.response.subnet \
@ -785,6 +788,30 @@ class NetworkingSecurityGroupsFixture(NetworkingAPIFixture):
failed_list=cls.failed_secgroups)
cls.delete_secgroups = []
@classmethod
def create_ping_ssh_ingress_rules(cls, sec_group_id, ethertype='IPv4'):
"""SG rules required by the remote clients"""
ingress_ping_rule_req = cls.sec.behaviors.create_security_group_rule(
security_group_id=sec_group_id, direction='ingress',
ethertype=ethertype, protocol='icmp')
ingress_ping_rule = ingress_ping_rule_req.response.entity
cls.delete_secgroups_rules.append(ingress_ping_rule.id)
# ICMP requires an egress rule too for the Ping reply to be sent
egress_ping_rule_req = cls.sec.behaviors.create_security_group_rule(
security_group_id=sec_group_id, direction='egress',
ethertype=ethertype, protocol='icmp')
egress_ping_rule = egress_ping_rule_req.response.entity
cls.delete_secgroups_rules.append(egress_ping_rule.id)
ingress_ssh_rule_req = cls.sec.behaviors.create_security_group_rule(
security_group_id=sec_group_id, direction='ingress',
ethertype=ethertype, protocol='tcp', port_range_min=22,
port_range_max=22)
ingress_ssh_rule = ingress_ssh_rule_req.response.entity
cls.delete_secgroups_rules.append(ingress_ssh_rule.id)
def create_test_secgroup(self, expected_secgroup=None, delete=True):
"""
@summary: creating a test security group
@ -967,6 +994,7 @@ class NetworkingComputeFixture(NetworkingSecurityGroupsFixture):
cls.delete_servers = []
cls.failed_servers = []
cls.delete_keypairs = []
# Using the serversCleanup method
cls.addClassCleanup(cls.serversCleanUp)
@ -992,18 +1020,219 @@ class NetworkingComputeFixture(NetworkingSecurityGroupsFixture):
cls.delete_servers = []
cls.failed_servers = []
if cls.delete_keypairs:
cls.fixture_log.info('Deleting Keypairs...')
for key_name in cls.delete_keypairs:
cls.keypairs.client.delete_keypair(key_name)
@classmethod
def create_test_server(cls, name=None, scheduler_hints=None,
network_ids=None, port_ids=None,
active_server=True):
def create_test_server(cls, name=None, key_name=None,
scheduler_hints=None, network_ids=None,
port_ids=None, active_server=True):
resp = cls.net.behaviors.create_networking_server(
name=name, scheduler_hints=scheduler_hints,
name=name, key_name=key_name, scheduler_hints=scheduler_hints,
network_ids=network_ids, port_ids=port_ids,
active_server=active_server)
server = resp.entity
cls.delete_servers.append(server.id)
return server
@classmethod
def create_keypair(cls, name):
# Using rand_name to avoid HTTP 409 Conflict due to duplicate names
name = rand_name(name)
resp = cls.keypairs.client.create_keypair(name)
msg = ('Unable to create server keypair: received HTTP {0} instead of '
'the expected HTTP {1} response').format(
resp.status_code, ComputeResponseCodes.CREATE_KEYPAIR)
assert resp.status_code == ComputeResponseCodes.CREATE_KEYPAIR, msg
return resp.entity
def verify_remote_client_auth(self, server, remote_client,
sec_group=None):
msg = ('Remote client unable to authenticate for server {0} {1} '
'with security group: {2}').format(server.name, server.id,
sec_group)
self.assertTrue(remote_client.can_authenticate(), msg)
def verify_ping(self, remote_client, ip_address, ip_version=4,
count=3, accepted_packet_loss=0):
ping_packet_loss_regex = '(\d{1,3})\.?\d*\%.*loss'
if ip_version == 6:
ping_cmd = 'ping6 -c {0} {1}'.format(count, ip_address)
else:
ping_cmd = 'ping -c {0} {1}'.format(count, ip_address)
resp = remote_client.ssh_client.execute_command(ping_cmd)
loss_pct_search = re.search(ping_packet_loss_regex, resp.stdout)
if loss_pct_search is None:
smsg = ('Ping from {0} to {1} got unexpected output:\n{2}'
'').format(remote_client.ip_address, ip_address, resp)
self.fail(smsg)
loss_pct = loss_pct_search.group(0)
index = loss_pct.find('%')
loss_pct_num = int(loss_pct[:index])
if loss_pct_num > accepted_packet_loss:
msg = ('Ping from {0} to {1} got unexpected packet loss of '
'{2}% instead of the expected {3}%').format(
remote_client.ip_address, ip_address,
loss_pct_num, accepted_packet_loss)
self.fail(msg)
def verify_udp_connectivity(self, listener_client, sender_client,
listener_ip, port, file_content,
expected_data, ip_version=4):
"""
@summary: Verify UDP port connectivity between two servers
@param listener_client: remote client server that receives TCP packages
@type listener_client: cloudcafe.compute.common.clients.
remote_instance.linux.linux_client.LinuxClient
@param sender_client: remote client server that sends TCP packages
@type sender_client: cloudcafe.compute.common.clients.
remote_instance.linux.linux_client.LinuxClient
@param listener_ip: public, service or isolated network IP
@type listener_ip: str
@param port: open port on listener
@type port: str
@param file_content: file content, for ex. Security Groups UDP testing
@type file_content: str
@param expected_data: transmited file content, for ex.
'XXXXXXXSecurity Groups UDP testing'
@type expected_data: str
"""
file_name = 'udp_transfer'
# Can be set as the default_file_path property in the config
# file servers section, or to be set to /root by default
dir_path = self.servers.config.default_file_path or '/root'
file_path = '/{0}/{1}'.format(dir_path, file_name)
# Deleting the file if it exists
if sender_client.is_file_present(file_path=file_path):
sender_client.delete_file(file_path=file_path)
if listener_client.is_file_present(file_path=file_path):
listener_client.delete_file(file_path=file_path)
# Listener and sender commands
if ip_version == 6:
lnc_cmd = 'nc -6 -u -l {0} > {1}'.format(port, file_name)
snc_cmd = 'nc -6 -u -n -v {0} {1} -w 3 < {2}'.format(listener_ip,
port,
file_name)
else:
lnc_cmd = 'nc -u -l {0} > {1}'.format(port, file_name)
snc_cmd = 'nc -u -n -v {0} {1} -w 3 < {2}'.format(listener_ip,
port,
file_name)
# Creating the file to transfer for UDP testing
sender_client.create_file(file_name=file_name,
file_content=file_content,
file_path=dir_path)
file_created = sender_client.is_file_present(file_path=file_path)
fcmsg = 'Unable to create remote file {0} at {1} sender server'.format(
file_path, sender_client.ip_address)
self.assertTrue(file_created, fcmsg)
# Opening listener port to receive file contents
set_listener = listener_client.ssh_client.execute_shell_command(
lnc_cmd)
listener_ok = lnc_cmd in set_listener.stdout
lkmsg = ('Unexpected shell command output:\n{0}\nRunning command:'
' {1}\nAt listener server: {2}\n').format(
set_listener, lnc_cmd, listener_client.ip_address)
self.assertTrue(listener_ok, lkmsg)
# Transmitting file
t = sender_client.ssh_client.execute_command(snc_cmd)
t_ok = (listener_ip in t.stderr and port in t.stderr and
'succeeded!' in t.stderr)
tkmsg = ('Unexpected shell command output:\n{0}\nRunning command:'
' {1}\nAt sender server: {2}\n').format(
t, snc_cmd, sender_client.ip_address)
self.assertTrue(t_ok, tkmsg)
# Checking file was created by running the listener command
fp = listener_client.is_file_present(file_path=file_path)
fpmsg = 'File {0} missing at listener server {1}'.format(
file_path, listener_client.ip_address)
self.assertTrue(fp, fpmsg)
# Getting the file contents in the listener
fd = listener_client.get_file_details(file_path=file_path)
fdmsg = ('Unexpected data: {0} \ninstead of the expected: {1} \n'
'at listener server {2} on port {3}').format(
fd.content, expected_data, listener_client.ip_address,
port)
self.assertEqual(fd.content, expected_data, fdmsg)
def verify_tcp_connectivity(self, listener_client, sender_client,
listener_ip, port1, port2, port_range,
expected_data, ip_version=4):
"""
@summary: Verify TCP port connectivity between two servers
@param listener_client: remote client server that receives TCP packages
@type listener_client: cloudcafe.compute.common.clients.
remote_instance.linux.linux_client.LinuxClient
@param sender_client: remote client server that sends TCP packages
@type sender_client: cloudcafe.compute.common.clients.
remote_instance.linux.linux_client.LinuxClient
@param listener_ip: public, service or isolated network IP
@type listener_ip: str
@param port1: open port on listener
@type port1: str
@param port2: open port on listener
@type port2: str
@param port_range: ports to check on listener from sender
@type port_range: str
@param expected_data: stdout from port check by sender, for ex.
['442 (tcp) timed out: Operation now in progress',
'443 port [tcp/*] succeeded!',
'444 port [tcp/*] succeeded!',
'445 (tcp) failed: Connection refused']
@type expected_data: list
"""
if ip_version == 6:
# Security group rule has default ports 992-995
lnc_cmd = 'nc -6 -l {0} & nc -6 -l {1} &'.format(port1, port2)
snc_cmd = 'nc -z -n -v -6 {0} {1} -w 2'.format(
listener_ip, port_range)
else:
# Security group rule has default ports 443-445
lnc_cmd = 'nc -l {0} & nc -l {1} &'.format(port1, port2)
snc_cmd = 'nc -z -n -v {0} {1} -w 2'.format(listener_ip,
port_range)
set_listener = listener_client.ssh_client.execute_shell_command(
lnc_cmd)
listener_ok = lnc_cmd in set_listener.stdout
msg = ('Unexpected shell command output:\n{0}\nRunning command:'
' {1}\nAt server: {2}\n').format(set_listener, lnc_cmd,
listener_client.ip_address)
self.assertTrue(listener_ok, msg)
check_ports = sender_client.ssh_client.execute_command(snc_cmd)
for data in expected_data:
verify_data = data in check_ports.stderr
msg = ('Running at {listener_ip} listener command: {lnc_cmd}\n'
'Running at {sender_ip} sender command: {snc_cmd}\n'
'Received unexpected response:\n{response}\n'
'Without the expected data:\n{exp_response}\n'
'').format(listener_ip=listener_client.ip_address,
lnc_cmd=lnc_cmd,
sender_ip=sender_client.ip_address,
snc_cmd=snc_cmd, response=check_ports,
exp_response=expected_data)
self.assertTrue(verify_data, msg)
def assertServerNetworkByName(self, server, network_name, ipv4=True,
ipv6=False, ipv4_cidr=None, ipv6_cidr=None):
"""