Coverage for drivers/on_slave.py : 62%
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 LinstorSR
87 import LVMSR
88 import MooseFSSR
89 import NFSSR
90 import XFSSR
91 import ZFSSR
92 import blktap2
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"]
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}
117 sr_uuid = srRec["uuid"]
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)
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')
129 cmd.dconf = session.xenapi.PBD.get_device_config(pbd)
131 driver = SR.driver(srType)
132 sr = driver(cmd, sr_uuid)
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
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"
147def is_open(session, args):
148 try:
149 return _is_open(session, args)
150 except:
151 util.logException("is_open")
152 raise
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"
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
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
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"
189def cancel_coalesce_master(session, args):
190 sr_uuid = args["sr_uuid"]
191 vdi_uuid = args["vdi_uuid"]
193 # from ipc import IPCFlag
194 # flag = IPCFlag(sr_uuid)
196 # runningStr = "gc_running_{}".format(vdi_uuid)
197 # abortStr = "abort_{}".format(vdi_uuid)
199 # if not flag.test(runningStr):
200 # return "True"
202 # if not flag.test(abortStr):
203 # flag.set(abortStr)
205 # while flag.test(abortStr) or flag.test(runningStr):
206 # time.sleep(1)
208 # return "True"
210 util.SMlog("Running cancel_coalesce_master plugin: {}".format(vdi_uuid))
211 path = "/run/nonpersistent/sm/{}/gc_running_{}".format(sr_uuid, vdi_uuid)
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
223 while os.path.exists(path):
224 time.sleep(1)
226 return "True"
228def is_openers(session, args):
229 path = args["path"]
230 openers_pid= util.get_openers_pid(path)
231 return str(bool(openers_pid))
233def make_chain_rw(session, args):
234 from cowutil import getCowUtil
235 from lvmcowutil import LvmCowUtil
236 from lvutil import MASTER_LVM_CONF
238 if util.is_master(session):
239 os.environ['LVM_SYSTEM_DIR'] = MASTER_LVM_CONF
241 vgName = args["vgName"]
242 lvName = args["lvName"]
243 vdi_type = args["vdiType"]
245 cowutil = getCowUtil(vdi_type)
246 lvmcache = LVMCache(vgName)
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}")
254 return "True"
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 })