In the case that the ceph storage backing volumes is different from the one backing ephemeral storage in nova, the auth values in the rbd connection_info could be different and not work if we are using the nova.conf values for ephemeral storage. This change makes the volume connection config code for rbd prefer the cinder connection_info values if they exist, and only falls back to nova config values if cinder doesn't have anything set. Depends-On: I4655cae3212d589177d2570403b563a83aad529a Change-Id: Idcbada705c1d38ac5fd7c600141c2de7020eae25 Closes-Bug: #1635008
123 lines
5.7 KiB
Python
123 lines
5.7 KiB
Python
# 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 oslo_log import log as logging
|
|
|
|
import nova.conf
|
|
from nova import exception
|
|
from nova.i18n import _, _LW
|
|
from nova import utils
|
|
from nova.virt.libvirt.volume import volume as libvirt_volume
|
|
|
|
|
|
CONF = nova.conf.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class LibvirtNetVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
|
|
"""Driver to attach Network volumes to libvirt."""
|
|
def __init__(self, host):
|
|
super(LibvirtNetVolumeDriver,
|
|
self).__init__(host, is_block_dev=False)
|
|
|
|
def _get_secret_uuid(self, conf, password=None):
|
|
# TODO(mriedem): Add delegation methods to connection (LibvirtDriver)
|
|
# to call through for these secret CRUD operations so the volume driver
|
|
# doesn't need to know the internal attributes of the connection
|
|
# object.
|
|
secret = self.host.find_secret(conf.source_protocol,
|
|
conf.source_name)
|
|
if secret is None:
|
|
secret = self.host.create_secret(conf.source_protocol,
|
|
conf.source_name,
|
|
password)
|
|
return secret.UUIDString()
|
|
|
|
def _delete_secret_by_name(self, connection_info):
|
|
source_protocol = connection_info['driver_volume_type']
|
|
netdisk_properties = connection_info['data']
|
|
if source_protocol == 'rbd':
|
|
return
|
|
elif source_protocol == 'iscsi':
|
|
usage_type = 'iscsi'
|
|
usage_name = ("%(target_iqn)s/%(target_lun)s" %
|
|
netdisk_properties)
|
|
self.host.delete_secret(usage_type, usage_name)
|
|
|
|
def _set_auth_config_rbd(self, conf, netdisk_properties):
|
|
# The rbd volume driver in cinder sets auth_enabled if the rbd_user is
|
|
# set in cinder. The rbd auth values from the cinder connection take
|
|
# precedence over any local nova config values in case the cinder ceph
|
|
# backend is configured differently than the nova rbd ephemeral storage
|
|
# configuration.
|
|
auth_enabled = netdisk_properties.get('auth_enabled')
|
|
if auth_enabled:
|
|
conf.auth_username = netdisk_properties['auth_username']
|
|
conf.auth_secret_uuid = netdisk_properties['secret_uuid']
|
|
# secret_type is always hard-coded to 'ceph' in cinder
|
|
conf.auth_secret_type = netdisk_properties['secret_type']
|
|
elif CONF.libvirt.rbd_secret_uuid:
|
|
# Anyone relying on falling back to nova config is probably having
|
|
# this work accidentally and we'll remove that support in the
|
|
# 16.0.0 Pike release.
|
|
LOG.warning(_LW('Falling back to Nova configuration values for '
|
|
'RBD authentication. Cinder should be configured '
|
|
'for auth with Ceph volumes. This fallback will '
|
|
'be dropped in the Nova 16.0.0 Pike release.'))
|
|
# use the nova config values
|
|
conf.auth_username = CONF.libvirt.rbd_user
|
|
conf.auth_secret_uuid = CONF.libvirt.rbd_secret_uuid
|
|
# secret_type is always hard-coded to 'ceph' in cinder
|
|
conf.auth_secret_type = netdisk_properties['secret_type']
|
|
|
|
def _set_auth_config_iscsi(self, conf, netdisk_properties):
|
|
if netdisk_properties.get('auth_method') == 'CHAP':
|
|
conf.auth_secret_type = 'iscsi'
|
|
password = netdisk_properties.get('auth_password')
|
|
conf.auth_secret_uuid = self._get_secret_uuid(conf, password)
|
|
conf.auth_username = netdisk_properties['auth_username']
|
|
|
|
def get_config(self, connection_info, disk_info):
|
|
"""Returns xml for libvirt."""
|
|
conf = super(LibvirtNetVolumeDriver,
|
|
self).get_config(connection_info, disk_info)
|
|
|
|
netdisk_properties = connection_info['data']
|
|
conf.source_type = "network"
|
|
conf.source_protocol = connection_info['driver_volume_type']
|
|
conf.source_name = netdisk_properties.get('name')
|
|
conf.source_hosts = netdisk_properties.get('hosts', [])
|
|
conf.source_ports = netdisk_properties.get('ports', [])
|
|
if conf.source_protocol == 'rbd':
|
|
self._set_auth_config_rbd(conf, netdisk_properties)
|
|
elif conf.source_protocol == 'iscsi':
|
|
try:
|
|
conf.source_name = ("%(target_iqn)s/%(target_lun)s" %
|
|
netdisk_properties)
|
|
target_portal = netdisk_properties['target_portal']
|
|
except KeyError:
|
|
raise exception.NovaException(_("Invalid volume source data"))
|
|
|
|
ip, port = utils.parse_server_string(target_portal)
|
|
if ip == '' or port == '':
|
|
raise exception.NovaException(_("Invalid target_lun"))
|
|
conf.source_hosts = [ip]
|
|
conf.source_ports = [port]
|
|
self._set_auth_config_iscsi(conf, netdisk_properties)
|
|
return conf
|
|
|
|
def disconnect_volume(self, connection_info, disk_dev):
|
|
"""Detach the volume from instance_name."""
|
|
super(LibvirtNetVolumeDriver,
|
|
self).disconnect_volume(connection_info, disk_dev)
|
|
self._delete_secret_by_name(connection_info)
|