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 #TODO: naming should reflect that it does more than coalesceing, like setting volume RW 

169 

170 def set_RW(path): 

171 try: 

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

173 except: 

174 pass 

175 #TODO: need to make children RW. Or we let the relink happen with a refresh on master and hope it doesn't corrupt the disk 

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

177 set_RW(path) 

178 

179 from cowutil import getCowUtil 

180 cowutil = getCowUtil(vdi_type) 

181 try: 

182 parent = cowutil.getParentNoCheck(path) 

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

184 set_RW(parent) 

185 return str(cowutil.coalesceOnline(path)) 

186 except: 

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

188 raise 

189 

190def commit_cancel(session, args): 

191 path = args["path"] 

192 vdi_type = args["vdi_type"] 

193 from cowutil import getCowUtil 

194 cowutil = getCowUtil(vdi_type) 

195 try: 

196 cowutil.cancelCoalesceOnline(path) 

197 except: 

198 return "False" 

199 return "True" 

200 

201def cancel_coalesce_master(session, args): 

202 sr_uuid = args["sr_uuid"] 

203 vdi_uuid = args["vdi_uuid"] 

204 

205 # from ipc import IPCFlag 

206 # flag = IPCFlag(sr_uuid) 

207 

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

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

210 

211 # if not flag.test(runningStr): 

212 # return "True" 

213 

214 # if not flag.test(abortStr): 

215 # flag.set(abortStr) 

216 

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

218 # time.sleep(1) 

219 

220 # return "True" 

221 

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

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

224 

225 try: 

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

227 f.truncate(0) 

228 f.flush() 

229 os.fsync(f.fileno()) 

230 except IOError as e: 

231 if e.errno == errno.ENOENT: 

232 return "True" 

233 raise 

234 

235 while os.path.exists(path): 

236 time.sleep(1) 

237 

238 return "True" 

239 

240def is_openers(session, args): 

241 path = args["path"] 

242 openers_pid= util.get_openers_pid(path) 

243 return str(bool(openers_pid)) 

244 

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

246 import XenAPIPlugin 

247 XenAPIPlugin.dispatch({ 

248 "multi": multi, 

249 "is_open": is_open, 

250 "refresh_lun_size_by_SCSIid": refresh_lun_size_by_SCSIid, 

251 "is_openers": is_openers, 

252 "commit_tapdisk": commit_tapdisk, 

253 "commit_cancel": commit_cancel, 

254 "cancel_coalesce_master": cancel_coalesce_master, 

255 })