Skip to content

Commit 97061c9

Browse files
committed
Add LVM NVMe support
This patch adds NVMe LVM support to the existing iSCSI LVM configuration support. We deprecate the CINDER_ISCSI_HELPER configuration option since we are no longer limited to iSCSI, and replace it with the CINDER_TARGET_HELPER option. The patch also adds another 3 target configuration options: - CINDER_TARGET_PROTOCOL - CINDER_TARGET_PREFIX - CINDER_TARGET_PORT These options will have different defaults based on the selected target helper. For tgtadm and lioadm they'll be iSCSI, iqn.2010-10.org.openstack:, and 3260 respectively, and for nvmet they'll be nvmet_rdma, nvme-subsystem-1, and 4420. Besides nvmet_rdma the CINDER_TARGET_PROTOCOL option can also be set to nvmet_tcp, and nvmet_fc. For the RDMA transport protocol devstack will be using Soft-RoCE and creating a device on top of the network interface. LVM NVMe-TCP support is added in the dependency mentioned in the footer and LVM NVMe-FC will be added in later patches (need os-brick and cinder patches) but the code here should still be valid. Change-Id: I6578cdc27489b34916cdeb72ba3fdf06ea9d4ad8
1 parent bd6e520 commit 97061c9

6 files changed

Lines changed: 154 additions & 27 deletions

File tree

doc/source/configuration.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,35 @@ adjusted by setting ``CINDER_QUOTA_VOLUMES``, ``CINDER_QUOTA_BACKUPS``,
669669
or ``CINDER_QUOTA_SNAPSHOTS`` to the desired value. (The default for
670670
each is 10.)
671671

672+
DevStack's Cinder LVM configuration module currently supports both iSCSI and
673+
NVMe connections, and we can choose which one to use with options
674+
``CINDER_TARGET_HELPER``, ``CINDER_TARGET_PROTOCOL``, ``CINDER_TARGET_PREFIX``,
675+
and ``CINDER_TARGET_PORT``.
676+
677+
Defaults use iSCSI with the LIO target manager::
678+
679+
CINDER_TARGET_HELPER="lioadm"
680+
CINDER_TARGET_PROTOCOL="iscsi"
681+
CINDER_TARGET_PREFIX="iqn.2010-10.org.openstack:"
682+
CINDER_TARGET_PORT=3260
683+
684+
Additionally there are 3 supported transport protocols for NVMe,
685+
``nvmet_rdma``, ``nvmet_tcp``, and ``nvmet_fc``, and when the ``nvmet`` target
686+
is selected the protocol, prefix, and port defaults will change to more
687+
sensible defaults for NVMe::
688+
689+
CINDER_TARGET_HELPER="nvmet"
690+
CINDER_TARGET_PROTOCOL="nvmet_rdma"
691+
CINDER_TARGET_PREFIX="nvme-subsystem-1"
692+
CINDER_TARGET_PORT=4420
693+
694+
When selecting the RDMA transport protocol DevStack will create on Cinder nodes
695+
a Software RoCE device on top of the ``HOST_IP_IFACE`` and if it is not defined
696+
then on top of the interface with IP address ``HOST_IP`` or ``HOST_IPV6``.
697+
698+
This Soft-RoCE device will always be created on the Nova compute side since we
699+
cannot tell beforehand whether there will be an RDMA connection or not.
700+
672701

673702
Keystone
674703
~~~~~~~~

lib/cinder

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ GITDIR["python-cinderclient"]=$DEST/python-cinderclient
4343
GITDIR["python-brick-cinderclient-ext"]=$DEST/python-brick-cinderclient-ext
4444
CINDER_DIR=$DEST/cinder
4545

46+
if [[ $SERVICE_IP_VERSION == 6 ]]; then
47+
CINDER_MY_IP="$HOST_IPV6"
48+
else
49+
CINDER_MY_IP="$HOST_IP"
50+
fi
51+
52+
4653
# Cinder virtual environment
4754
if [[ ${USE_VENV} = True ]]; then
4855
PROJECT_VENV["cinder"]=${CINDER_DIR}.venv
@@ -88,13 +95,32 @@ CINDER_ENABLED_BACKENDS=${CINDER_ENABLED_BACKENDS:-lvm:lvmdriver-1}
8895
CINDER_VOLUME_CLEAR=${CINDER_VOLUME_CLEAR:-${CINDER_VOLUME_CLEAR_DEFAULT:-zero}}
8996
CINDER_VOLUME_CLEAR=$(echo ${CINDER_VOLUME_CLEAR} | tr '[:upper:]' '[:lower:]')
9097

91-
# Default to lioadm
92-
CINDER_ISCSI_HELPER=${CINDER_ISCSI_HELPER:-lioadm}
98+
99+
if [[ -n "$CINDER_ISCSI_HELPER" ]]; then
100+
if [[ -z "$CINDER_TARGET_HELPER" ]]; then
101+
deprecated 'Using CINDER_ISCSI_HELPER is deprecated, use CINDER_TARGET_HELPER instead'
102+
CINDER_TARGET_HELPER="$CINDER_ISCSI_HELPER"
103+
else
104+
deprecated 'Deprecated CINDER_ISCSI_HELPER is set, but is being overwritten by CINDER_TARGET_HELPER'
105+
fi
106+
fi
107+
CINDER_TARGET_HELPER=${CINDER_TARGET_HELPER:-lioadm}
108+
109+
if [[ $CINDER_TARGET_HELPER == 'nvmet' ]]; then
110+
CINDER_TARGET_PROTOCOL=${CINDER_TARGET_PROTOCOL:-'nvmet_rdma'}
111+
CINDER_TARGET_PREFIX=${CINDER_TARGET_PREFIX:-'nvme-subsystem-1'}
112+
CINDER_TARGET_PORT=${CINDER_TARGET_PORT:-4420}
113+
else
114+
CINDER_TARGET_PROTOCOL=${CINDER_TARGET_PROTOCOL:-'iscsi'}
115+
CINDER_TARGET_PREFIX=${CINDER_TARGET_PREFIX:-'iqn.2010-10.org.openstack:'}
116+
CINDER_TARGET_PORT=${CINDER_TARGET_PORT:-3260}
117+
fi
118+
93119

94120
# EL and SUSE should only use lioadm
95121
if is_fedora || is_suse; then
96-
if [[ ${CINDER_ISCSI_HELPER} != "lioadm" ]]; then
97-
die "lioadm is the only valid Cinder target_helper config on this platform"
122+
if [[ ${CINDER_TARGET_HELPER} != "lioadm" && ${CINDER_TARGET_HELPER} != 'nvmet' ]]; then
123+
die "lioadm and nvmet are the only valid Cinder target_helper config on this platform"
98124
fi
99125
fi
100126

@@ -187,7 +213,7 @@ function _cinder_cleanup_apache_wsgi {
187213
function cleanup_cinder {
188214
# ensure the volume group is cleared up because fails might
189215
# leave dead volumes in the group
190-
if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
216+
if [ "$CINDER_TARGET_HELPER" = "tgtadm" ]; then
191217
local targets
192218
targets=$(sudo tgtadm --op show --mode target)
193219
if [ $? -ne 0 ]; then
@@ -215,8 +241,14 @@ function cleanup_cinder {
215241
else
216242
stop_service tgtd
217243
fi
218-
else
244+
elif [ "$CINDER_TARGET_HELPER" = "lioadm" ]; then
219245
sudo cinder-rtstool get-targets | sudo xargs -rn 1 cinder-rtstool delete
246+
elif [ "$CINDER_TARGET_HELPER" = "nvmet" ]; then
247+
# If we don't disconnect everything vgremove will block
248+
sudo nvme disconnect-all
249+
sudo nvmetcli clear
250+
else
251+
die $LINENO "Unknown value \"$CINDER_TARGET_HELPER\" for CINDER_TARGET_HELPER"
220252
fi
221253

222254
if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
@@ -267,19 +299,15 @@ function configure_cinder {
267299

268300
iniset $CINDER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
269301

270-
iniset $CINDER_CONF DEFAULT target_helper "$CINDER_ISCSI_HELPER"
302+
iniset $CINDER_CONF DEFAULT target_helper "$CINDER_TARGET_HELPER"
271303
iniset $CINDER_CONF database connection `database_connection_url cinder`
272304
iniset $CINDER_CONF DEFAULT api_paste_config $CINDER_API_PASTE_INI
273305
iniset $CINDER_CONF DEFAULT rootwrap_config "$CINDER_CONF_DIR/rootwrap.conf"
274306
iniset $CINDER_CONF DEFAULT osapi_volume_extension cinder.api.contrib.standard_extensions
275307
iniset $CINDER_CONF DEFAULT osapi_volume_listen $CINDER_SERVICE_LISTEN_ADDRESS
276308
iniset $CINDER_CONF DEFAULT state_path $CINDER_STATE_PATH
277309
iniset $CINDER_CONF oslo_concurrency lock_path $CINDER_STATE_PATH
278-
if [[ $SERVICE_IP_VERSION == 6 ]]; then
279-
iniset $CINDER_CONF DEFAULT my_ip "$HOST_IPV6"
280-
else
281-
iniset $CINDER_CONF DEFAULT my_ip "$HOST_IP"
282-
fi
310+
iniset $CINDER_CONF DEFAULT my_ip "$CINDER_MY_IP"
283311
iniset $CINDER_CONF key_manager backend cinder.keymgr.conf_key_mgr.ConfKeyManager
284312
iniset $CINDER_CONF key_manager fixed_key $(openssl rand -hex 16)
285313
if [[ -n "$CINDER_ALLOWED_DIRECT_URL_SCHEMES" ]]; then
@@ -465,9 +493,9 @@ function init_cinder {
465493
function install_cinder {
466494
git_clone $CINDER_REPO $CINDER_DIR $CINDER_BRANCH
467495
setup_develop $CINDER_DIR
468-
if [[ "$CINDER_ISCSI_HELPER" == "tgtadm" ]]; then
496+
if [[ "$CINDER_TARGET_HELPER" == "tgtadm" ]]; then
469497
install_package tgt
470-
elif [[ "$CINDER_ISCSI_HELPER" == "lioadm" ]]; then
498+
elif [[ "$CINDER_TARGET_HELPER" == "lioadm" ]]; then
471499
if is_ubuntu; then
472500
# TODO(frickler): Workaround for https://launchpad.net/bugs/1819819
473501
sudo mkdir -p /etc/target
@@ -476,6 +504,43 @@ function install_cinder {
476504
else
477505
install_package targetcli
478506
fi
507+
elif [[ "$CINDER_TARGET_HELPER" == "nvmet" ]]; then
508+
install_package nvme-cli
509+
510+
# TODO: Remove manual installation of the dependency when the
511+
# requirement is added to nvmetcli:
512+
# http://lists.infradead.org/pipermail/linux-nvme/2022-July/033576.html
513+
if is_ubuntu; then
514+
install_package python3-configshell-fb
515+
else
516+
install_package python3-configshell
517+
fi
518+
# Install from source because Ubuntu doesn't have the package and some packaged versions didn't work on Python 3
519+
pip_install git+git://git.infradead.org/users/hch/nvmetcli.git
520+
521+
sudo modprobe nvmet
522+
sudo modprobe nvme-fabrics
523+
524+
if [[ $CINDER_TARGET_PROTOCOL == 'nvmet_rdma' ]]; then
525+
install_package rdma-core
526+
sudo modprobe nvme-rdma
527+
528+
# Create the Soft-RoCE device over the networking interface
529+
local iface=${HOST_IP_IFACE:-`ip -br -$SERVICE_IP_VERSION a | grep $CINDER_MY_IP | awk '{print $1}'`}
530+
if [[ -z "$iface" ]]; then
531+
die $LINENO "Cannot find interface to bind Soft-RoCE"
532+
fi
533+
534+
if ! sudo rdma link | grep $iface ; then
535+
sudo rdma link add rxe_$iface type rxe netdev $iface
536+
fi
537+
538+
elif [[ $CINDER_TARGET_PROTOCOL == 'nvmet_tcp' ]]; then
539+
sudo modprobe nvme-tcp
540+
541+
else # 'nvmet_fc'
542+
sudo modprobe nvme-fc
543+
fi
479544
fi
480545
}
481546

@@ -512,7 +577,7 @@ function start_cinder {
512577
service_port=$CINDER_SERVICE_PORT_INT
513578
service_protocol="http"
514579
fi
515-
if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
580+
if [ "$CINDER_TARGET_HELPER" = "tgtadm" ]; then
516581
if is_service_enabled c-vol; then
517582
# Delete any old stack.conf
518583
sudo rm -f /etc/tgt/conf.d/stack.conf

lib/cinder_backends/fake_gate

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function configure_cinder_backend_lvm {
5050
iniset $CINDER_CONF $be_name volume_backend_name $be_name
5151
iniset $CINDER_CONF $be_name volume_driver "cinder.tests.fake_driver.FakeGateDriver"
5252
iniset $CINDER_CONF $be_name volume_group $VOLUME_GROUP_NAME-$be_name
53-
iniset $CINDER_CONF $be_name target_helper "$CINDER_ISCSI_HELPER"
53+
iniset $CINDER_CONF $be_name target_helper "$CINDER_TARGET_HELPER"
5454
iniset $CINDER_CONF $be_name lvm_type "$CINDER_LVM_TYPE"
5555

5656
if [[ "$CINDER_VOLUME_CLEAR" == "non" ]]; then

lib/cinder_backends/lvm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ function configure_cinder_backend_lvm {
5050
iniset $CINDER_CONF $be_name volume_backend_name $be_name
5151
iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.lvm.LVMVolumeDriver"
5252
iniset $CINDER_CONF $be_name volume_group $VOLUME_GROUP_NAME-$be_name
53-
iniset $CINDER_CONF $be_name target_helper "$CINDER_ISCSI_HELPER"
53+
iniset $CINDER_CONF $be_name target_helper "$CINDER_TARGET_HELPER"
54+
iniset $CINDER_CONF $be_name target_protocol "$CINDER_TARGET_PROTOCOL"
55+
iniset $CINDER_CONF $be_name target_port "$CINDER_TARGET_PORT"
56+
iniset $CINDER_CONF $be_name target_prefix "$CINDER_TARGET_PREFIX"
5457
iniset $CINDER_CONF $be_name lvm_type "$CINDER_LVM_TYPE"
5558
iniset $CINDER_CONF $be_name volume_clear "$CINDER_VOLUME_CLEAR"
5659
}

lib/lvm

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,22 @@ function init_lvm_volume_group {
130130
local size=$2
131131

132132
# Start the tgtd service on Fedora and SUSE if tgtadm is used
133-
if is_fedora || is_suse && [[ "$CINDER_ISCSI_HELPER" = "tgtadm" ]]; then
133+
if is_fedora || is_suse && [[ "$CINDER_TARGET_HELPER" = "tgtadm" ]]; then
134134
start_service tgtd
135135
fi
136136

137137
# Start with a clean volume group
138138
_create_lvm_volume_group $vg $size
139139

140140
# Remove iscsi targets
141-
if [ "$CINDER_ISCSI_HELPER" = "lioadm" ]; then
141+
if [ "$CINDER_TARGET_HELPER" = "lioadm" ]; then
142142
sudo cinder-rtstool get-targets | sudo xargs -rn 1 cinder-rtstool delete
143-
else
143+
elif [ "$CINDER_TARGET_HELPER" = "tgtadm" ]; then
144144
sudo tgtadm --op show --mode target | awk '/Target/ {print $3}' | sudo xargs -r -n1 tgt-admin --delete
145+
elif [ "$CINDER_TARGET_HELPER" = "nvmet" ]; then
146+
# If we don't disconnect everything vgremove will block
147+
sudo nvme disconnect-all
148+
sudo nvmetcli clear
145149
fi
146150
_clean_lvm_volume_group $vg
147151
}

lib/nova

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ NOVA_SERVICE_LISTEN_ADDRESS=${NOVA_SERVICE_LISTEN_ADDRESS:-$(ipv6_unquote $SERVI
9797
METADATA_SERVICE_PORT=${METADATA_SERVICE_PORT:-8775}
9898
NOVA_ENABLE_CACHE=${NOVA_ENABLE_CACHE:-True}
9999

100+
if [[ $SERVICE_IP_VERSION == 6 ]]; then
101+
NOVA_MY_IP="$HOST_IPV6"
102+
else
103+
NOVA_MY_IP="$HOST_IP"
104+
fi
105+
100106
# Option to enable/disable config drive
101107
# NOTE: Set ``FORCE_CONFIG_DRIVE="False"`` to turn OFF config drive
102108
FORCE_CONFIG_DRIVE=${FORCE_CONFIG_DRIVE:-"False"}
@@ -219,6 +225,9 @@ function cleanup_nova {
219225
done
220226
sudo iscsiadm --mode node --op delete || true
221227

228+
# Disconnect all nvmeof connections
229+
sudo nvme disconnect-all || true
230+
222231
# Clean out the instances directory.
223232
sudo rm -rf $NOVA_INSTANCES_PATH/*
224233
fi
@@ -306,6 +315,7 @@ function configure_nova {
306315
fi
307316
fi
308317

318+
# Due to cinder bug #1966513 we ALWAYS need an initiator name for LVM
309319
# Ensure each compute host uses a unique iSCSI initiator
310320
echo InitiatorName=$(iscsi-iname) | sudo tee /etc/iscsi/initiatorname.iscsi
311321

@@ -326,8 +336,28 @@ EOF
326336
# not work under FIPS.
327337
iniset -sudo /etc/iscsi/iscsid.conf DEFAULT "node.session.auth.chap_algs" "SHA3-256,SHA256"
328338

329-
# ensure that iscsid is started, even when disabled by default
330-
restart_service iscsid
339+
if [[ $CINDER_TARGET_HELPER != 'nvmet' ]]; then
340+
# ensure that iscsid is started, even when disabled by default
341+
restart_service iscsid
342+
343+
# For NVMe-oF we need different packages that many not be present
344+
else
345+
install_package nvme-cli
346+
sudo modprobe nvme-fabrics
347+
348+
# Ensure NVMe is ready and create the Soft-RoCE device over the networking interface
349+
if [[ $CINDER_TARGET_PROTOCOL == 'nvmet_rdma' ]]; then
350+
sudo modprobe nvme-rdma
351+
iface=${HOST_IP_IFACE:-`ip -br -$SERVICE_IP_VERSION a | grep $NOVA_MY_IP | awk '{print $1}'`}
352+
if ! sudo rdma link | grep $iface ; then
353+
sudo rdma link add rxe_$iface type rxe netdev $iface
354+
fi
355+
elif [[ $CINDER_TARGET_PROTOCOL == 'nvmet_tcp' ]]; then
356+
sudo modprobe nvme-tcp
357+
else # 'nvmet_fc'
358+
sudo modprobe nvme-fc
359+
fi
360+
fi
331361
fi
332362

333363
# Rebuild the config file from scratch
@@ -418,11 +448,7 @@ function create_nova_conf {
418448
iniset $NOVA_CONF filter_scheduler enabled_filters "$NOVA_FILTERS"
419449
iniset $NOVA_CONF scheduler workers "$API_WORKERS"
420450
iniset $NOVA_CONF neutron default_floating_pool "$PUBLIC_NETWORK_NAME"
421-
if [[ $SERVICE_IP_VERSION == 6 ]]; then
422-
iniset $NOVA_CONF DEFAULT my_ip "$HOST_IPV6"
423-
else
424-
iniset $NOVA_CONF DEFAULT my_ip "$HOST_IP"
425-
fi
451+
iniset $NOVA_CONF DEFAULT my_ip "$NOVA_MY_IP"
426452
iniset $NOVA_CONF DEFAULT instance_name_template "${INSTANCE_NAME_PREFIX}%08x"
427453
iniset $NOVA_CONF DEFAULT osapi_compute_listen "$NOVA_SERVICE_LISTEN_ADDRESS"
428454
iniset $NOVA_CONF DEFAULT metadata_listen "$NOVA_SERVICE_LISTEN_ADDRESS"

0 commit comments

Comments
 (0)