Coverage for drivers/ZFSSR.py : 68%

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/>.
17from sm_typing import override
19import SR
20import SRCommand
21import VDI
23import FileSR
25import util
26import xs_errors
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]
46CONFIGURATION = [
47 ['location', 'local ZFS directory path (required)']
48]
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}
63def is_zfs_available():
64 return util.find_executable('zfs') and \
65 util.pathexists('/sys/module/zfs/initstate')
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'
74class ZFSSR(FileSR.FileSR):
75 DRIVER_TYPE = 'zfs'
77 @override
78 @staticmethod
79 def handles(type) -> bool:
80 return type == ZFSSR.DRIVER_TYPE
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)
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)
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)
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)
118 @override
119 def detach(self, sr_uuid) -> None:
120 return super(ZFSSR, self).detach(sr_uuid)
122 @override
123 def vdi(self, uuid, loadLocked=False) -> VDI.VDI:
124 return ZFSFileVDI(self, uuid)
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)
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 = {}
139 self.xenstore_data['storage-type'] = ZFSSR.DRIVER_TYPE
141 return super(ZFSFileVDI, self).attach(sr_uuid, vdi_uuid)
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)