From 7c92bf438a3d76487110aacf713e79939e44af5c Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 25 Jan 2013 13:15:09 +0000 Subject: [PATCH] Move libvirt NFS volume driver impl into volume.py For inexplicable reasons the NFS volume driver was put into a different file than all the other libvirt volume driver impls. The NFS code isn't so large & complex that it needs to be in a different place than everything else. Move the code into the main volume.py file. To avoid breaking existing deployments, the original class has to be a trivial subclass of the new module. Any use of it will trigger a deprecation warning. This allows time for users to update their 'libvirt_volume_drivers' config (in the unlikely event they have altered from the default setting). Change-Id: I26d957e4ee33938b45dc1cad0fe32a2968520a4a Signed-off-by: Daniel P. Berrange --- nova/tests/test_libvirt.py | 3 +- nova/virt/libvirt/driver.py | 2 +- nova/virt/libvirt/volume.py | 71 +++++++++++++++++++++++++- nova/virt/libvirt/volume_nfs.py | 90 +++++---------------------------- 4 files changed, 86 insertions(+), 80 deletions(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 06db4f5ffe13..2c1866a2c6b7 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -61,7 +61,6 @@ from nova.virt.libvirt import firewall from nova.virt.libvirt import imagebackend from nova.virt.libvirt import utils as libvirt_utils from nova.virt.libvirt import volume -from nova.virt.libvirt import volume_nfs try: @@ -412,7 +411,7 @@ class LibvirtVolumeTestCase(test.TestCase): mnt_base = '/mnt' self.flags(nfs_mount_point_base=mnt_base) - libvirt_driver = volume_nfs.NfsVolumeDriver(self.fake_conn) + libvirt_driver = volume.LibvirtNFSVolumeDriver(self.fake_conn) export_string = '192.168.1.1:/nfs/share1' name = 'volume-00001' export_mnt_base = os.path.join(mnt_base, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index bd2f51e696d8..fef44d6b6308 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -150,7 +150,7 @@ libvirt_opts = [ 'fake=nova.virt.libvirt.volume.LibvirtFakeVolumeDriver', 'rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver', 'sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver', - 'nfs=nova.virt.libvirt.volume_nfs.NfsVolumeDriver' + 'nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver' ], help='Libvirt handlers for remote volumes.'), cfg.StrOpt('libvirt_disk_prefix', diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index d02db22f35e0..f8ed95e0fd17 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -17,6 +17,7 @@ """Volume drivers for libvirt.""" +import hashlib import os import time @@ -24,6 +25,7 @@ from nova import exception from nova.openstack.common import cfg from nova.openstack.common import lockutils from nova.openstack.common import log as logging +from nova import paths from nova import utils from nova.virt.libvirt import config as vconfig from nova.virt.libvirt import utils as virtutils @@ -40,7 +42,14 @@ volume_opts = [ cfg.StrOpt('rbd_secret_uuid', default=None, help='the libvirt uuid of the secret for the rbd_user' - 'volumes') + 'volumes'), + cfg.StrOpt('nfs_mount_point_base', + default=paths.state_path_def('mnt'), + help='Dir where the nfs volume is mounted on the compute node'), + cfg.StrOpt('nfs_mount_options', + default=None, + help='Mount options passed to the nfs client. See section ' + 'of the nfs man page for details'), ] CONF = cfg.CONF @@ -246,3 +255,63 @@ class LibvirtISCSIVolumeDriver(LibvirtBaseVolumeDriver): check_exit_code=[0, 21, 255]) self._run_iscsiadm(iscsi_properties, ('--op', 'delete'), check_exit_code=[0, 21, 255]) + + +class LibvirtNFSVolumeDriver(LibvirtBaseVolumeDriver): + """Class implements libvirt part of volume driver for NFS.""" + + def __init__(self, connection): + """Create back-end to nfs.""" + super(LibvirtNFSVolumeDriver, + self).__init__(connection, is_block_dev=False) + + def connect_volume(self, connection_info, mount_device): + """Connect the volume. Returns xml for libvirt.""" + conf = super(LibvirtNFSVolumeDriver, + self).connect_volume(connection_info, mount_device) + path = self._ensure_mounted(connection_info['data']['export']) + path = os.path.join(path, connection_info['data']['name']) + conf.source_type = 'file' + conf.source_path = path + return conf + + def _ensure_mounted(self, nfs_export): + """ + @type nfs_export: string + """ + mount_path = os.path.join(CONF.nfs_mount_point_base, + self.get_hash_str(nfs_export)) + self._mount_nfs(mount_path, nfs_export, ensure=True) + return mount_path + + def _mount_nfs(self, mount_path, nfs_share, ensure=False): + """Mount nfs export to mount path.""" + if not self._path_exists(mount_path): + utils.execute('mkdir', '-p', mount_path) + + # Construct the NFS mount command. + nfs_cmd = ['mount', '-t', 'nfs'] + if CONF.nfs_mount_options is not None: + nfs_cmd.extend(['-o', CONF.nfs_mount_options]) + nfs_cmd.extend([nfs_share, mount_path]) + + try: + utils.execute(*nfs_cmd, run_as_root=True) + except exception.ProcessExecutionError as exc: + if ensure and 'already mounted' in exc.message: + LOG.warn(_("%s is already mounted"), nfs_share) + else: + raise + + @staticmethod + def get_hash_str(base_str): + """returns string that represents hash of base_str (in hex format).""" + return hashlib.md5(base_str).hexdigest() + + @staticmethod + def _path_exists(path): + """Check path.""" + try: + return utils.execute('stat', path, run_as_root=True) + except exception.ProcessExecutionError: + return False diff --git a/nova/virt/libvirt/volume_nfs.py b/nova/virt/libvirt/volume_nfs.py index fc10863b53c2..668969ed2ab8 100755 --- a/nova/virt/libvirt/volume_nfs.py +++ b/nova/virt/libvirt/volume_nfs.py @@ -15,88 +15,26 @@ # License for the specific language governing permissions and limitations # under the License. -"""Volume driver for using NFS as volumes storage. Nova compute part.""" +"""Deprecated file, kept for back-compat only. To be removed in Hxxxx.""" -import hashlib -import os - -from nova import exception -from nova.openstack.common import cfg from nova.openstack.common import log as logging -from nova import paths -from nova import utils from nova.virt.libvirt import volume LOG = logging.getLogger(__name__) -volume_opts = [ - cfg.StrOpt('nfs_mount_point_base', - default=paths.state_path_def('mnt'), - help='Base dir where nfs expected to be mounted on compute'), - cfg.StrOpt('nfs_mount_options', - default=None, - help='Mount options passed to the nfs client. See section ' - 'of the nfs man page for details'), -] -CONF = cfg.CONF -CONF.register_opts(volume_opts) +class NfsVolumeDriver(volume.LibvirtNFSVolumeDriver): + """Deprecated driver for NFS, renamed to LibvirtNFSVolumeDriver + and moved into the main volume.py module. Kept for backwards + compatibility in the Grizzly cycle to give users opportunity + to configure before its removal in the Hxxxx cycle.""" -class NfsVolumeDriver(volume.LibvirtBaseVolumeDriver): - """Class implements libvirt part of volume driver for NFS.""" - - def __init__(self, connection): - """Create back-end to nfs.""" + def __init__(self, *args, **kwargs): super(NfsVolumeDriver, - self).__init__(connection, is_block_dev=False) - - def connect_volume(self, connection_info, mount_device): - """Connect the volume. Returns xml for libvirt.""" - conf = super(NfsVolumeDriver, - self).connect_volume(connection_info, mount_device) - path = self._ensure_mounted(connection_info['data']['export']) - path = os.path.join(path, connection_info['data']['name']) - conf.source_type = 'file' - conf.source_path = path - return conf - - def _ensure_mounted(self, nfs_export): - """ - @type nfs_export: string - """ - mount_path = os.path.join(CONF.nfs_mount_point_base, - self.get_hash_str(nfs_export)) - self._mount_nfs(mount_path, nfs_export, ensure=True) - return mount_path - - def _mount_nfs(self, mount_path, nfs_share, ensure=False): - """Mount nfs export to mount path.""" - if not self._path_exists(mount_path): - utils.execute('mkdir', '-p', mount_path) - - # Construct the NFS mount command. - nfs_cmd = ['mount', '-t', 'nfs'] - if CONF.nfs_mount_options is not None: - nfs_cmd.extend(['-o', CONF.nfs_mount_options]) - nfs_cmd.extend([nfs_share, mount_path]) - - try: - utils.execute(*nfs_cmd, run_as_root=True) - except exception.ProcessExecutionError as exc: - if ensure and 'already mounted' in exc.message: - LOG.warn(_("%s is already mounted"), nfs_share) - else: - raise - - @staticmethod - def get_hash_str(base_str): - """returns string that represents hash of base_str (in hex format).""" - return hashlib.md5(base_str).hexdigest() - - @staticmethod - def _path_exists(path): - """Check path.""" - try: - return utils.execute('stat', path, run_as_root=True) - except exception.ProcessExecutionError: - return False + self).__init__(*args, **kwargs) + LOG.deprecated( + _("The nova.virt.libvirt.volume_nfs.NfsVolumeDriver " + "class is deprecated and will be removed in the " + "Hxxxx release. Please update nova.conf so that " + "the 'libvirt_volume_drivers' parameter refers to " + "nova.virt.libvirt.volume.LibvirtNFSVolumeDriver."))