diff --git a/.zuul.yaml b/.zuul.yaml index acbf02ec95..038c0f2a09 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -319,6 +319,7 @@ - openstack-infra/devstack-gate - openstack/manila - openstack/manila-tempest-plugin + - openstack/neutron-dynamic-routing - openstack/python-manilaclient - openstack/tempest diff --git a/contrib/ci/post_test_hook.sh b/contrib/ci/post_test_hook.sh index b7188c8fbf..ab11bf5138 100755 --- a/contrib/ci/post_test_hook.sh +++ b/contrib/ci/post_test_hook.sh @@ -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=$? diff --git a/contrib/ci/pre_test_hook.sh b/contrib/ci/pre_test_hook.sh index 688b31dbb4..1bfd886f7b 100755 --- a/contrib/ci/pre_test_hook.sh +++ b/contrib/ci/pre_test_hook.sh @@ -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 diff --git a/devstack/plugin.sh b/devstack/plugin.sh index d53f1259e4..3d17f1bb14 100755 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -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 diff --git a/devstack/settings b/devstack/settings index c9fd8cb4b2..d96e990704 100644 --- a/devstack/settings +++ b/devstack/settings @@ -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 diff --git a/manila/share/driver.py b/manila/share/driver.py index 133bd38626..d101e6c35c 100644 --- a/manila/share/driver.py +++ b/manila/share/driver.py @@ -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 diff --git a/manila/share/utils.py b/manila/share/utils.py index 9b53e83f6a..5e9451d3b9 100644 --- a/manila/share/utils.py +++ b/manila/share/utils.py @@ -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) diff --git a/manila/tests/share/test_share_utils.py b/manila/tests/share/test_share_utils.py index 4238583f32..ed762318d6 100644 --- a/manila/tests/share/test_share_utils.py +++ b/manila/tests/share/test_share_utils.py @@ -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') diff --git a/playbooks/legacy/manila-tempest-minimal-dsvm-lvm-centos-7/run.yaml b/playbooks/legacy/manila-tempest-minimal-dsvm-lvm-centos-7/run.yaml index 926c79d9bf..cbb0767852 100644 --- a/playbooks/legacy/manila-tempest-minimal-dsvm-lvm-centos-7/run.yaml +++ b/playbooks/legacy/manila-tempest-minimal-dsvm-lvm-centos-7/run.yaml @@ -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',