Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python3 

2# 

3# Copyright (C) 2020 Vates SAS 

4# 

5# This program is free software: you can redistribute it and/or modify 

6# it under the terms of the GNU General Public License as published by 

7# the Free Software Foundation, either version 3 of the License, or 

8# (at your option) any later version. 

9# This program is distributed in the hope that it will be useful, 

10# but WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

12# GNU General Public License for more details. 

13# 

14# You should have received a copy of the GNU General Public License 

15# along with this program. If not, see <https://www.gnu.org/licenses/>. 

16 

17from sm_typing import override 

18 

19import SR 

20import SRCommand 

21import VDI 

22 

23import FileSR 

24 

25import util 

26import xs_errors 

27 

28CAPABILITIES = [ 

29 'SR_UPDATE', 

30 'VDI_CREATE', 

31 'VDI_DELETE', 

32 'VDI_ATTACH', 

33 'VDI_DETACH', 

34 'VDI_CLONE', 

35 'VDI_SNAPSHOT', 

36 'VDI_RESIZE', 

37 'VDI_MIRROR', 

38 'VDI_GENERATE_CONFIG', 

39 'ATOMIC_PAUSE', 

40 'VDI_CONFIG_CBT', 

41 'VDI_ACTIVATE', 

42 'VDI_DEACTIVATE', 

43 'THIN_PROVISIONING' 

44] 

45 

46CONFIGURATION = [ 

47 ['location', 'local ZFS directory path (required)'] 

48] 

49 

50DRIVER_INFO = { 

51 'name': 'Local ZFS VHD', 

52 'description': 

53 'SR plugin which represents disks as VHD files stored on a ZFS disk', 

54 'vendor': 'Vates SAS', 

55 'copyright': '(C) 2020 Vates SAS', 

56 'driver_version': '1.0', 

57 'required_api_version': '1.0', 

58 'capabilities': CAPABILITIES, 

59 'configuration': CONFIGURATION 

60} 

61 

62 

63def is_zfs_available(): 

64 return util.find_executable('zfs') and \ 

65 util.pathexists('/sys/module/zfs/initstate') 

66 

67 

68def is_zfs_path(path): 

69 cmd = ['findmnt', '-o', 'FSTYPE', '-n', path] 

70 fs_type = util.pread2(cmd).split('\n')[0] 

71 return fs_type == 'zfs' 

72 

73 

74class ZFSSR(FileSR.FileSR): 

75 DRIVER_TYPE = 'zfs' 

76 

77 @override 

78 @staticmethod 

79 def handles(type) -> bool: 

80 return type == ZFSSR.DRIVER_TYPE 

81 

82 @override 

83 def load(self, sr_uuid) -> None: 

84 if not is_zfs_available(): 

85 raise xs_errors.XenError( 

86 'SRUnavailable', 

87 opterr='zfs is not installed or module is not loaded' 

88 ) 

89 return super(ZFSSR, self).load(sr_uuid) 

90 

91 @override 

92 def create(self, sr_uuid, size) -> None: 

93 if not is_zfs_path(self.remotepath): 

94 raise xs_errors.XenError( 

95 'ZFSSRCreate', 

96 opterr='Cannot create SR, path is not a ZFS mountpoint' 

97 ) 

98 return super(ZFSSR, self).create(sr_uuid, size) 

99 

100 @override 

101 def delete(self, sr_uuid) -> None: 

102 if not self._checkmount(): 

103 raise xs_errors.XenError( 

104 'ZFSSRDelete', 

105 opterr='ZFS SR is not mounted or uses an invalid FS type' 

106 ) 

107 return super(ZFSSR, self).delete(sr_uuid) 

108 

109 @override 

110 def attach(self, sr_uuid) -> None: 

111 if not is_zfs_path(self.remotepath): 

112 raise xs_errors.XenError( 

113 'SRUnavailable', 

114 opterr='Invalid ZFS path' 

115 ) 

116 super(ZFSSR, self).attach(sr_uuid) 

117 

118 @override 

119 def detach(self, sr_uuid) -> None: 

120 return super(ZFSSR, self).detach(sr_uuid) 

121 

122 @override 

123 def vdi(self, uuid, loadLocked=False) -> VDI.VDI: 

124 return ZFSFileVDI(self, uuid) 

125 

126 # Ensure _checkmount is overridden to prevent bad behaviors in FileSR. 

127 @override 

128 def _checkmount(self) -> bool: 

129 return super(ZFSSR, self)._checkmount() and \ 

130 is_zfs_path(self.remotepath) 

131 

132 

133class ZFSFileVDI(FileSR.FileVDI): 

134 @override 

135 def attach(self, sr_uuid, vdi_uuid) -> str: 

136 if not hasattr(self, 'xenstore_data'): 

137 self.xenstore_data = {} 

138 

139 self.xenstore_data['storage-type'] = ZFSSR.DRIVER_TYPE 

140 

141 return super(ZFSFileVDI, self).attach(sr_uuid, vdi_uuid) 

142 

143 

144if __name__ == '__main__': 144 ↛ 145line 144 didn't jump to line 145, because the condition on line 144 was never true

145 SRCommand.run(ZFSSR, DRIVER_INFO) 

146else: 

147 SR.registerSR(ZFSSR)