Coverage for drivers/on_slave.py : 64%
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
20import sys
21import os
22import time
23import errno
24sys.path.append("/opt/xensource/sm/")
25import util
26import lock
27from lvmcache import LVMCache
28import scsiutil
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)
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
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"]
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}
116 sr_uuid = srRec["uuid"]
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)
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')
128 cmd.dconf = session.xenapi.PBD.get_device_config(pbd)
130 driver = SR.driver(srType)
131 sr = driver(cmd, sr_uuid)
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
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"
146def is_open(session, args):
147 try:
148 return _is_open(session, args)
149 except:
150 util.logException("is_open")
151 raise
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"
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
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)
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
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"
200def cancel_coalesce_master(session, args):
201 sr_uuid = args["sr_uuid"]
202 vdi_uuid = args["vdi_uuid"]
204 # from ipc import IPCFlag
205 # flag = IPCFlag(sr_uuid)
207 # runningStr = "gc_running_{}".format(vdi_uuid)
208 # abortStr = "abort_{}".format(vdi_uuid)
210 # if not flag.test(runningStr):
211 # return "True"
213 # if not flag.test(abortStr):
214 # flag.set(abortStr)
216 # while flag.test(abortStr) or flag.test(runningStr):
217 # time.sleep(1)
219 # return "True"
221 util.SMlog("Running cancel_coalesce_master plugin: {}".format(vdi_uuid))
222 path = "/run/nonpersistent/sm/{}/gc_running_{}".format(sr_uuid, vdi_uuid)
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
234 while os.path.exists(path):
235 time.sleep(1)
237 return "True"
239def is_openers(session, args):
240 path = args["path"]
241 openers_pid= util.get_openers_pid(path)
242 return str(bool(openers_pid))
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 })