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/python3 

2# 

3# Copyright (C) Citrix Systems Inc. 

4# 

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

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

7# by the Free Software Foundation; version 2.1 only. 

8# 

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 Lesser General Public License for more details. 

13# 

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

15# along with this program; if not, write to the Free Software Foundation, Inc., 

16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 

17# 

18# EXTSR: Based on local-file storage repository, mounts ext4 partition 

19 

20from sm_typing import override 

21 

22import SR 

23from SR import deviceCheck 

24import VDI 

25import SRCommand 

26import FileSR 

27import util 

28import lvutil 

29import scsiutil 

30 

31import lock 

32import os 

33import xs_errors 

34from constants import EXT_PREFIX 

35 

36CAPABILITIES = ["SR_PROBE", "SR_UPDATE", "SR_SUPPORTS_LOCAL_CACHING", 

37 "VDI_CREATE", "VDI_DELETE", "VDI_ATTACH", "VDI_DETACH", 

38 "VDI_UPDATE", "VDI_CLONE", "VDI_SNAPSHOT", "VDI_RESIZE", "VDI_MIRROR", 

39 "VDI_GENERATE_CONFIG", 

40 "VDI_RESET_ON_BOOT/2", "ATOMIC_PAUSE", "VDI_CONFIG_CBT", 

41 "VDI_ACTIVATE", "VDI_DEACTIVATE", "THIN_PROVISIONING", "VDI_READ_CACHING"] 

42 

43CONFIGURATION = [['device', 'local device path (required) (e.g. /dev/sda3)']] 

44 

45DRIVER_INFO = { 

46 'name': 'Local EXT4 VHD and QCOW2', 

47 'description': 'SR plugin which represents disks as VHD and QCOW2 files stored on a local EXT4 filesystem, created inside an LVM volume', 

48 'vendor': 'Citrix Systems Inc', 

49 'copyright': '(C) 2008 Citrix Systems Inc', 

50 'driver_version': '1.0', 

51 'required_api_version': '1.0', 

52 'capabilities': CAPABILITIES, 

53 'configuration': CONFIGURATION 

54 } 

55 

56DRIVER_CONFIG = {"ATTACH_FROM_CONFIG_WITH_TAPDISK": True} 

57 

58 

59class EXTSR(FileSR.FileSR): 

60 """EXT4 Local file storage repository""" 

61 

62 @override 

63 @staticmethod 

64 def handles(srtype) -> bool: 

65 return srtype == 'ext' 

66 

67 @override 

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

69 self.ops_exclusive = FileSR.OPS_EXCLUSIVE 

70 self.lock = lock.Lock(lock.LOCK_TYPE_SR, self.uuid) 

71 self.sr_vditype = SR.DEFAULT_TAP 

72 

73 self.path = os.path.join(SR.MOUNT_BASE, sr_uuid) 

74 self.vgname = EXT_PREFIX + sr_uuid 

75 self.remotepath = os.path.join("/dev", self.vgname, sr_uuid) 

76 self.attached = self._checkmount() 

77 self.driver_config = DRIVER_CONFIG 

78 

79 @override 

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

81 super(EXTSR, self).delete(sr_uuid) 

82 

83 # Check PVs match VG 

84 try: 

85 for dev in self.dconf['device'].split(','): 

86 cmd = ["pvs", dev] 

87 txt = util.pread2(cmd) 

88 if txt.find(self.vgname) == -1: 

89 raise xs_errors.XenError('VolNotFound', 

90 opterr='volume is %s' % self.vgname) 

91 except util.CommandException as inst: 

92 raise xs_errors.XenError('PVSfailed', 

93 opterr='error is %d' % inst.code) 

94 

95 # Remove LV, VG and pv 

96 try: 

97 cmd = ["lvremove", "-f", self.remotepath] 

98 util.pread2(cmd) 

99 

100 cmd = ["vgremove", self.vgname] 

101 util.pread2(cmd) 

102 

103 for dev in self.dconf['device'].split(','): 

104 cmd = ["pvremove", dev] 

105 util.pread2(cmd) 

106 except util.CommandException as inst: 

107 raise xs_errors.XenError('LVMDelete', 

108 opterr='errno is %d' % inst.code) 

109 

110 @override 

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

112 if not self._checkmount(): 

113 try: 

114 #Activate LV 

115 cmd = ['lvchange', '-ay', self.remotepath] 

116 util.pread2(cmd) 

117 except util.CommandException as inst: 

118 raise xs_errors.XenError( 

119 'LVMMount', 

120 opterr='Unable to activate LV. Errno is %d' % inst.code) 

121 

122 try: 

123 util.pread(["fsck", "-a", self.remotepath]) 

124 except util.CommandException as inst: 

125 if inst.code == 1: 

126 util.SMlog("FSCK detected and corrected FS errors. Not fatal.") 

127 else: 

128 raise xs_errors.XenError( 

129 'LVMMount', 

130 opterr='FSCK failed on %s. Errno is %d' % (self.remotepath, inst.code)) 

131 

132 self.attach_and_bind(sr_uuid, bind=False) 

133 

134 self.attached = True 

135 

136 #Update SCSIid string 

137 scsiutil.add_serial_record( 

138 self.session, self.sr_ref, 

139 scsiutil.devlist_to_serialstring(self.dconf['device'].split(','))) 

140 

141 # Set the block scheduler 

142 for dev in self.dconf['device'].split(','): 

143 self.block_setscheduler(dev) 

144 

145 @override 

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

147 super(EXTSR, self).detach(sr_uuid) 

148 try: 

149 # deactivate SR 

150 cmd = ["lvchange", "-an", self.remotepath] 

151 util.pread2(cmd) 

152 except util.CommandException as inst: 

153 raise xs_errors.XenError( 

154 'LVMUnMount', 

155 opterr='lvm -an failed errno is %d' % inst.code) 

156 

157 @override 

158 @deviceCheck 

159 def probe(self) -> str: 

160 return lvutil.srlist_toxml(lvutil.scan_srlist(EXT_PREFIX, self.dconf['device']), 

161 EXT_PREFIX) 

162 

163 @override 

164 @deviceCheck 

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

166 if self._checkmount(): 

167 raise xs_errors.XenError('SRExists') 

168 

169 # Check none of the devices already in use by other PBDs 

170 if util.test_hostPBD_devs(self.session, sr_uuid, self.dconf['device']): 

171 raise xs_errors.XenError('SRInUse') 

172 

173 # Check serial number entry in SR records 

174 for dev in self.dconf['device'].split(','): 

175 if util.test_scsiserial(self.session, dev): 

176 raise xs_errors.XenError('SRInUse') 

177 

178 if not lvutil._checkVG(self.vgname): 

179 lvutil.createVG(self.dconf['device'], self.vgname) 

180 

181 if lvutil._checkLV(self.remotepath): 

182 raise xs_errors.XenError('SRExists') 

183 

184 try: 

185 numdevs = len(self.dconf['device'].split(',')) 

186 cmd = ["lvcreate", "-n", sr_uuid] 

187 if numdevs > 1: 

188 lowest = -1 

189 for dev in self.dconf['device'].split(','): 

190 stats = lvutil._getPVstats(dev) 

191 if lowest < 0 or stats['freespace'] < lowest: 

192 lowest = stats['freespace'] 

193 size_mb = (lowest // (1024 * 1024)) * numdevs 

194 

195 # Add stripe parameter to command 

196 cmd += ["-i", str(numdevs), "-I", "2048"] 

197 else: 

198 stats = lvutil._getVGstats(self.vgname) 

199 size_mb = stats['freespace'] // (1024 * 1024) 

200 assert(size_mb > 0) 

201 cmd += ["-L", str(size_mb), self.vgname] 

202 text = util.pread(cmd) 

203 

204 cmd = ["lvchange", "-ay", self.remotepath] 

205 text = util.pread(cmd) 

206 except util.CommandException as inst: 

207 raise xs_errors.XenError( 

208 'LVMCreate', 

209 opterr='lv operation, error %d' % inst.code) 

210 except AssertionError: 

211 raise xs_errors.XenError( 

212 'SRNoSpace', 

213 opterr='Insufficient space in VG %s' % self.vgname) 

214 

215 try: 

216 util.pread2(["mkfs.ext4", "-F", self.remotepath]) 

217 except util.CommandException as inst: 

218 raise xs_errors.XenError('LVMFilesystem', 

219 opterr='mkfs failed error %d' % inst.code) 

220 

221 #Update serial number string 

222 scsiutil.add_serial_record( 

223 self.session, self.sr_ref, 

224 scsiutil.devlist_to_serialstring(self.dconf['device'].split(','))) 

225 

226 @override 

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

228 return EXTFileVDI(self, uuid) 

229 

230 

231class EXTFileVDI(FileSR.FileVDI): 

232 @override 

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

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

235 self.xenstore_data = {} 

236 

237 self.xenstore_data["storage-type"] = "ext" 

238 

239 return super(EXTFileVDI, self).attach(sr_uuid, vdi_uuid) 

240 

241 

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

243 SRCommand.run(EXTSR, DRIVER_INFO) 

244else: 

245 SR.registerSR(EXTSR)