Enable support for iscsi multipath connections

Adds new charm config option to enable multipath
connections to iscsi volumes. This is configured
in the [libvirt] section of the nova config.

Since newton, the option has been renamed to
'volume_use_multipath'. To accomodate this,
a newton template has been created.

Change-Id: Ibbf91547c5fc41215873c63219cd83303b1d37cd
Partial-Bug: #1518001
This commit is contained in:
Shane Peters 2017-11-21 11:16:20 -05:00
parent 5d92bc9f7e
commit 5cd8900103
10 changed files with 291 additions and 0 deletions

View File

@ -406,3 +406,13 @@ options:
description: |
A comma-separated list of nagios servicegroups. If left empty, the
nagios_context will be used as the servicegroup.
use-multipath:
type: boolean
default: False
description: |
Use a multipath connection for iSCSI volumes. Enabling this feature
causes libvirt to discover and login to available iscsi targets before
presenting the disk via device mapper (/dev/mapper/XX) to the VM instead
of a single path (/dev/disk/by-path/XX). If changed after deployment,
each VM will require a full stop/start for changes to take affect.

View File

@ -197,6 +197,9 @@ class NovaComputeLibvirtContext(context.OSContextGenerator):
if config('disk-cachemodes'):
ctxt['disk_cachemodes'] = config('disk-cachemodes')
if config('use-multipath'):
ctxt['use_multipath'] = config('use-multipath')
if config('cpu-mode'):
ctxt['cpu_mode'] = config('cpu-mode')
elif ctxt['arch'] in ('ppc64el', 'ppc64le', 'aarch64'):

View File

@ -175,5 +175,8 @@ rbd_secret_uuid = {{ rbd_secret_uuid }}
{% if disk_cachemodes -%}
disk_cachemodes = {{ disk_cachemodes }}
{% endif -%}
{% if use_multipath -%}
iscsi_use_multipath = {{ use_multipath }}
{% endif %}
{% include "parts/section-ephemeral" %}

View File

@ -170,6 +170,9 @@ live_migration_uri = {{ live_migration_uri }}
{% if disk_cachemodes -%}
disk_cachemodes = {{ disk_cachemodes }}
{% endif %}
{% if use_multipath -%}
iscsi_use_multipath = {{ use_multipath }}
{% endif %}
{% include "parts/section-cinder" %}

View File

@ -188,6 +188,9 @@ live_migration_uri = {{ live_migration_uri }}
{% if disk_cachemodes -%}
disk_cachemodes = {{ disk_cachemodes }}
{% endif %}
{% if use_multipath -%}
iscsi_use_multipath = {{ use_multipath }}
{% endif %}
{% include "parts/section-database" %}

View File

@ -198,6 +198,9 @@ live_migration_uri = {{ live_migration_uri }}
{% if disk_cachemodes -%}
disk_cachemodes = {{ disk_cachemodes }}
{% endif %}
{% if use_multipath -%}
iscsi_use_multipath = {{ use_multipath }}
{% endif %}
{% include "parts/section-database" %}

View File

@ -208,6 +208,9 @@ disk_cachemodes = {{ disk_cachemodes }}
# Disable tunnelled migration so that selective
# live block migration can be supported.
live_migration_tunnelled = False
{% if use_multipath -%}
iscsi_use_multipath = {{ use_multipath }}
{% endif %}
{% if virt_type == 'lxd' -%}
[lxd]

241
templates/newton/nova.conf Normal file
View File

@ -0,0 +1,241 @@
# mitaka
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
{% if restart_trigger -%}
# restart trigger: {{ restart_trigger }}
{% endif -%}
###############################################################################
[DEFAULT]
verbose={{ verbose }}
debug={{ debug }}
dhcpbridge_flagfile=/etc/nova/nova.conf
dhcpbridge=/usr/bin/nova-dhcpbridge
logdir=/var/log/nova
state_path=/var/lib/nova
force_dhcp_release=True
use_syslog = {{ use_syslog }}
ec2_private_dns_show_ip=True
api_paste_config=/etc/nova/api-paste.ini
enabled_apis=osapi_compute,metadata
auth_strategy=keystone
my_ip = {{ host_ip }}
{% if arch == 'aarch64' -%}
libvirt_use_virtio_for_bridges=False
libvirt_disk_prefix=vd
{% endif -%}
{% if console_vnc_type -%}
vnc_enabled = True
novnc_enabled = True
vnc_keymap = {{ console_keymap }}
vncserver_listen = 0.0.0.0
vncserver_proxyclient_address = {{ console_listen_addr }}
{% if console_access_protocol == 'novnc' or console_access_protocol == 'vnc' -%}
novncproxy_base_url = {{ novnc_proxy_address }}
{% endif -%}
{% if console_access_protocol == 'xvpvnc' or console_access_protocol == 'vnc' -%}
xvpvncproxy_port = {{ xvpvnc_proxy_port }}
xvpvncproxy_host = {{ xvpvnc_proxy_host }}
xvpvncproxy_base_url = {{ xvpvnc_proxy_address }}
{% endif -%}
{% else -%}
vnc_enabled = False
novnc_enabled = False
{% endif -%}
{% if neutron_plugin and neutron_plugin in ('ovs', 'midonet') -%}
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
{% if neutron_security_groups -%}
security_group_api = neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'vsp' -%}
network_api_class=nova.network.neutronv2.api.API
libvirt_vif_driver=nova.virt.libvirt.vif.LibvirtGenericVIFDriver
neutron_ovs_bridge=alubr0
security_group_api=neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if neutron_plugin and (neutron_plugin == 'nvp' or neutron_plugin == 'nsx') -%}
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtOpenVswitchVirtualPortDriver
security_group_api = neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'Calico' -%}
security_group_api = neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if neutron_plugin and neutron_plugin == 'plumgrid' -%}
security_group_api=neutron
firewall_driver = nova.virt.firewall.NoopFirewallDriver
{% endif -%}
{% if network_manager != 'neutron' and network_manager_config -%}
{% for key, value in network_manager_config.items() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if network_manager == 'neutron' -%}
network_api_class = nova.network.neutronv2.api.API
use_neutron = True
{% else -%}
network_manager = nova.network.manager.FlatDHCPManager
{% endif -%}
{% if network_device_mtu -%}
network_device_mtu = {{ network_device_mtu }}
{% endif -%}
{% if volume_service -%}
volume_api_class = nova.volume.cinder.API
{% endif -%}
{% if user_config_flags -%}
{% for key, value in user_config_flags.items() -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if instances_path -%}
instances_path = {{ instances_path }}
{% endif -%}
{% if enable_designate -%}
notify_on_state_change = {{ notify_on_state_change }}
{% endif -%}
{% if sections and 'DEFAULT' in sections -%}
{% for key, value in sections['DEFAULT'] -%}
{{ key }} = {{ value }}
{% endfor -%}
{% endif -%}
{% if vcpu_pin_set -%}
vcpu_pin_set = {{ vcpu_pin_set }}
{% endif -%}
reserved_host_memory_mb = {{ reserved_host_memory }}
{% if pci_passthrough_whitelist -%}
pci_passthrough_whitelist = {{ pci_passthrough_whitelist }}
{% endif -%}
{% include "section-zeromq" %}
{% if default_availability_zone -%}
default_availability_zone = {{ default_availability_zone }}
{% endif -%}
{% if resume_guests_state_on_host_boot -%}
resume_guests_state_on_host_boot = {{ resume_guests_state_on_host_boot }}
{% endif -%}
{% if network_manager == 'neutron' and network_manager_config -%}
[neutron]
url = {{ network_manager_config.neutron_url }}
{% if network_manager_config.keystone_host -%}
{% if neutron_plugin and neutron_plugin == 'vsp' -%}
ovs_bridge = alubr0
{% endif -%}
{% if auth_host -%}
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = {{ admin_tenant_name }}
username = {{ admin_user }}
password = {{ admin_password }}
signing_dir = {{ signing_dir }}
{% endif -%}
{% if metadata_shared_secret -%}
metadata_proxy_shared_secret = {{ metadata_shared_secret }}
service_metadata_proxy=True
{% endif -%}
{% endif -%}
metadata_workers = {{ workers }}
{% endif -%}
{% include "section-keystone-authtoken-mitaka" %}
{% if glance_api_servers -%}
[glance]
api_servers = {{ glance_api_servers }}
{% endif -%}
{% if console_access_protocol == 'spice' -%}
[spice]
agent_enabled = True
enabled = True
html5proxy_base_url = {{ spice_proxy_address }}
keymap = {{ console_keymap }}
server_listen = 0.0.0.0
server_proxyclient_address = {{ console_listen_addr }}
{% endif -%}
[libvirt]
{% if cpu_mode -%}
cpu_mode = {{ cpu_mode }}
{% endif -%}
{% if cpu_model -%}
cpu_model = {{ cpu_model }}
{% endif -%}
{% if libvirt_images_type -%}
images_type = {{ libvirt_images_type }}
{% endif -%}
{% if libvirt_images_type and rbd_pool -%}
images_rbd_pool = {{ rbd_pool }}
images_rbd_ceph_conf = {{ libvirt_rbd_images_ceph_conf }}
inject_password = false
inject_key = false
inject_partition = -2
{% endif -%}
rbd_user = {{ rbd_user }}
rbd_secret_uuid = {{ rbd_secret_uuid }}
{% if live_migration_uri -%}
live_migration_uri = {{ live_migration_uri }}
{% endif -%}
{% if disk_cachemodes -%}
disk_cachemodes = {{ disk_cachemodes }}
{% endif %}
# Disable tunnelled migration so that selective
# live block migration can be supported.
live_migration_tunnelled = False
{% if use_multipath -%}
volume_use_multipath = {{ use_multipath }}
{% endif %}
{% if virt_type == 'lxd' -%}
[lxd]
{% if enable_live_migration -%}
allow_live_migration = True
{% endif -%}
{% if storage_pool -%}
pool = {{ storage_pool }}
{% endif -%}
{% endif -%}
{% include "parts/section-database" %}
{% include "section-rabbitmq-oslo" %}
{% include "section-oslo-notifications" %}
{% include "parts/section-cinder" %}
[oslo_concurrency]
lock_path=/var/lock/nova
[workarounds]
disable_libvirt_livesnapshot = False
{% include "parts/section-ephemeral" %}
{% include "parts/section-serial-console" %}

View File

@ -209,6 +209,9 @@ disk_cachemodes = {{ disk_cachemodes }}
# Disable tunnelled migration so that selective
# live block migration can be supported.
live_migration_tunnelled = False
{% if use_multipath -%}
volume_use_multipath = {{ use_multipath }}
{% endif %}
{% if virt_type == 'lxd' -%}
[lxd]

View File

@ -576,3 +576,22 @@ class SerialConsoleContextTests(CharmTestCase):
{'enable_serial_console': 'true',
'serial_console_base_url': 'ws://10.10.10.1:6083/'}
)
def test_libvirt_use_multipath(self):
self.kv.return_value = FakeUnitdata(**{'host_uuid': self.host_uuid})
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'yakkety'}
self.os_release.return_value = 'ocata'
self.test_config.set('use-multipath', True)
libvirt = context.NovaComputeLibvirtContext()
self.assertEqual(
{'libvirtd_opts': '',
'libvirt_user': 'libvirt',
'use_multipath': True,
'arch': platform.machine(),
'ksm': 'AUTO',
'kvm_hugepages': 0,
'listen_tls': 0,
'host_uuid': self.host_uuid,
'force_raw_images': True,
'reserved_host_memory': 512}, libvirt())