Add test_sriov_instance_connectivity

+Add corresponding test
+Add _create_port
+Add _cleanup_ports
+Add sriov deployment tag if computes with SR-IOV enabled interface
are present and unit-tests for ostf-adapter
+Add sriov_enabled physnets to cluster config

Change-Id: I487c0dc0f4756b893af5d5c59ea85ba0d47faa5c
Closes-Bug: #1566906
Implements: blueprint test-sriov-support
This commit is contained in:
Volodymyr Shypyguzov 2016-04-06 17:56:37 +03:00
parent c3499188a1
commit dee7b92c2e
7 changed files with 235 additions and 14 deletions

View File

@ -719,8 +719,8 @@ class NailgunConfig(object):
compute_nodes = filter(lambda node: 'compute' in node['roles'], compute_nodes = filter(lambda node: 'compute' in node['roles'],
data) data)
online_computes = filter( online_computes = filter(
lambda node: 'compute' in node['roles'] lambda node: 'compute' in node['roles'] and
and node['online'] is True, data) node['online'] is True, data)
online_computes_ips = [] online_computes_ips = []
for node in online_computes: for node in online_computes:
online_computes_ips.append(node['ip']) online_computes_ips.append(node['ip'])
@ -730,14 +730,25 @@ class NailgunConfig(object):
for node in compute_nodes: for node in compute_nodes:
compute_ips.append(node['ip']) compute_ips.append(node['ip'])
LOG.info("COMPUTES IPS %s" % compute_ips) LOG.info("COMPUTES IPS %s" % compute_ips)
sriov_physnets = []
compute_ids = [node['id'] for node in online_computes]
for compute_id in compute_ids:
api_url = '/api/nodes/{}/interfaces'.format(compute_id)
ifaces_resp = self.req_session.get(
self.nailgun_url + api_url).json()
for iface in ifaces_resp:
if iface['interface_properties']['sriov']['enabled']:
sriov_physnets.append(
iface['interface_properties']['sriov']['physnet'])
self.compute.sriov_physnets = sriov_physnets
self.compute.compute_nodes = compute_ips self.compute.compute_nodes = compute_ips
ceph_nodes = filter(lambda node: 'ceph-osd' in node['roles'], ceph_nodes = filter(lambda node: 'ceph-osd' in node['roles'],
data) data)
self.compute.ceph_nodes = ceph_nodes self.compute.ceph_nodes = ceph_nodes
online_ironic = filter( online_ironic = filter(
lambda node: 'ironic' in node['roles'] lambda node: 'ironic' in node['roles'] and
and node['online'] is True, data) node['online'] is True, data)
self.ironic.online_conductors = [] self.ironic.online_conductors = []
for node in online_ironic: for node in online_ironic:
self.ironic.online_conductors.append(node['ip']) self.ironic.online_conductors.append(node['ip'])

View File

@ -31,6 +31,7 @@ class NeutronBaseTest(fuel_health.nmanager.NovaNetworkScenarioTest):
cls.networks = [] cls.networks = []
cls.floating_ips = [] cls.floating_ips = []
cls.security_groups = {} cls.security_groups = {}
cls.ports = []
def setUp(self): def setUp(self):
super(NeutronBaseTest, self).setUp() super(NeutronBaseTest, self).setUp()
@ -172,8 +173,18 @@ class NeutronBaseTest(fuel_health.nmanager.NovaNetworkScenarioTest):
cls.error_msg.append(exc) cls.error_msg.append(exc)
LOG.debug(traceback.format_exc()) LOG.debug(traceback.format_exc())
@classmethod
def _cleanup_ports(cls):
for port in cls.ports:
try:
cls.neutron_client.delete_port(port['port']['id'])
except Exception as exc:
cls.error_msg.append(exc)
LOG.debug(traceback.format_exc())
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
super(NeutronBaseTest, cls) super(NeutronBaseTest, cls)
cls._clean_floating_ips() cls._clean_floating_ips()
cls._clear_networks() cls._clear_networks()
cls._cleanup_ports()

View File

@ -569,6 +569,7 @@ class NovaNetworkScenarioTest(OfficialClientTest):
cls.error_msg = [] cls.error_msg = []
cls.flavors = [] cls.flavors = []
cls.images = [] cls.images = []
cls.ports = []
cls.private_net = cls.config.network.private_net cls.private_net = cls.config.network.private_net
def setUp(self): def setUp(self):
@ -654,6 +655,22 @@ class NovaNetworkScenarioTest(OfficialClientTest):
"Network creation failed") "Network creation failed")
return networks return networks
def _create_port(self, net_id, vnic_type, label='ost1_test-port-'):
n_label = rand_name(label)
port_data = {
'name': n_label,
'binding:vnic_type': vnic_type,
'network_id': net_id,
}
port = self.neutron_client.create_port({'port': port_data})
self.set_resource(n_label, port)
self.ports.append(port)
LOG.debug(port)
self.verify_response_body_content(port['port']['name'],
n_label,
"Port creation failed")
return port
@classmethod @classmethod
def _clear_networks(cls): def _clear_networks(cls):
try: try:
@ -680,7 +697,8 @@ class NovaNetworkScenarioTest(OfficialClientTest):
def _create_server(self, client, name, security_groups=None, def _create_server(self, client, name, security_groups=None,
flavor_id=None, net_id=None, img_name=None, flavor_id=None, net_id=None, img_name=None,
data_file=None, az_name=None): data_file=None, az_name=None, port=None):
create_kwargs = {}
if img_name: if img_name:
base_image_id = self.get_image_from_name(img_name=img_name) base_image_id = self.get_image_from_name(img_name=img_name)
@ -702,6 +720,7 @@ class NovaNetworkScenarioTest(OfficialClientTest):
security_groups = [self._create_security_group( security_groups = [self._create_security_group(
self.compute_client).name] self.compute_client).name]
if 'neutron' in self.config.network.network_provider: if 'neutron' in self.config.network.network_provider:
create_kwargs['nics'] = []
if net_id: if net_id:
network = [net_id] network = [net_id]
else: else:
@ -709,15 +728,17 @@ class NovaNetworkScenarioTest(OfficialClientTest):
self.compute_client.networks.list() self.compute_client.networks.list()
if net.label == self.private_net] if net.label == self.private_net]
if network: if port:
create_kwargs = {'nics': [{'net-id': network[0]}], create_kwargs['nics'].append({'port-id': port['port']['id']})
'security_groups': security_groups}
else: else:
self.fail("Default private network '{0}' isn't present. " if network:
"Please verify it is properly created.". create_kwargs['nics'].append({'net-id': network[0]})
format(self.private_net)) else:
else: self.fail("Default private network '{0}' isn't present. "
create_kwargs = {'security_groups': security_groups} "Please verify it is properly created.".
format(self.private_net))
create_kwargs['security_groups'] = security_groups
server = client.servers.create(name, base_image_id, server = client.servers.create(name, base_image_id,
flavor_id, files=data_file, flavor_id, files=data_file,

View File

@ -144,3 +144,99 @@ class TestNeutron(neutronmanager.NeutronBaseTest):
"Subnet deletion", subnet) "Subnet deletion", subnet)
self.verify(20, self._remove_network, 16, self.verify(20, self._remove_network, 16,
"Network can not be deleted", "Network deletion", network) "Network can not be deleted", "Network deletion", network)
def test_check_sriov_instance_connectivity(self):
"""Check network connectivity from SRIOV instance via floating IP
Target component: Neutron
Scenario:
1. Create a new security group (if it doesn't exist yet).
2. Create SR-IOV port
3. Create an instance using new security group and SR-IOV port.
4. Create new floating IP
5. Assign created floating IP to the instance.
6. Check connectivity to the floating IP using ping command.
7. Check that public IP 8.8.8.8 can be pinged from instance.
8. Disassociate server floating ip.
9. Delete floating ip
10. Delete server.
11. Delete SR-IOV port
Duration: 300 s.
Deployment tags: sriov
"""
if 'physnet2' not in self.config.compute.sriov_physnets:
self.skipTest('physnet2 is not configured for any interface')
self.check_image_exists()
if not self.security_groups:
self.security_groups[self.tenant_id] = self.verify(
25, self._create_security_group, 1,
"Security group can not be created.",
'security group creation',
self.compute_client)
name = rand_name('ost1_test-server-sriov-')
security_groups = [self.security_groups[self.tenant_id].name]
network = [net.id for net in
self.compute_client.networks.list()
if net.label == self.private_net]
port = self.verify(
20,
self._create_port,
2,
"SRIOV port can not be created.",
'SRIOV port creation',
net_id=network[0], vnic_type='direct')
server = self.verify(250, self._create_server, 3,
"Server can not be created.",
"server creation",
self.compute_client, name, security_groups,
port=port, net_id=network[0])
floating_ip = self.verify(
20,
self._create_floating_ip,
4,
"Floating IP can not be created.",
'floating IP creation')
self.verify(20, self._assign_floating_ip_to_instance,
5, "Floating IP can not be assigned.",
'floating IP assignment',
self.compute_client, server, floating_ip)
self.floating_ips.append(floating_ip)
ip_address = floating_ip.ip
LOG.info('is address is {0}'.format(ip_address))
LOG.debug(ip_address)
self.verify(600, self._check_vm_connectivity, 6,
"VM connectivity doesn`t function properly.",
'VM connectivity checking', ip_address,
30, (5, 10))
self.verify(600, self._check_connectivity_from_vm,
7, ("Connectivity to 8.8.8.8 from the VM doesn`t "
"function properly."),
'public connectivity checking from VM', ip_address,
30, (5, 10))
self.verify(20, self.compute_client.servers.remove_floating_ip,
8, "Floating IP cannot be removed.",
"removing floating IP", server, floating_ip)
self.verify(20, self.compute_client.floating_ips.delete,
9, "Floating IP cannot be deleted.",
"floating IP deletion", floating_ip)
self.verify(30, self._delete_server, 10,
"Server can not be deleted. ",
"server deletion", server)
self.verify(30, self.neutron_client.delete_port, 11,
"Port can not be deleted. ",
"port deletion", port['port']['id'])

View File

@ -160,7 +160,21 @@ def _get_cluster_attrs(cluster_id, token=None):
enable_without_ceph = filter(lambda node: 'ceph-osd' in node['roles'], enable_without_ceph = filter(lambda node: 'ceph-osd' in node['roles'],
nodes_response) nodes_response)
sriov_compute_ids = []
compute_ids = [node['id'] for node in nodes_response
if "compute" in node['roles']]
for compute_id in compute_ids:
ifaces_url = URL.format(
cfg.CONF.adapter.nailgun_host, cfg.CONF.adapter.nailgun_port,
'api/nodes/{id}/interfaces'.format(id=compute_id))
ifaces_resp = REQ_SES.get(ifaces_url).json()
for iface in ifaces_resp:
if iface['interface_properties']['sriov']['enabled']:
sriov_compute_ids.append(compute_id)
deployment_tags = set() deployment_tags = set()
if sriov_compute_ids:
deployment_tags.add('sriov')
if not enable_without_ceph: if not enable_without_ceph:
deployment_tags.add('enable_without_ceph') deployment_tags.add('enable_without_ceph')

View File

@ -147,7 +147,47 @@ CLUSTERS = {
'common': {} 'common': {}
} }
} }
} },
7: {
'cluster_meta': {
'release_id': 7,
'mode': 'ha'
},
'release_data': {
'operating_system': 'rhel',
'version': '2015.2-1.0',
},
'cluster_node': [
{
"hostname": "node-1",
'id': "1",
'roles': "compute"
},
],
'node_interfaces': [
{
'interface_properties': {
'sriov': {
'enabled': 'true'
}
}
}
],
'cluster_attributes': {
'editable': {
'additional_components': {
'murano': {
'value': True
},
'sahara': {
'value': False
}
},
'common': {}
}
}
},
} }

View File

@ -49,3 +49,31 @@ class TestDeplTagsGetter(base.BaseUnitTest):
res = mixins._get_cluster_attrs(expected['cluster_id']) res = mixins._get_cluster_attrs(expected['cluster_id'])
self.assertEqual(res, expected['attrs']) self.assertEqual(res, expected['attrs'])
def test_sriov_deployment_tag(self):
expected = {
'cluster_id': 7,
'attrs': {
'deployment_tags': set(
['ha', 'rhel', 'additional_components',
'murano', 'nova_network', 'public_on_all_nodes',
'enable_without_ceph', 'sriov']),
'release_version': '2015.2-1.0'
}
}
with requests_mock.Mocker() as m:
cluster = base.CLUSTERS[expected['cluster_id']]
m.register_uri('GET', '/api/clusters/7',
json=cluster['cluster_meta'])
m.register_uri('GET', '/api/clusters/7/attributes',
json=cluster['cluster_attributes'])
m.register_uri('GET', '/api/releases/7',
json=cluster['release_data'])
m.register_uri('GET', '/api/nodes?cluster_id=7',
json=cluster['cluster_node'])
m.register_uri('GET', '/api/nodes/1/interfaces',
json=cluster['node_interfaces'])
res = mixins._get_cluster_attrs(expected['cluster_id'])
self.assertEqual(res, expected['attrs'])