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# A plugin for synchronizing slaves when something changes on the Master 

19 

20import sys 

21import os 

22import time 

23import errno 

24sys.path.append("/opt/xensource/sm/") 

25import util 

26import lock 

27from lvmcache import LVMCache 

28import scsiutil 

29 

30 

31def multi(session, args): 

32 """Perform several actions in one call (to save on round trips)""" 

33 util.SMlog("on-slave.multi: %s" % args) 

34 vgName = args["vgName"] 

35 lvmCache = LVMCache(vgName) 

36 i = 1 

37 while True: 

38 action = args.get("action%d" % i) 

39 if not action: 

40 break 

41 util.SMlog("on-slave.action %d: %s" % (i, action)) 

42 if action == "activate": 

43 try: 

44 lvmCache.activate(args["ns%d" % i], args["uuid%d" % i], 

45 args["lvName%d" % i], False) 

46 except util.CommandException: 

47 util.SMlog("on-slave.activate failed") 

48 raise 

49 elif action == "deactivate": 

50 try: 

51 lvmCache.deactivate(args["ns%d" % i], args["uuid%d" % i], 

52 args["lvName%d" % i], False) 

53 except util.SMException: 

54 util.SMlog("on-slave.deactivate failed") 

55 raise 

56 elif action == "deactivateNoRefcount": 

57 try: 

58 lvmCache.deactivateNoRefcount(args["lvName%d" % i]) 

59 except util.SMException: 

60 util.SMlog("on-slave.deactivateNoRefcount failed") 

61 raise 

62 elif action == "refresh": 

63 try: 

64 lvmCache.activateNoRefcount(args["lvName%d" % i], True) 

65 except util.CommandException: 

66 util.SMlog("on-slave.refresh failed") 

67 raise 

68 elif action == "cleanupLockAndRefcount": 

69 from refcounter import RefCounter 

70 lock.Lock.cleanup(args["uuid%d" % i], args["ns%d" % i]) 

71 RefCounter.reset(args["uuid%d" % i], args["ns%d" % i]) 

72 else: 

73 raise util.SMException("unrecognized action: %s" % action) 

74 i += 1 

75 return str(True) 

76 

77 

78def _is_open(session, args): 

79 """Check if VDI <args["vdiUuid"]> is open by a tapdisk on this host""" 

80 import SRCommand 

81 import SR 

82 import CephFSSR 

83 import EXTSR 

84 import LargeBlockSR 

85 import GlusterFSSR 

86 import LinstorSR 

87 import LVMSR 

88 import MooseFSSR 

89 import NFSSR 

90 import XFSSR 

91 import ZFSSR 

92 import blktap2 

93 

94 util.SMlog("on-slave.is_open: %s" % args) 

95 vdiUuid = args["vdiUuid"] 

96 srRef = args["srRef"] 

97 srRec = session.xenapi.SR.get_record(srRef) 

98 srType = srRec["type"] 

99 

100 # FIXME: ugly hacks to create a VDI object without a real SRCommand to 

101 # avoid having to refactor the core files 

102 if srType.startswith("lvm"): 

103 srType = "lvm" 

104 cmd = SRCommand.SRCommand(None) 

105 cmd.driver_info = {"capabilities": None} 

106 cmd.dconf = { 

107 "server": None, 

108 "device": "/HACK", 

109 # Hack for custom XCP-ng drivers. 

110 "masterhost": None, # MooseFS 

111 "rootpath": None, # MooseFS 

112 "serverpath": None, # CephFS 

113 "location": "/HACK" # ZFS 

114 } 

115 cmd.params = {"command": None} 

116 

117 sr_uuid = srRec["uuid"] 

118 

119 # Another ugly piece of code to load a real Linstor SR, otherwise 

120 # we can't fetch the VDI path. 

121 if srType == 'linstor': 121 ↛ 122line 121 didn't jump to line 122, because the condition on line 121 was never true

122 host_ref = util.get_this_host_ref(session) 

123 sr_ref = session.xenapi.SR.get_by_uuid(sr_uuid) 

124 

125 pbd = util.find_my_pbd(session, host_ref, sr_ref) 

126 if pbd is None: 

127 raise util.SMException('Failed to find Linstor PBD') 

128 

129 cmd.dconf = session.xenapi.PBD.get_device_config(pbd) 

130 

131 driver = SR.driver(srType) 

132 sr = driver(cmd, sr_uuid) 

133 

134 # session_ref param is required to have a valid session when SR object is created. 

135 # It's not the case here, so attach the current session object to make LinstorSR happy. 

136 if srType == 'linstor': 136 ↛ 137line 136 didn't jump to line 137, because the condition on line 136 was never true

137 sr.session = session 

138 

139 vdi = sr.vdi(vdiUuid) 

140 tapdisk = blktap2.Tapdisk.find_by_path(vdi.path) 

141 util.SMlog("Tapdisk for %s: %s" % (vdi.path, tapdisk)) 

142 if tapdisk: 

143 return "True" 

144 return "False" 

145 

146 

147def is_open(session, args): 

148 try: 

149 return _is_open(session, args) 

150 except: 

151 util.logException("is_open") 

152 raise 

153 

154def refresh_lun_size_by_SCSIid(session, args): 

155 """Refresh the size of LUNs backing the SCSIid on the local node.""" 

156 util.SMlog("on-slave.refresh_lun_size_by_SCSIid(,%s)" % args) 

157 if scsiutil.refresh_lun_size_by_SCSIid(args['SCSIid']): 

158 util.SMlog("on-slave.refresh_lun_size_by_SCSIid with %s succeeded" 

159 % args) 

160 return "True" 

161 else: 

162 util.SMlog("on-slave.refresh_lun_size_by_SCSIid with %s failed" % args) 

163 return "False" 

164 

165def commit_tapdisk(session, args): 

166 path: str = args["path"] 

167 vdi_type = args["vdi_type"] 

168 leaf_path: str = args["leaf_path"] # The path of the leaf used by the tapdisk 

169 

170 from cowutil import getCowUtil 

171 cowutil = getCowUtil(vdi_type) 

172 try: 

173 return str(cowutil.coalesceOnline(path)) 

174 except: 

175 util.logException(f"Couldn't coalesce online: `{path}`") 

176 raise 

177 

178def commit_cancel(session, args): 

179 path = args["path"] 

180 vdi_type = args["vdi_type"] 

181 from cowutil import getCowUtil 

182 cowutil = getCowUtil(vdi_type) 

183 try: 

184 cowutil.cancelCoalesceOnline(path) 

185 except: 

186 return "False" 

187 return "True" 

188 

189def cancel_coalesce_master(session, args): 

190 sr_uuid = args["sr_uuid"] 

191 vdi_uuid = args["vdi_uuid"] 

192 

193 # from ipc import IPCFlag 

194 # flag = IPCFlag(sr_uuid) 

195 

196 # runningStr = "gc_running_{}".format(vdi_uuid) 

197 # abortStr = "abort_{}".format(vdi_uuid) 

198 

199 # if not flag.test(runningStr): 

200 # return "True" 

201 

202 # if not flag.test(abortStr): 

203 # flag.set(abortStr) 

204 

205 # while flag.test(abortStr) or flag.test(runningStr): 

206 # time.sleep(1) 

207 

208 # return "True" 

209 

210 util.SMlog("Running cancel_coalesce_master plugin: {}".format(vdi_uuid)) 

211 path = "/run/nonpersistent/sm/{}/gc_running_{}".format(sr_uuid, vdi_uuid) 

212 

213 try: 

214 with open(path, "r+") as f: 

215 f.truncate(0) 

216 f.flush() 

217 os.fsync(f.fileno()) 

218 except IOError as e: 

219 if e.errno == errno.ENOENT: 

220 return "True" 

221 raise 

222 

223 while os.path.exists(path): 

224 time.sleep(1) 

225 

226 return "True" 

227 

228def is_openers(session, args): 

229 path = args["path"] 

230 openers_pid= util.get_openers_pid(path) 

231 return str(bool(openers_pid)) 

232 

233def make_chain_rw(session, args): 

234 from cowutil import getCowUtil 

235 from lvmcowutil import LvmCowUtil 

236 from lvutil import MASTER_LVM_CONF 

237 

238 if util.is_master(session): 

239 os.environ['LVM_SYSTEM_DIR'] = MASTER_LVM_CONF 

240 

241 vgName = args["vgName"] 

242 lvName = args["lvName"] 

243 vdi_type = args["vdiType"] 

244 

245 cowutil = getCowUtil(vdi_type) 

246 lvmcache = LVMCache(vgName) 

247 

248 for uuid, lvName in cowutil.getParentChain(lvName, LvmCowUtil.extractUuid, vgName).items(): 

249 try: 

250 lvmcache.setReadonly(lvName, False) 

251 except util.CommandException as e: 

252 util.SMlog(f"on-slave:make_chain_rw: {e}") 

253 

254 return "True" 

255 

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

257 import XenAPIPlugin 

258 XenAPIPlugin.dispatch({ 

259 "multi": multi, 

260 "is_open": is_open, 

261 "refresh_lun_size_by_SCSIid": refresh_lun_size_by_SCSIid, 

262 "is_openers": is_openers, 

263 "commit_tapdisk": commit_tapdisk, 

264 "commit_cancel": commit_cancel, 

265 "cancel_coalesce_master": cancel_coalesce_master, 

266 "make_chain_rw": make_chain_rw, 

267 })