Coverage for drivers/ZFSSR.py : 63%

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/>.
17import SR
18import SRCommand
20import FileSR
22import util
23import xs_errors
25CAPABILITIES = [
26 'SR_PROBE',
27 'SR_UPDATE',
28 'VDI_CREATE',
29 'VDI_DELETE',
30 'VDI_ATTACH',
31 'VDI_DETACH',
32 'VDI_CLONE',
33 'VDI_SNAPSHOT',
34 'VDI_RESIZE',
35 'VDI_MIRROR',
36 'VDI_GENERATE_CONFIG',
37 'ATOMIC_PAUSE',
38 'VDI_CONFIG_CBT',
39 'VDI_ACTIVATE',
40 'VDI_DEACTIVATE',
41 'THIN_PROVISIONING'
42]
44CONFIGURATION = [
45 ['location', 'local ZFS directory path (required)']
46]
48DRIVER_INFO = {
49 'name': 'Local ZFS VHD',
50 'description':
51 'SR plugin which represents disks as VHD files stored on a ZFS disk',
52 'vendor': 'Vates SAS',
53 'copyright': '(C) 2020 Vates SAS',
54 'driver_version': '1.0',
55 'required_api_version': '1.0',
56 'capabilities': CAPABILITIES,
57 'configuration': CONFIGURATION
58}
61def is_zfs_available():
62 import distutils.spawn
63 return distutils.spawn.find_executable('zfs') and \
64 util.pathexists('/sys/module/zfs/initstate')
67def is_zfs_path(path):
68 cmd = ['findmnt', '-o', 'FSTYPE', '-n', path]
69 fs_type = util.pread2(cmd).split('\n')[0]
70 return fs_type == 'zfs'
73class ZFSSR(FileSR.FileSR):
74 DRIVER_TYPE = 'zfs'
76 @staticmethod
77 def handles(type):
78 return type == ZFSSR.DRIVER_TYPE
80 def load(self, sr_uuid):
81 if not is_zfs_available():
82 raise xs_errors.XenError(
83 'SRUnavailable',
84 opterr='zfs is not installed or module is not loaded'
85 )
86 return super(ZFSSR, self).load(sr_uuid)
88 def create(self, sr_uuid, size):
89 if not is_zfs_path(self.remotepath):
90 raise xs_errors.XenError(
91 'ZFSSRCreate',
92 opterr='Cannot create SR, path is not a ZFS mountpoint'
93 )
94 return super(ZFSSR, self).create(sr_uuid, size)
96 def delete(self, sr_uuid):
97 if not self._checkmount():
98 raise xs_errors.XenError(
99 'ZFSSRDelete',
100 opterr='ZFS SR is not mounted or uses an invalid FS type'
101 )
102 return super(ZFSSR, self).delete(sr_uuid)
104 def attach(self, sr_uuid):
105 if not is_zfs_path(self.remotepath):
106 raise xs_errors.XenError(
107 'SRUnavailable',
108 opterr='Invalid ZFS path'
109 )
110 return super(ZFSSR, self).attach(sr_uuid)
112 def detach(self, sr_uuid):
113 return super(ZFSSR, self).detach(sr_uuid)
115 def vdi(self, uuid, loadLocked=False):
116 return ZFSFileVDI(self, uuid)
118 # Ensure _checkmount is overridden to prevent bad behaviors in FileSR.
119 def _checkmount(self):
120 return super(ZFSSR, self)._checkmount() and \
121 is_zfs_path(self.remotepath)
124class ZFSFileVDI(FileSR.FileVDI):
125 def attach(self, sr_uuid, vdi_uuid):
126 if not hasattr(self, 'xenstore_data'):
127 self.xenstore_data = {}
129 self.xenstore_data['storage-type'] = ZFSSR.DRIVER_TYPE
131 return super(ZFSFileVDI, self).attach(sr_uuid, vdi_uuid)
134if __name__ == '__main__': 134 ↛ 135line 134 didn't jump to line 135, because the condition on line 134 was never true
135 SRCommand.run(ZFSSR, DRIVER_INFO)
136else:
137 SR.registerSR(ZFSSR)