Update manila plugin to support IPv6

This patch makes necessary changes to devstack manila
plugin in order to be able to run IPv6 scenario tests.

Part of the changes included the dependency of
neutron-dynamic-routing plugin and the installation
of quagga, so routes in devstack host can be created
automatically for each router and private network
created by tempest during the tests.

Also, added a new config option "override_ip_for_nfs_access"
for manila tempest plugin that overrides the access rules used
for NFS scenario tests. This option can be set by exporting the
environment variable "OVERRIDE_IP_FOR_NFS_ACCESS" with the
intended value before running devstack.

This change is enabled by a following change and
tested alongside a change on manila-tempest-plugin
project.

Please note that we are temporarily disabling IPv6
functionality in Host-assisted Share Migration, as
the Data Service is not able to handle IPv4 + IPv6
scenarios.

Change-Id: I4ca727f92618998242af18908bbbda6bb5f86303
Needed-By: Id8b005cdd429d53a75624885fe7ca795746c3ede
This commit is contained in:
Rodrigo Barbieri 2017-11-21 11:00:45 -02:00
parent afe308098a
commit dc93ae534c
9 changed files with 252 additions and 10 deletions

View File

@ -319,6 +319,7 @@
- openstack-infra/devstack-gate
- openstack/manila
- openstack/manila-tempest-plugin
- openstack/neutron-dynamic-routing
- openstack/python-manilaclient
- openstack/tempest

View File

@ -78,6 +78,7 @@ RUN_MANILA_HOST_ASSISTED_MIGRATION_TESTS=${RUN_MANILA_HOST_ASSISTED_MIGRATION_TE
RUN_MANILA_DRIVER_ASSISTED_MIGRATION_TESTS=${RUN_MANILA_DRIVER_ASSISTED_MIGRATION_TESTS:-False}
RUN_MANILA_MOUNT_SNAPSHOT_TESTS=${RUN_MANILA_MOUNT_SNAPSHOT_TESTS:-False}
RUN_MANILA_MIGRATION_WITH_PRESERVE_SNAPSHOTS_TESTS=${RUN_MANILA_MIGRATION_WITH_PRESERVE_SNAPSHOTS_TESTS:-False}
RUN_MANILA_IPV6_TESTS=${RUN_MANILA_IPV6_TESTS:-False}
MANILA_CONF=${MANILA_CONF:-/etc/manila/manila.conf}
@ -316,18 +317,43 @@ export OS_USER_DOMAIN_NAME=$ADMIN_DOMAIN_NAME
source $BASE/new/manila/contrib/ci/common.sh
manila_wait_for_drivers_init $MANILA_CONF
# (aovchinnikov): extra rules are needed to allow instances talk to host.
sudo iptables -N manila-nfs
sudo iptables -I INPUT 1 -j manila-nfs
TCP_PORTS=(2049 111 32803 892 875 662)
UDP_PORTS=(111 32769 892 875 662)
for port in ${TCP_PORTS[*]}; do
sudo iptables -A manila-nfs -m tcp -p tcp --dport $port -j ACCEPT
done
for port in ${UDP_PORTS[*]}; do
sudo iptables -A manila-nfs -m udp -p udp --dport $port -j ACCEPT
for ipcmd in iptables ip6tables; do
# (aovchinnikov): extra rules are needed to allow instances talk to host.
sudo $ipcmd -N manila-nfs
sudo $ipcmd -I INPUT 1 -j manila-nfs
for port in ${TCP_PORTS[*]}; do
sudo $ipcmd -A manila-nfs -m tcp -p tcp --dport $port -j ACCEPT
done
for port in ${UDP_PORTS[*]}; do
sudo $ipcmd -A manila-nfs -m udp -p udp --dport $port -j ACCEPT
done
done
source $BASE/new/devstack/openrc admin admin
public_net_id=$(openstack network list --name $PUBLIC_NETWORK_NAME -f value -c ID )
iniset $TEMPEST_CONFIG network public_network_id $public_net_id
# Now that all plugins are loaded, setup BGP here
if [ $(trueorfalse False MANILA_SETUP_IPV6) == True ]; then
neutron bgp-speaker-create --ip-version 6 --local-as 100 bgpspeaker
neutron bgp-speaker-network-add bgpspeaker $PUBLIC_NETWORK_NAME
neutron bgp-peer-create --peer-ip ::1 --remote-as 200 bgppeer
neutron bgp-speaker-peer-add bgpspeaker bgppeer
fi
# Set config to run IPv6 tests according to env var
iniset $TEMPEST_CONFIG share run_ipv6_tests $RUN_MANILA_IPV6_TESTS
if ! [[ -z "$OVERRIDE_IP_FOR_NFS_ACCESS" ]]; then
# Set config to use specified IP as access rule on NFS scenario tests
# in order to workaround multiple NATs between the VMs and the storage
# controller
iniset $TEMPEST_CONFIG share override_ip_for_nfs_access $OVERRIDE_IP_FOR_NFS_ACCESS
fi
echo "Running tempest manila test suites"
sudo -H -u $USER tox -eall -- $MANILA_TESTS --concurrency=$MANILA_TEMPEST_CONCURRENCY
RETVAL=$?

View File

@ -174,6 +174,16 @@ echo "TEMPEST_USE_TEST_ACCOUNTS=True" >> $localconf
echo "TEMPEST_ALLOW_TENANT_ISOLATION=False" >> $localconf
echo "TEMPEST_CONCURRENCY=${MANILA_TEMPEST_CONCURRENCY:-8}" >> $localconf
MANILA_SETUP_IPV6=${MANILA_SETUP_IPV6:-False}
echo "MANILA_SETUP_IPV6=${MANILA_SETUP_IPV6}" >> $localconf
if [[ "$MANILA_SETUP_IPV6" == True ]]; then
# When setting up proper IPv6 networks, we should do it ourselves so we can
# use Neutron Dynamic Routing plugin with address scopes instead of the
# regular Neutron DevStack configuration.
echo "NEUTRON_CREATE_INITIAL_NETWORKS=False" >> $localconf
echo "IP_VERSION=4+6" >> $localconf
fi
if [[ "$DRIVER" == "generic"* ]]; then
echo -e '[[post-config|${NOVA_CONF:-/etc/nova/nova.conf}]]\n[DEFAULT]\nquota_instances=30\n' >> $localconf
echo -e '[[post-config|${NEUTRON_CONF:-/etc/neutron/neutron.conf}]]\n[DEFAULT]\nmax_fixed_ips_per_port=100\n' >> $localconf

View File

@ -1,3 +1,5 @@
#!/bin/bash
# Plugin file for enabling manila services
# ----------------------------------------
@ -938,6 +940,115 @@ function install_libraries {
fi
}
function setup_ipv6 {
# save IPv6 default route to add back later after enabling forwarding
local default_route=$(ip -6 route | grep default | cut -d ' ' -f1,2,3,4,5)
# make sure those system values are set
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0
sudo sysctl -w net.ipv6.conf.all.accept_ra=2
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Disable in-band as our communication is only internal
sudo ovs-vsctl set Bridge $PUBLIC_BRIDGE other_config:disable-in-band=true
# Create address scopes and subnet pools
neutron address-scope-create --shared scope-v4 4
neutron address-scope-create --shared scope-v6 6
openstack subnet pool create $SUBNETPOOL_NAME_V4 --default-prefix-length $SUBNETPOOL_SIZE_V4 --pool-prefix $SUBNETPOOL_PREFIX_V4 --address-scope scope-v4 --default --share
openstack subnet pool create $SUBNETPOOL_NAME_V6 --default-prefix-length $SUBNETPOOL_SIZE_V6 --pool-prefix $SUBNETPOOL_PREFIX_V6 --address-scope scope-v6 --default --share
# Create example private network and router
openstack router create $Q_ROUTER_NAME
openstack network create $PRIVATE_NETWORK_NAME
openstack subnet create --ip-version 6 --use-default-subnet-pool --ipv6-address-mode $IPV6_ADDRESS_MODE --ipv6-ra-mode $IPV6_RA_MODE --network $PRIVATE_NETWORK_NAME $IPV6_PRIVATE_SUBNET_NAME
openstack subnet create --ip-version 4 --use-default-subnet-pool --network $PRIVATE_NETWORK_NAME $PRIVATE_SUBNET_NAME
openstack router add subnet $Q_ROUTER_NAME $IPV6_PRIVATE_SUBNET_NAME
openstack router add subnet $Q_ROUTER_NAME $PRIVATE_SUBNET_NAME
# Create public network
openstack network create $PUBLIC_NETWORK_NAME --external --default --provider-network-type flat --provider-physical-network $PUBLIC_PHYSICAL_NETWORK
local public_gateway_ipv6=$(openstack subnet create $IPV6_PUBLIC_SUBNET_NAME --ip-version 6 --network $PUBLIC_NETWORK_NAME --subnet-pool $SUBNETPOOL_NAME_V6 --no-dhcp -c gateway_ip -f value)
local public_gateway_ipv4=$(openstack subnet create $PUBLIC_SUBNET_NAME --ip-version 4 --network $PUBLIC_NETWORK_NAME --subnet-range $FLOATING_RANGE --no-dhcp -c gateway_ip -f value)
# Set router to use public network
openstack router set --external-gateway $PUBLIC_NETWORK_NAME $Q_ROUTER_NAME
# Configure interfaces due to NEUTRON_CREATE_INITIAL_NETWORKS=False
local ipv4_cidr_len=${FLOATING_RANGE#*/}
sudo ip -6 addr add "$public_gateway_ipv6"/$SUBNETPOOL_SIZE_V6 dev $PUBLIC_BRIDGE
sudo ip addr add $PUBLIC_NETWORK_GATEWAY/"$ipv4_cidr_len" dev $PUBLIC_BRIDGE
# Enabling interface is needed due to NEUTRON_CREATE_INITIAL_NETWORKS=False
sudo ip link set $PUBLIC_BRIDGE up
if [ "$SHARE_DRIVER" == "manila.share.drivers.lvm.LVMShareDriver" ]; then
for backend_name in ${MANILA_ENABLED_BACKENDS//,/ }; do
iniset $MANILA_CONF $backend_name lvm_share_export_ips $public_gateway_ipv4,$public_gateway_ipv6
done
iniset $MANILA_CONF DEFAULT data_node_access_ip $public_gateway_ipv4
fi
# install Quagga for setting up the host routes dynamically
install_package quagga
# set Quagga daemons
(
echo "zebra=yes"
echo "bgpd=yes"
echo "ospfd=no"
echo "ospf6d=no"
echo "ripd=no"
echo "ripngd=no"
echo "isisd=no"
echo "babeld=no"
) | sudo tee /etc/quagga/daemons > /dev/null
# set Quagga zebra.conf
(
echo "hostname dsvm"
echo "password openstack"
echo "log file /var/log/quagga/zebra.log"
) | sudo tee /etc/quagga/zebra.conf > /dev/null
# set Quagga bgpd.conf
(
echo "log file /var/log/quagga/bgpd.log"
echo "bgp multiple-instance"
echo "router bgp 200"
echo " bgp router-id 1.2.3.4"
echo " neighbor ::1 remote-as 100"
echo " neighbor ::1 passive"
echo " address-family ipv6"
echo " neighbor ::1 activate"
echo "line vty"
echo "debug bgp events"
echo "debug bgp filters"
echo "debug bgp fsm"
echo "debug bgp keepalives"
echo "debug bgp updates"
) | sudo tee /etc/quagga/bgpd.conf > /dev/null
if is_ubuntu; then
sudo systemctl enable quagga
sudo systemctl restart quagga
else
# Disable SELinux rule that conflicts with Zebra
sudo setsebool -P zebra_write_config 1
sudo systemctl enable zebra
sudo systemctl enable bgpd
sudo systemctl restart zebra
sudo systemctl restart bgpd
fi
# add default IPv6 route back
if ! [[ -z $default_route ]]; then
sudo ip -6 route add $default_route
fi
}
# Main dispatcher
if [[ "$1" == "stack" && "$2" == "install" ]]; then
echo_summary "Installing Manila Client"
@ -991,6 +1102,11 @@ elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
echo_summary "Configure Samba server"
configure_samba
echo_summary "Configuring IPv6"
if [ $(trueorfalse False MANILA_SETUP_IPV6) == True ]; then
setup_ipv6
fi
echo_summary "Starting Manila API"
start_manila_api

View File

@ -199,6 +199,9 @@ else
TEMPEST_PLUGINS=$MANILA_TEMPEST_PLUGIN_PATH
fi
# Manila IPv6 Setup flag
MANILA_SETUP_IPV6=${MANILA_SETUP_IPV6:=False}
# Enable manila services
# ----------------------
# We have to add Manila to enabled services for screen_it to work

View File

@ -27,6 +27,7 @@ from oslo_log import log
from manila import exception
from manila.i18n import _
from manila import network
from manila.share import utils as share_utils
from manila import utils
LOG = log.getLogger(__name__)
@ -627,8 +628,13 @@ class ShareDriver(object):
# NOTE(ganso): If drivers want to override the export_location IP,
# they can do so using this configuration. This method can also be
# overridden if necessary.
# NOTE(ganso): The data service needs to be improved to
# support IPv4 + IPv6. Until then we will support only IPv4.
path = next((x['path'] for x in share_instance['export_locations']
if x['is_admin_only']), None)
if (x['is_admin_only']) and
share_utils.is_proper_ipv4_export_location(
x['path'],
share_instance['share_proto'].lower())), None)
if not path:
path = share_instance['export_locations'][0]['path']
return path

View File

@ -152,3 +152,16 @@ def _usage_from_share(share_ref, share_instance_ref, **extra_usage_info):
def get_recent_db_migration_id():
return migration.version()
def is_proper_ipv4_export_location(export, protocol):
"""Verifies if the export location is in proper IPv4 format."""
export = export.replace('[', '').replace(']', '')
if protocol == 'nfs' and ':/' in export:
ip = export.split(':/')[0]
elif protocol == 'cifs' and export.startswith(r'\\'):
ip = export.split('\\')[2]
else:
# TODO(ganso): proper handling of other protocols is pending
ip = export.split(':')[0] if ':' in export else export.split('/')[0]
return utils.is_valid_ip_address(ip, 4)

View File

@ -16,6 +16,7 @@
"""Tests For miscellaneous util methods used with share."""
import ddt
import mock
from manila.common import constants
@ -23,6 +24,7 @@ from manila.share import utils as share_utils
from manila import test
@ddt.ddt
class ShareUtilsTestCase(test.TestCase):
def test_extract_host_without_pool(self):
host = 'Host@Backend'
@ -162,6 +164,69 @@ class ShareUtilsTestCase(test.TestCase):
replica = share_utils.get_active_replica(replica_list)
self.assertIsNone(replica)
@ddt.data({'exp': '172.24.5.1:/my_export_location', 'proto': 'nfs',
'expected': True},
{'exp': '\\\\172.24.5.1\\foo\\bar', 'proto': 'cifs',
'expected': True},
{'exp': 'fad0:88:133:/my_export_location', 'proto': 'nfs',
'expected': False},
{'exp': '\\\\fad0:88::133\\foo\\bar', 'proto': 'cifs',
'expected': False},
{'exp': 'fd01::1:/my_export_location', 'proto': 'nfs',
'expected': False},
{'exp': '\\\\[fd01::1]\\foo\\bar', 'proto': 'cifs',
'expected': False},
{'exp': '[fad0:88::133]:/my_export_location', 'proto': 'nfs',
'expected': False},
{'exp': '\\\\[fad0:88::133]\\foo\\bar', 'proto': 'cifs',
'expected': False},
{'exp': '[fd01::1]:/my_export_location', 'proto': 'nfs',
'expected': False},
{'exp': '\\\\fad0-88--133.ipv6-literal.net\\foo\\bar',
'proto': 'cifs', 'expected': False},
{'exp': '172.24.5.1:8080/my_export_location', 'proto': 'other',
'expected': True},
{'exp': '172.24.5.1:8080:/my_export_location', 'proto': 'other',
'expected': True},
{'exp': '172.24.5.1:/my_export_location', 'proto': 'other',
'expected': True},
{'exp': '172.24.5.1/my_export_location', 'proto': 'other',
'expected': True},
{'exp': '172.24.5.1/my_export_location', 'proto': 'nfs',
'expected': True},
{'exp': 'fd01::1:8080/my_export_location', 'proto': 'other',
'expected': False},
{'exp': 'fd01::1/my_export_location', 'proto': 'other',
'expected': False},
{'exp': 'fd01::1:8080:/my_export_location', 'proto': 'other',
'expected': False},
{'exp': 'fd01::1:/my_export_location', 'proto': 'other',
'expected': False},
{'exp': '555.555.555.555:/my_export_location', 'proto': 'other',
'expected': False},
{'exp': '555.555.555.555:/my_export_location', 'proto': 'nfs',
'expected': False},
{'exp': '555.555.555.555/my_export_location', 'proto': 'other',
'expected': False},
{'exp': '555.5.5.555:8080/my_export_location', 'proto': 'other',
'expected': False},
{'exp': '555.55.5.55:8080:/my_export_location', 'proto': 'other',
'expected': False},
{'exp': '[172.24.5.1]:/my_export_location', 'proto': 'nfs',
'expected': True},
{'exp': '172.24.5.1/my_export_location', 'proto': 'other',
'expected': True},
{'exp': '172.24.5.1\\foo\\bar', 'proto': 'cifs',
'expected': False},
{'exp': '\\172.24.5.1\\foo\\bar', 'proto': 'cifs',
'expected': False},
{'exp': '\\\\172.24.5.1\\foo\\bar', 'proto': 'other',
'expected': False})
@ddt.unpack
def test_is_proper_ipv4_export_location(self, exp, proto, expected):
result = share_utils.is_proper_ipv4_export_location(exp, proto)
self.assertEqual(expected, result)
class NotifyUsageTestCase(test.TestCase):
@mock.patch('manila.share.utils._usage_from_share')

View File

@ -39,6 +39,7 @@
[[local|localrc]]
SKIP_EPEL_INSTALL=True
enable_plugin manila git://git.openstack.org/openstack/manila
enable_plugin neutron-dynamic-routing git://git.openstack.org/openstack/neutron-dynamic-routing
EOF
executable: /bin/bash
@ -52,6 +53,7 @@
export PYTHONUNBUFFERED=true
export DEVSTACK_GATE_NEUTRON=1
export DEVSTACK_PROJECT_FROM_GIT="python-manilaclient"
# Basic services needed for minimal job
OVERRIDE_ENABLED_SERVICES=key,mysql,rabbit,tempest
if [ "lvm" == "lvm" ]; then
@ -71,7 +73,7 @@
# Keep localrc to be able to set some vars in pre_test_hook
export KEEP_LOCALRC=1
export PROJECTS="openstack/manila-tempest-plugin $PROJECTS"
export PROJECTS="openstack/manila-tempest-plugin openstack/neutron-dynamic-routing $PROJECTS"
function pre_test_hook {
# 'dhss' - acronym for 'Driver Handles Share Servers',