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 'VDI_RESET_ON_BOOT/2',
45 'VDI_UPDATE'
46]
48CONFIGURATION = [
49 ['location', 'local ZFS directory path (required)']
50]
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}
65def is_zfs_available():
66 return util.find_executable('zfs') and \
67 util.pathexists('/sys/module/zfs/initstate')
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'
76class ZFSSR(FileSR.FileSR):
77 DRIVER_TYPE = 'zfs'
79 @override
80 @staticmethod
81 def handles(type) -> bool:
82 return type == ZFSSR.DRIVER_TYPE
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)
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)
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)
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)
120 @override
121 def detach(self, sr_uuid) -> None:
122 return super(ZFSSR, self).detach(sr_uuid)
124 @override
125 def vdi(self, uuid) -> VDI.VDI:
126 return ZFSFileVDI(self, uuid)
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)
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 = {}
141 self.xenstore_data['storage-type'] = ZFSSR.DRIVER_TYPE
143 return super(ZFSFileVDI, self).attach(sr_uuid, vdi_uuid)
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)