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 'VDI_RESET_ON_BOOT/2', 

45 'VDI_UPDATE' 

46] 

47 

48CONFIGURATION = [ 

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

50] 

51 

52DRIVER_INFO = { 

53 'name': 'Local ZFS VHD and QCOW2', 

54 'description': 

55 'SR plugin which represents disks as VHD and QCOW2 files stored on a ZFS disk', 

56 'vendor': 'Vates SAS', 

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

58 'driver_version': '1.0', 

59 'required_api_version': '1.0', 

60 'capabilities': CAPABILITIES, 

61 'configuration': CONFIGURATION 

62} 

63 

64 

65def is_zfs_available(): 

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

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

68 

69 

70def is_zfs_path(path): 

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

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

73 return fs_type == 'zfs' 

74 

75 

76class ZFSSR(FileSR.FileSR): 

77 DRIVER_TYPE = 'zfs' 

78 

79 @override 

80 @staticmethod 

81 def handles(type) -> bool: 

82 return type == ZFSSR.DRIVER_TYPE 

83 

84 @override 

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

86 if not is_zfs_available(): 

87 raise xs_errors.XenError( 

88 'SRUnavailable', 

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

90 ) 

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

92 

93 @override 

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

95 if not is_zfs_path(self.remotepath): 

96 raise xs_errors.XenError( 

97 'ZFSSRCreate', 

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

99 ) 

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

101 

102 @override 

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

104 if not self._checkmount(): 

105 raise xs_errors.XenError( 

106 'ZFSSRDelete', 

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

108 ) 

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

110 

111 @override 

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

113 if not is_zfs_path(self.remotepath): 

114 raise xs_errors.XenError( 

115 'SRUnavailable', 

116 opterr='Invalid ZFS path' 

117 ) 

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

119 

120 @override 

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

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

123 

124 @override 

125 def vdi(self, uuid) -> VDI.VDI: 

126 return ZFSFileVDI(self, uuid) 

127 

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

129 @override 

130 def _checkmount(self) -> bool: 

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

132 is_zfs_path(self.remotepath) 

133 

134 

135class ZFSFileVDI(FileSR.FileVDI): 

136 @override 

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

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

139 self.xenstore_data = {} 

140 

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

142 

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

144 

145 

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

147 SRCommand.run(ZFSSR, DRIVER_INFO) 

148else: 

149 SR.registerSR(ZFSSR)