Coverage for nova/virt/libvirt/volume/fs.py: 94%

36 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-24 11:16 +0000

1# Copyright 2015 IBM Corp. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); you may 

4# not use this file except in compliance with the License. You may obtain 

5# a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

12# License for the specific language governing permissions and limitations 

13# under the License. 

14 

15import abc 

16import os 

17 

18from nova import utils 

19from nova.virt.libvirt.volume import mount 

20from nova.virt.libvirt.volume import volume as libvirt_volume 

21 

22 

23class LibvirtBaseFileSystemVolumeDriver( 

24 libvirt_volume.LibvirtBaseVolumeDriver, metaclass=abc.ABCMeta): 

25 """The base class for file system type volume drivers""" 

26 

27 def __init__(self, host): 

28 super(LibvirtBaseFileSystemVolumeDriver, 

29 self).__init__(host, is_block_dev=False) 

30 

31 @abc.abstractmethod 

32 def _get_mount_point_base(self): 

33 """Return the mount point path prefix. 

34 

35 This is used to build the device path. 

36 

37 :returns: The mount point path prefix. 

38 """ 

39 raise NotImplementedError('_get_mount_point_base') 

40 

41 def _normalize_export(self, export): 

42 """Normalize the export (share) if necessary. 

43 

44 Subclasses should override this method if they have a non-standard 

45 export value, e.g. if the export is a URL. By default this method just 

46 returns the export value passed in unchanged. 

47 

48 :param export: The export (share) value to normalize. 

49 :returns: The normalized export value. 

50 """ 

51 return export 

52 

53 def _get_mount_path(self, connection_info): 

54 """Returns the mount path prefix using the mount point base and share. 

55 

56 :param connection_info: dict of the form 

57 

58 :: 

59 

60 connection_info = { 

61 'data': { 

62 'export': the file system share, 

63 ... 

64 } 

65 ... 

66 } 

67 

68 :returns: The mount path prefix. 

69 """ 

70 share = self._normalize_export(connection_info['data']['export']) 

71 return os.path.join(self._get_mount_point_base(), 

72 utils.get_hash_str(share)) 

73 

74 def _get_device_path(self, connection_info): 

75 """Returns the hashed path to the device. 

76 

77 :param connection_info: dict of the form 

78 

79 :: 

80 

81 connection_info = { 

82 'data': { 

83 'export': the file system share, 

84 'name': the name of the device, 

85 ... 

86 } 

87 ... 

88 } 

89 

90 :returns: The full path to the device. 

91 """ 

92 mount_path = self._get_mount_path(connection_info) 

93 return os.path.join(mount_path, connection_info['data']['name']) 

94 

95 

96class LibvirtMountedFileSystemVolumeDriver(LibvirtBaseFileSystemVolumeDriver, 

97 metaclass=abc.ABCMeta): 

98 # NOTE(mdbooth): Hopefully we'll get to the point where everything which 

99 # previously subclassed LibvirtBaseFileSystemVolumeDriver now subclasses 

100 # LibvirtMountedFileSystemVolumeDriver. If we get there, we should fold 

101 # this class into the base class. 

102 def __init__(self, host, fstype): 

103 super(LibvirtMountedFileSystemVolumeDriver, self).__init__(host) 

104 

105 self.fstype = fstype 

106 

107 def connect_volume(self, connection_info, instance): 

108 """Connect the volume.""" 

109 export = connection_info['data']['export'] 

110 vol_name = connection_info['data']['name'] 

111 mountpoint = self._get_mount_path(connection_info) 

112 

113 mount.mount(self.fstype, export, vol_name, mountpoint, instance, 

114 self._mount_options(connection_info)) 

115 

116 connection_info['data']['device_path'] = \ 

117 self._get_device_path(connection_info) 

118 

119 def disconnect_volume(self, connection_info, instance, force=False): 

120 """Disconnect the volume.""" 

121 vol_name = connection_info['data']['name'] 

122 mountpoint = self._get_mount_path(connection_info) 

123 

124 return mount.umount(vol_name, mountpoint, instance) 

125 

126 @abc.abstractmethod 

127 def _mount_options(self, connection_info): 

128 """Return a list of additional arguments to pass to the mount command. 

129 """ 

130 pass