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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

#!/usr/bin/env python 

# 

# Copyright (C) 2020  Vates SAS 

# 

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

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

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

# (at your option) any later version. 

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

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

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

# GNU General Public License for more details. 

# 

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

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

 

import SR 

import SRCommand 

 

import FileSR 

 

import util 

import xs_errors 

 

CAPABILITIES = [ 

    'SR_PROBE', 

    'SR_UPDATE', 

    'VDI_CREATE', 

    'VDI_DELETE', 

    'VDI_ATTACH', 

    'VDI_DETACH', 

    'VDI_CLONE', 

    'VDI_SNAPSHOT', 

    'VDI_RESIZE', 

    'VDI_MIRROR', 

    'VDI_GENERATE_CONFIG', 

    'ATOMIC_PAUSE', 

    'VDI_CONFIG_CBT', 

    'VDI_ACTIVATE', 

    'VDI_DEACTIVATE', 

    'THIN_PROVISIONING' 

] 

 

CONFIGURATION = [ 

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

] 

 

DRIVER_INFO = { 

    'name': 'Local ZFS VHD', 

    'description': 

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

    'vendor': 'Vates SAS', 

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

    'driver_version': '1.0', 

    'required_api_version': '1.0', 

    'capabilities': CAPABILITIES, 

    'configuration': CONFIGURATION 

} 

 

 

def is_zfs_available(): 

    import distutils.spawn 

    return distutils.spawn.find_executable('zfs') and \ 

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

 

 

def is_zfs_path(path): 

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

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

    return fs_type == 'zfs' 

 

 

class ZFSSR(FileSR.FileSR): 

    DRIVER_TYPE = 'zfs' 

 

    @staticmethod 

    def handles(type): 

        return type == ZFSSR.DRIVER_TYPE 

 

    def load(self, sr_uuid): 

        if not is_zfs_available(): 

            raise xs_errors.XenError( 

                'SRUnavailable', 

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

            ) 

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

 

    def create(self, sr_uuid, size): 

        if not is_zfs_path(self.remotepath): 

            raise xs_errors.XenError( 

                'ZFSSRCreate', 

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

            ) 

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

 

    def delete(self, sr_uuid): 

        if not self._checkmount(): 

            raise xs_errors.XenError( 

                'ZFSSRDelete', 

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

            ) 

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

 

    def attach(self, sr_uuid): 

        if not is_zfs_path(self.remotepath): 

            raise xs_errors.XenError( 

                'SRUnavailable', 

                opterr='Invalid ZFS path' 

            ) 

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

 

    def detach(self, sr_uuid): 

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

 

    def vdi(self, uuid, loadLocked=False): 

        return ZFSFileVDI(self, uuid) 

 

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

    def _checkmount(self): 

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

            is_zfs_path(self.remotepath) 

 

 

class ZFSFileVDI(FileSR.FileVDI): 

    def attach(self, sr_uuid, vdi_uuid): 

        if not hasattr(self, 'xenstore_data'): 

            self.xenstore_data = {} 

 

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

 

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

 

 

135if __name__ == '__main__': 

    SRCommand.run(ZFSSR, DRIVER_INFO) 

else: 

    SR.registerSR(ZFSSR)