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 _make_chain_RW(cowutil, leaf_path, write: bool): 

166 def set_RW(path): 

167 try: 

168 util.pread2(["lvchange", "-p", "rw", path]) 

169 except: 

170 pass 

171 

172 # if path.startswith("/dev/"): 

173 # set_RW(leaf_path) # Not needed since it's a leaf 

174 

175 parent = cowutil.getParentNoCheck(leaf_path) 

176 while parent: 

177 if parent.startswith("/dev/"): 

178 set_RW(parent) 

179 parent = cowutil.getParentNoCheck(parent) 

180 

181def commit_tapdisk(session, args): 

182 path: str = args["path"] 

183 vdi_type = args["vdi_type"] 

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

185 

186 from cowutil import getCowUtil 

187 cowutil = getCowUtil(vdi_type) 

188 try: 

189 if path.startswith("/dev/"): 

190 # We need to make children RW or tapdisk will crash trying to do it 

191 _make_chain_RW(cowutil, leaf_path, True) 

192 return str(cowutil.coalesceOnline(path)) 

193 except: 

194 util.logException("Couldn't coalesce online") 

195 raise 

196 

197def commit_cancel(session, args): 

198 path = args["path"] 

199 vdi_type = args["vdi_type"] 

200 from cowutil import getCowUtil 

201 cowutil = getCowUtil(vdi_type) 

202 try: 

203 cowutil.cancelCoalesceOnline(path) 

204 except: 

205 return "False" 

206 return "True" 

207 

208def cancel_coalesce_master(session, args): 

209 sr_uuid = args["sr_uuid"] 

210 vdi_uuid = args["vdi_uuid"] 

211 

212 # from ipc import IPCFlag 

213 # flag = IPCFlag(sr_uuid) 

214 

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

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

217 

218 # if not flag.test(runningStr): 

219 # return "True" 

220 

221 # if not flag.test(abortStr): 

222 # flag.set(abortStr) 

223 

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

225 # time.sleep(1) 

226 

227 # return "True" 

228 

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

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

231 

232 try: 

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

234 f.truncate(0) 

235 f.flush() 

236 os.fsync(f.fileno()) 

237 except IOError as e: 

238 if e.errno == errno.ENOENT: 

239 return "True" 

240 raise 

241 

242 while os.path.exists(path): 

243 time.sleep(1) 

244 

245 return "True" 

246 

247def is_openers(session, args): 

248 path = args["path"] 

249 openers_pid= util.get_openers_pid(path) 

250 return str(bool(openers_pid)) 

251 

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

253 import XenAPIPlugin 

254 XenAPIPlugin.dispatch({ 

255 "multi": multi, 

256 "is_open": is_open, 

257 "refresh_lun_size_by_SCSIid": refresh_lun_size_by_SCSIid, 

258 "is_openers": is_openers, 

259 "commit_tapdisk": commit_tapdisk, 

260 "commit_cancel": commit_cancel, 

261 "cancel_coalesce_master": cancel_coalesce_master, 

262 })