e2058dcbb6
The method 'warm_restart_nodes' needs iterable object to be given as 'devops_nodes' argument. Change-Id: I7971594bf160e90156f920686f644434e0582ec8 Closes-bug: #1582578
433 lines
15 KiB
Python
433 lines
15 KiB
Python
# Copyright 2016 Mirantis, Inc.
|
|
#
|
|
# 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.
|
|
|
|
from copy import deepcopy
|
|
import random
|
|
|
|
from devops.helpers import helpers as devops_helpers
|
|
from proboscis.asserts import assert_raises
|
|
from proboscis.asserts import assert_true
|
|
from proboscis import test
|
|
# pylint: disable=import-error
|
|
from six.moves.urllib.error import HTTPError
|
|
# pylint: enable=import-error
|
|
|
|
from fuelweb_test.helpers.decorators import log_snapshot_after_test
|
|
from fuelweb_test.helpers import os_actions
|
|
from fuelweb_test.tests.base_test_case import SetupEnvironment
|
|
from fuelweb_test.tests.base_test_case import TestBasic
|
|
from fuelweb_test.tests.test_bonding_base import BondingTestDPDK
|
|
from fuelweb_test import logger
|
|
from fuelweb_test import settings
|
|
|
|
|
|
class TestDPDK(TestBasic):
|
|
"""TestDPDK."""
|
|
|
|
tests_requirements = {'KVM_USE': True}
|
|
|
|
def __init__(self):
|
|
super(TestDPDK, self).__init__()
|
|
self.check_settings_requirements()
|
|
|
|
def check_settings_requirements(self):
|
|
bad_params = set()
|
|
for param, value in self.tests_requirements.items():
|
|
if getattr(settings, param) != value:
|
|
bad_params.add('{0}={1}'.format(param, value))
|
|
assert_true(not bad_params,
|
|
'Can not start tests, the following settings are '
|
|
'not set properly: {0}'.format(', '.join(bad_params)))
|
|
|
|
def check_dpdk_instance_connectivity(self, os_conn, cluster_id,
|
|
mem_page_size='2048'):
|
|
"""Boot VM with HugePages and ping it via floating IP
|
|
|
|
:param os_conn: an object of connection to openstack services
|
|
:param cluster_id: an integer number of cluster id
|
|
:param mem_page_size: huge pages size
|
|
:return:
|
|
"""
|
|
|
|
extra_specs = {
|
|
'hw:mem_page_size': mem_page_size
|
|
}
|
|
|
|
net_name = self.fuel_web.get_cluster_predefined_networks_name(
|
|
cluster_id)['private_net']
|
|
flavor_id = random.randint(10, 10000)
|
|
name = 'system_test-{}'.format(random.randint(10, 10000))
|
|
flavor = os_conn.create_flavor(name=name, ram=64,
|
|
vcpus=1, disk=1,
|
|
flavorid=flavor_id,
|
|
extra_specs=extra_specs)
|
|
|
|
server = os_conn.create_server_for_migration(neutron=True,
|
|
label=net_name,
|
|
flavor=flavor_id)
|
|
os_conn.verify_instance_status(server, 'ACTIVE')
|
|
|
|
float_ip = os_conn.assign_floating_ip(server)
|
|
logger.info("Floating address {0} associated with instance {1}"
|
|
.format(float_ip.ip, server.id))
|
|
|
|
logger.info("Wait for ping from instance {} "
|
|
"by floating ip".format(server.id))
|
|
devops_helpers.wait(
|
|
lambda: devops_helpers.tcp_ping(float_ip.ip, 22),
|
|
timeout=300,
|
|
timeout_msg=("Instance {0} is unreachable for {1} seconds".
|
|
format(server.id, 300)))
|
|
|
|
os_conn.delete_instance(server)
|
|
os_conn.delete_flavor(flavor)
|
|
|
|
def setup_hugepages(self, nailgun_node,
|
|
hp_2mb=0, hp_1gb=0, hp_dpdk_mb=0):
|
|
node_attributes = self.fuel_web.client.get_node_attributes(
|
|
nailgun_node['id'])
|
|
node_attributes['hugepages']['nova']['value']['2048'] = hp_2mb
|
|
node_attributes['hugepages']['nova']['value']['1048576'] = hp_1gb
|
|
node_attributes['hugepages']['dpdk']['value'] = hp_dpdk_mb
|
|
self.fuel_web.client.upload_node_attributes(node_attributes,
|
|
nailgun_node['id'])
|
|
|
|
def check_dpdk(self, nailgun_node, net='private'):
|
|
compute_net = self.fuel_web.client.get_node_interfaces(
|
|
nailgun_node['id'])
|
|
dpdk_available = False
|
|
dpdk_enabled = False
|
|
for interface in compute_net:
|
|
if net not in [n['name'] for n in interface['assigned_networks']]:
|
|
continue
|
|
if 'dpdk' not in interface['interface_properties']:
|
|
continue
|
|
|
|
dpdk_available = interface['interface_properties']['dpdk'][
|
|
'available']
|
|
if 'enabled' in interface['interface_properties']['dpdk']:
|
|
dpdk_enabled = interface['interface_properties']['dpdk'][
|
|
'enabled']
|
|
break
|
|
|
|
return {'available': dpdk_available, 'enabled': dpdk_enabled}
|
|
|
|
def enable_dpdk(self, nailgun_node, switch_to=True, net='private',
|
|
forceEnable=False):
|
|
if not forceEnable:
|
|
assert_true(self.check_dpdk(nailgun_node, net=net)['available'],
|
|
'DPDK not available on selected interface')
|
|
|
|
compute_net = self.fuel_web.client.get_node_interfaces(
|
|
nailgun_node['id'])
|
|
for interface in compute_net:
|
|
for ids in interface['assigned_networks']:
|
|
if ids['name'] == net:
|
|
if interface['type'] == 'bond':
|
|
interface['bond_properties']['type__'] = 'dpdkovs'
|
|
interface['interface_properties']['dpdk'].update(
|
|
{'enabled': switch_to})
|
|
else:
|
|
interface['interface_properties']['dpdk'][
|
|
'enabled'] = switch_to
|
|
break
|
|
|
|
self.fuel_web.client.put_node_interfaces(
|
|
[{'id': nailgun_node['id'], 'interfaces': compute_net}])
|
|
|
|
return self.check_dpdk(nailgun_node, net=net)['enabled'] == switch_to
|
|
|
|
|
|
@test(groups=["support_dpdk"])
|
|
class SupportDPDK(TestDPDK):
|
|
"""SupportDPDK."""
|
|
|
|
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
|
|
groups=["deploy_cluster_with_dpdk"])
|
|
@log_snapshot_after_test
|
|
def deploy_cluster_with_dpdk(self):
|
|
"""Deploy cluster with DPDK
|
|
|
|
Scenario:
|
|
1. Create new environment with VLAN segmentation for Neutron
|
|
2. Set KVM as Hypervisor
|
|
3. Add controller and compute nodes
|
|
4. Configure HugePages for compute nodes
|
|
5. Configure private network in DPDK mode
|
|
6. Run network verification
|
|
7. Deploy environment
|
|
8. Run network verification
|
|
9. Run OSTF
|
|
10. Reboot compute
|
|
11. Run OSTF
|
|
12. Run instance on compute with DPDK and check its availability
|
|
via floating IP
|
|
|
|
Snapshot: deploy_cluster_with_dpdk
|
|
|
|
"""
|
|
self.env.revert_snapshot("ready_with_3_slaves")
|
|
|
|
self.show_step(1)
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": "vlan"
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['compute'],
|
|
'slave-03': ['cinder']
|
|
})
|
|
|
|
compute = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
cluster_id, ['compute'], role_status='pending_roles')[0]
|
|
|
|
self.show_step(4)
|
|
self.setup_hugepages(compute, hp_2mb=256, hp_dpdk_mb=128)
|
|
|
|
self.show_step(5)
|
|
self.enable_dpdk(compute)
|
|
|
|
self.show_step(6)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(8)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(9)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
|
|
self.show_step(10)
|
|
# reboot compute
|
|
self.fuel_web.warm_restart_nodes(
|
|
[self.fuel_web.get_devops_node_by_nailgun_node(compute)])
|
|
|
|
# Wait until OpenStack services are UP
|
|
self.fuel_web.assert_os_services_ready(cluster_id)
|
|
|
|
self.show_step(11)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
|
|
self.show_step(12)
|
|
os_conn = os_actions.OpenStackActions(
|
|
self.fuel_web.get_public_vip(cluster_id))
|
|
|
|
self.check_dpdk_instance_connectivity(os_conn, cluster_id)
|
|
|
|
self.env.make_snapshot("deploy_cluster_with_dpdk")
|
|
|
|
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
|
|
groups=["check_can_not_enable_dpdk_with_tun"])
|
|
@log_snapshot_after_test
|
|
def check_can_not_enable_dpdk_with_tun(self):
|
|
"""Check can not enable DPDK on tun network
|
|
|
|
Scenario:
|
|
1. Create new environment with VXLAN segmentation for Neutron
|
|
2. Set KVM as Hypervisor
|
|
3. Add controller and compute nodes
|
|
4. Configure HugePages for compute nodes
|
|
5. Try configure private network in DPDK mode
|
|
"""
|
|
self.env.revert_snapshot("ready_with_3_slaves")
|
|
|
|
self.show_step(1)
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": "tun"
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['compute'],
|
|
'slave-03': ['cinder']
|
|
})
|
|
|
|
compute = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
cluster_id, ['compute'], role_status='pending_roles')[0]
|
|
|
|
self.show_step(4)
|
|
self.setup_hugepages(compute, hp_2mb=256, hp_dpdk_mb=128)
|
|
|
|
self.show_step(5)
|
|
assert_raises(HTTPError, self.enable_dpdk, compute, forceEnable=True)
|
|
|
|
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
|
|
groups=["check_can_not_enable_dpdk_on_non_dedicated_iface"])
|
|
@log_snapshot_after_test
|
|
def check_can_not_enable_dpdk_on_non_dedicated_iface(self):
|
|
"""Check can not enable DPDK on non-dedicated interface
|
|
|
|
Scenario:
|
|
1. Create new environment with VLAN segmentation for Neutron
|
|
2. Set KVM as Hypervisor
|
|
3. Add controller and compute nodes
|
|
4. Configure HugePages for compute nodes
|
|
5. Add private and storage networks to interface
|
|
and try enable DPDK mode
|
|
"""
|
|
self.env.revert_snapshot("ready_with_3_slaves")
|
|
|
|
self.show_step(1)
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": "vlan"
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['compute'],
|
|
'slave-03': ['cinder']
|
|
})
|
|
|
|
compute = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
cluster_id, ['compute'], role_status='pending_roles')[0]
|
|
|
|
self.show_step(4)
|
|
self.setup_hugepages(compute, hp_2mb=256, hp_dpdk_mb=128)
|
|
|
|
self.show_step(5)
|
|
assigned_networks = {
|
|
settings.iface_alias('eth0'): ['fuelweb_admin'],
|
|
settings.iface_alias('eth1'): ['public'],
|
|
settings.iface_alias('eth2'): ['management'],
|
|
settings.iface_alias('eth3'): ['private', 'storage'],
|
|
settings.iface_alias('eth4'): []
|
|
}
|
|
self.fuel_web.update_node_networks(compute['id'],
|
|
interfaces_dict=assigned_networks)
|
|
assert_raises(HTTPError, self.enable_dpdk, compute, forceEnable=True)
|
|
|
|
|
|
@test(groups=["support_dpdk_bond"])
|
|
class SupportDPDKBond(BondingTestDPDK, TestDPDK):
|
|
"""SupportDPDKBond."""
|
|
|
|
def __init__(self):
|
|
self.tests_requirements.update({'BONDING': True})
|
|
super(SupportDPDKBond, self).__init__()
|
|
|
|
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
|
|
groups=["deploy_cluster_with_dpdk_bond"])
|
|
@log_snapshot_after_test
|
|
def deploy_cluster_with_dpdk_bond(self):
|
|
"""Deploy cluster with DPDK, active-backup bonding and Neutron VLAN
|
|
|
|
Scenario:
|
|
1. Create cluster with VLAN for Neutron and KVM
|
|
2. Add 1 node with controller role
|
|
3. Add 2 nodes with compute and cinder roles
|
|
4. Setup bonding for all interfaces: 1 for admin, 1 for private
|
|
and 1 for public/storage/management networks
|
|
5. Configure HugePages for compute nodes
|
|
6. Enable DPDK for bond with private network on all computes
|
|
7. Run network verification
|
|
8. Deploy the cluster
|
|
9. Run network verification
|
|
10. Run OSTF
|
|
11. Run instance on compute with DPDK and check its availability
|
|
via floating IP
|
|
|
|
Duration 90m
|
|
Snapshot deploy_cluster_with_dpdk_bond
|
|
"""
|
|
|
|
self.env.revert_snapshot("ready_with_3_slaves")
|
|
|
|
self.show_step(1)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
settings={
|
|
"net_segment_type": settings.NEUTRON_SEGMENT['vlan'],
|
|
}
|
|
)
|
|
|
|
self.show_step(2)
|
|
self.show_step(3)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id, {
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['compute', 'cinder'],
|
|
'slave-03': ['compute', 'cinder']
|
|
}
|
|
)
|
|
|
|
self.show_step(4)
|
|
nailgun_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
|
|
for node in nailgun_nodes:
|
|
self.fuel_web.update_node_networks(
|
|
node['id'], interfaces_dict=deepcopy(self.INTERFACES),
|
|
raw_data=deepcopy(self.BOND_CONFIG)
|
|
)
|
|
|
|
computes = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
cluster_id,
|
|
roles=['compute'],
|
|
role_status='pending_roles')
|
|
|
|
self.show_step(5)
|
|
for node in computes:
|
|
self.setup_hugepages(node, hp_2mb=256, hp_dpdk_mb=128)
|
|
|
|
self.show_step(6)
|
|
for node in computes:
|
|
self.enable_dpdk(node)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(8)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(9)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(10)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
|
|
self.show_step(11)
|
|
os_conn = os_actions.OpenStackActions(
|
|
self.fuel_web.get_public_vip(cluster_id))
|
|
self.check_dpdk_instance_connectivity(os_conn, cluster_id)
|
|
|
|
self.env.make_snapshot("deploy_cluster_with_dpdk_bond")
|