Merge "libvirt: move LibvirtSMBFSVolumeDriver into it's own module"

This commit is contained in:
Jenkins 2015-08-05 13:36:00 +00:00 committed by Gerrit Code Review
commit b144fe4447
5 changed files with 206 additions and 160 deletions

View File

@ -0,0 +1,104 @@
# 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.
import os
import mock
from nova.tests.unit.virt.libvirt.volume import test_volume
from nova import utils
from nova.virt.libvirt import utils as libvirt_utils
from nova.virt.libvirt.volume import smbfs
class LibvirtSMBFSVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
"""Tests the libvirt SMBFS volume driver."""
def setUp(self):
super(LibvirtSMBFSVolumeDriverTestCase, self).setUp()
self.mnt_base = '/mnt'
self.flags(smbfs_mount_point_base=self.mnt_base, group='libvirt')
@mock.patch.object(libvirt_utils, 'is_mounted')
def test_libvirt_smbfs_driver(self, mock_is_mounted):
mock_is_mounted.return_value = False
libvirt_driver = smbfs.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(self.mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name,
'options': None}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('mkdir', '-p', export_mnt_base),
('mount', '-t', 'cifs', '-o', 'username=guest',
export_string, export_mnt_base),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)
def test_libvirt_smbfs_driver_already_mounted(self):
libvirt_driver = smbfs.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(self.mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('findmnt', '--target', export_mnt_base,
'--source', export_string),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)
def test_libvirt_smbfs_driver_get_config(self):
libvirt_driver = smbfs.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(self.mnt_base,
utils.get_hash_str(export_string))
file_path = os.path.join(export_mnt_base, self.name)
connection_info = {'data': {'export': export_string,
'name': self.name,
'device_path': file_path}}
conf = libvirt_driver.get_config(connection_info, self.disk_info)
tree = conf.format_dom()
self._assertFileTypeEquals(tree, file_path)
@mock.patch.object(libvirt_utils, 'is_mounted')
def test_libvirt_smbfs_driver_with_opts(self, mock_is_mounted):
mock_is_mounted.return_value = False
libvirt_driver = smbfs.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
options = '-o user=guest,uid=107,gid=105'
export_mnt_base = os.path.join(self.mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name,
'options': options}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('mkdir', '-p', export_mnt_base),
('mount', '-t', 'cifs', '-o', 'user=guest,uid=107,gid=105',
export_string, export_mnt_base),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)

View File

@ -644,87 +644,3 @@ Setting up iSCSI targets: unused
('umount', export_mnt_base),
]
self.assertEqual(expected_commands, self.executes)
@mock.patch.object(libvirt_utils, 'is_mounted')
def test_libvirt_smbfs_driver(self, mock_is_mounted):
mnt_base = '/mnt'
self.flags(smbfs_mount_point_base=mnt_base, group='libvirt')
mock_is_mounted.return_value = False
libvirt_driver = volume.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name,
'options': None}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('mkdir', '-p', export_mnt_base),
('mount', '-t', 'cifs', '-o', 'username=guest',
export_string, export_mnt_base),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)
def test_libvirt_smbfs_driver_already_mounted(self):
mnt_base = '/mnt'
self.flags(smbfs_mount_point_base=mnt_base, group='libvirt')
libvirt_driver = volume.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('findmnt', '--target', export_mnt_base,
'--source', export_string),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)
def test_libvirt_smbfs_driver_get_config(self):
mnt_base = '/mnt'
self.flags(smbfs_mount_point_base=mnt_base, group='libvirt')
libvirt_driver = volume.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
export_mnt_base = os.path.join(mnt_base,
utils.get_hash_str(export_string))
file_path = os.path.join(export_mnt_base, self.name)
connection_info = {'data': {'export': export_string,
'name': self.name,
'device_path': file_path}}
conf = libvirt_driver.get_config(connection_info, self.disk_info)
tree = conf.format_dom()
self._assertFileTypeEquals(tree, file_path)
@mock.patch.object(libvirt_utils, 'is_mounted')
def test_libvirt_smbfs_driver_with_opts(self, mock_is_mounted):
mnt_base = '/mnt'
self.flags(smbfs_mount_point_base=mnt_base, group='libvirt')
mock_is_mounted.return_value = False
libvirt_driver = volume.LibvirtSMBFSVolumeDriver(self.fake_conn)
export_string = '//192.168.1.1/volumes'
options = '-o user=guest,uid=107,gid=105'
export_mnt_base = os.path.join(mnt_base,
utils.get_hash_str(export_string))
connection_info = {'data': {'export': export_string,
'name': self.name,
'options': options}}
libvirt_driver.connect_volume(connection_info, self.disk_info)
libvirt_driver.disconnect_volume(connection_info, "vde")
expected_commands = [
('mkdir', '-p', export_mnt_base),
('mount', '-t', 'cifs', '-o', 'user=guest,uid=107,gid=105',
export_string, export_mnt_base),
('umount', export_mnt_base)]
self.assertEqual(expected_commands, self.executes)

View File

@ -280,7 +280,7 @@ libvirt_volume_drivers = [
'rbd=nova.virt.libvirt.volume.volume.LibvirtNetVolumeDriver',
'sheepdog=nova.virt.libvirt.volume.volume.LibvirtNetVolumeDriver',
'nfs=nova.virt.libvirt.volume.volume.LibvirtNFSVolumeDriver',
'smbfs=nova.virt.libvirt.volume.volume.LibvirtSMBFSVolumeDriver',
'smbfs=nova.virt.libvirt.volume.smbfs.LibvirtSMBFSVolumeDriver',
'aoe=nova.virt.libvirt.volume.aoe.LibvirtAOEVolumeDriver',
'glusterfs='
'nova.virt.libvirt.volume.glusterfs.LibvirtGlusterfsVolumeDriver',

View File

@ -0,0 +1,101 @@
# 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.
import os
import re
from oslo_config import cfg
from nova import paths
from nova import utils
from nova.virt.libvirt import utils as libvirt_utils
from nova.virt.libvirt.volume import remotefs
from nova.virt.libvirt.volume import volume as libvirt_volume
volume_opts = [
cfg.StrOpt('smbfs_mount_point_base',
default=paths.state_path_def('mnt'),
help='Directory where the SMBFS shares are mounted on the '
'compute node'),
cfg.StrOpt('smbfs_mount_options',
default='',
help='Mount options passed to the SMBFS client. See '
'mount.cifs man page for details. Note that the '
'libvirt-qemu uid and gid must be specified.'),
]
CONF = cfg.CONF
CONF.register_opts(volume_opts, 'libvirt')
class LibvirtSMBFSVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
"""Class implements libvirt part of volume driver for SMBFS."""
def __init__(self, connection):
super(LibvirtSMBFSVolumeDriver,
self).__init__(connection, is_block_dev=False)
self.username_regex = re.compile(
r"(user(?:name)?)=(?:[^ ,]+\\)?([^ ,]+)")
def _get_device_path(self, connection_info):
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
volume_path = os.path.join(mount_path,
connection_info['data']['name'])
return volume_path
def _get_mount_path(self, smbfs_share):
mount_path = os.path.join(CONF.libvirt.smbfs_mount_point_base,
utils.get_hash_str(smbfs_share))
return mount_path
def get_config(self, connection_info, disk_info):
"""Returns xml for libvirt."""
conf = super(LibvirtSMBFSVolumeDriver,
self).get_config(connection_info, disk_info)
conf.source_type = 'file'
conf.driver_cache = 'writethrough'
conf.source_path = connection_info['data']['device_path']
conf.driver_format = connection_info['data'].get('format', 'raw')
return conf
def connect_volume(self, connection_info, disk_info):
"""Connect the volume."""
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
if not libvirt_utils.is_mounted(mount_path, smbfs_share):
mount_options = self._parse_mount_options(connection_info)
remotefs.mount_share(mount_path, smbfs_share,
export_type='cifs', options=mount_options)
device_path = self._get_device_path(connection_info)
connection_info['data']['device_path'] = device_path
def disconnect_volume(self, connection_info, disk_dev):
"""Disconnect the volume."""
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
remotefs.unmount_share(mount_path, smbfs_share)
def _parse_mount_options(self, connection_info):
mount_options = " ".join(
[connection_info['data'].get('options') or '',
CONF.libvirt.smbfs_mount_options])
if not self.username_regex.findall(mount_options):
mount_options = mount_options + ' -o username=guest'
else:
# Remove the Domain Name from user name
mount_options = self.username_regex.sub(r'\1=\2', mount_options)
return mount_options.strip(", ").split(' ')

View File

@ -17,7 +17,6 @@
"""Volume drivers for libvirt."""
import os
import re
from os_brick.initiator import connector
from oslo_concurrency import processutils
@ -33,7 +32,6 @@ from nova import paths
from nova import utils
from nova.virt.libvirt import config as vconfig
from nova.virt.libvirt import utils as libvirt_utils
from nova.virt.libvirt.volume import remotefs
LOG = logging.getLogger(__name__)
@ -56,15 +54,6 @@ volume_opts = [
cfg.StrOpt('nfs_mount_options',
help='Mount options passed to the NFS client. See section '
'of the nfs man page for details'),
cfg.StrOpt('smbfs_mount_point_base',
default=paths.state_path_def('mnt'),
help='Directory where the SMBFS shares are mounted on the '
'compute node'),
cfg.StrOpt('smbfs_mount_options',
default='',
help='Mount options passed to the SMBFS client. See '
'mount.cifs man page for details. Note that the '
'libvirt-qemu uid and gid must be specified.'),
cfg.BoolOpt('iscsi_use_multipath',
default=False,
help='Use multipath connection of the iSCSI volume'),
@ -417,67 +406,3 @@ class LibvirtNFSVolumeDriver(LibvirtBaseVolumeDriver):
LOG.warn(_LW("%s is already mounted"), nfs_share)
else:
raise
class LibvirtSMBFSVolumeDriver(LibvirtBaseVolumeDriver):
"""Class implements libvirt part of volume driver for SMBFS."""
def __init__(self, connection):
super(LibvirtSMBFSVolumeDriver,
self).__init__(connection, is_block_dev=False)
self.username_regex = re.compile(
r"(user(?:name)?)=(?:[^ ,]+\\)?([^ ,]+)")
def _get_device_path(self, connection_info):
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
volume_path = os.path.join(mount_path,
connection_info['data']['name'])
return volume_path
def _get_mount_path(self, smbfs_share):
mount_path = os.path.join(CONF.libvirt.smbfs_mount_point_base,
utils.get_hash_str(smbfs_share))
return mount_path
def get_config(self, connection_info, disk_info):
"""Returns xml for libvirt."""
conf = super(LibvirtSMBFSVolumeDriver,
self).get_config(connection_info, disk_info)
conf.source_type = 'file'
conf.driver_cache = 'writethrough'
conf.source_path = connection_info['data']['device_path']
conf.driver_format = connection_info['data'].get('format', 'raw')
return conf
def connect_volume(self, connection_info, disk_info):
"""Connect the volume."""
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
if not libvirt_utils.is_mounted(mount_path, smbfs_share):
mount_options = self._parse_mount_options(connection_info)
remotefs.mount_share(mount_path, smbfs_share,
export_type='cifs', options=mount_options)
device_path = self._get_device_path(connection_info)
connection_info['data']['device_path'] = device_path
def disconnect_volume(self, connection_info, disk_dev):
"""Disconnect the volume."""
smbfs_share = connection_info['data']['export']
mount_path = self._get_mount_path(smbfs_share)
remotefs.unmount_share(mount_path, smbfs_share)
def _parse_mount_options(self, connection_info):
mount_options = " ".join(
[connection_info['data'].get('options') or '',
CONF.libvirt.smbfs_mount_options])
if not self.username_regex.findall(mount_options):
mount_options = mount_options + ' -o username=guest'
else:
# Remove the Domain Name from user name
mount_options = self.username_regex.sub(r'\1=\2', mount_options)
return mount_options.strip(", ").split(' ')