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 LVMSR 

87 import MooseFSSR 

88 import NFSSR 

89 import XFSSR 

90 import ZFSSR 

91 import blktap2 

92 

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

94 vdiUuid = args["vdiUuid"] 

95 srRef = args["srRef"] 

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

97 srType = srRec["type"] 

98 

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

100 # avoid having to refactor the core files 

101 if srType.startswith("lvm"): 

102 srType = "lvm" 

103 cmd = SRCommand.SRCommand(None) 

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

105 cmd.dconf = { 

106 "server": None, 

107 "device": "/HACK", 

108 # Hack for custom XCP-ng drivers. 

109 "masterhost": None, # MooseFS 

110 "rootpath": None, # MooseFS 

111 "serverpath": None, # CephFS 

112 "location": "/HACK" # ZFS 

113 } 

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

115 

116 sr_uuid = srRec["uuid"] 

117 

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

119 # we can't fetch the VDI path. 

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

121 host_ref = util.get_this_host_ref(session) 

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

123 

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

125 if pbd is None: 

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

127 

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

129 

130 driver = SR.driver(srType) 

131 sr = driver(cmd, sr_uuid) 

132 

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

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

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

136 sr.session = session 

137 

138 vdi = sr.vdi(vdiUuid) 

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

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

141 if tapdisk: 

142 return "True" 

143 return "False" 

144 

145 

146def is_open(session, args): 

147 try: 

148 return _is_open(session, args) 

149 except: 

150 util.logException("is_open") 

151 raise 

152 

153def refresh_lun_size_by_SCSIid(session, args): 

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

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

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

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

158 % args) 

159 return "True" 

160 else: 

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

162 return "False" 

163 

164def commit_tapdisk(session, args): 

165 path: str = args["path"] 

166 vdi_type = args["vdi_type"] 

167 #TODO: naming should reflect that it does more than coalesceing, like setting volume RW 

168 

169 def set_RW(path): 

170 try: 

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

172 except: 

173 pass 

174 #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 

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

176 set_RW(path) 

177 

178 from cowutil import getCowUtil 

179 cowutil = getCowUtil(vdi_type) 

180 try: 

181 parent = cowutil.getParentNoCheck(path) 

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

183 set_RW(parent) 

184 return str(cowutil.coalesceOnline(path)) 

185 except: 

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

187 raise 

188 

189def commit_cancel(session, args): 

190 path = args["path"] 

191 vdi_type = args["vdi_type"] 

192 from cowutil import getCowUtil 

193 cowutil = getCowUtil(vdi_type) 

194 try: 

195 cowutil.cancelCoalesceOnline(path) 

196 except: 

197 return "False" 

198 return "True" 

199 

200def cancel_coalesce_master(session, args): 

201 sr_uuid = args["sr_uuid"] 

202 vdi_uuid = args["vdi_uuid"] 

203 

204 # from ipc import IPCFlag 

205 # flag = IPCFlag(sr_uuid) 

206 

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

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

209 

210 # if not flag.test(runningStr): 

211 # return "True" 

212 

213 # if not flag.test(abortStr): 

214 # flag.set(abortStr) 

215 

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

217 # time.sleep(1) 

218 

219 # return "True" 

220 

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

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

223 

224 try: 

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

226 f.truncate(0) 

227 f.flush() 

228 os.fsync(f.fileno()) 

229 except IOError as e: 

230 if e.errno == errno.ENOENT: 

231 return "True" 

232 raise 

233 

234 while os.path.exists(path): 

235 time.sleep(1) 

236 

237 return "True" 

238 

239def is_openers(session, args): 

240 path = args["path"] 

241 openers_pid= util.get_openers_pid(path) 

242 return str(bool(openers_pid)) 

243 

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

245 import XenAPIPlugin 

246 XenAPIPlugin.dispatch({ 

247 "multi": multi, 

248 "is_open": is_open, 

249 "refresh_lun_size_by_SCSIid": refresh_lun_size_by_SCSIid, 

250 "is_openers": is_openers, 

251 "commit_tapdisk": commit_tapdisk, 

252 "commit_cancel": commit_cancel, 

253 "cancel_coalesce_master": cancel_coalesce_master, 

254 })