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:
parent
c3499188a1
commit
dee7b92c2e
|
@ -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'])
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
|
@ -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')
|
||||||
|
|
||||||
|
|
|
@ -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': {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
Loading…
Reference in New Issue