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 #TODO(XCPNG-3499): We could use IPCFlag to interrupt the GC instead of our custom function.
194 # from ipc import IPCFlag
195 # flag = IPCFlag(sr_uuid)
197 # runningStr = "gc_running_{}".format(vdi_uuid)
198 # abortStr = "abort_{}".format(vdi_uuid)
200 # if not flag.test(runningStr):
201 # return "True"
203 # if not flag.test(abortStr):
204 # flag.set(abortStr)
206 # while flag.test(abortStr) or flag.test(runningStr):
207 # time.sleep(1)
209 # return "True"
211 util.SMlog("Running cancel_coalesce_master plugin: {}".format(vdi_uuid))
212 path = "/run/nonpersistent/sm/{}/gc_running_{}".format(sr_uuid, vdi_uuid)
214 try:
215 with open(path, "r+") as f:
216 f.truncate(0)
217 f.flush()
218 os.fsync(f.fileno())
219 except IOError as e:
220 if e.errno == errno.ENOENT:
221 return "True"
222 raise
224 while os.path.exists(path):
225 time.sleep(1)
227 return "True"
229def is_openers(session, args):
230 path = args["path"]
231 openers_pid= util.get_openers_pid(path)
232 return str(bool(openers_pid))
234def make_chain_rw(session, args):
235 from cowutil import getCowUtil
236 from lvmcowutil import LvmCowUtil
237 from lvutil import MASTER_LVM_CONF
239 if util.is_master(session):
240 os.environ['LVM_SYSTEM_DIR'] = MASTER_LVM_CONF
242 vgName = args["vgName"]
243 lvName = args["lvName"]
244 vdi_type = args["vdiType"]
246 cowutil = getCowUtil(vdi_type)
247 lvmcache = LVMCache(vgName)
249 for uuid, lvName in cowutil.getParentChain(lvName, LvmCowUtil.extractUuid, vgName).items():
250 try:
251 lvmcache.setReadonly(lvName, False)
252 except util.CommandException as e:
253 util.SMlog(f"on-slave:make_chain_rw: {e}")
255 return "True"
257if __name__ == "__main__": 257 ↛ 258line 257 didn't jump to line 258, because the condition on line 257 was never true
258 import XenAPIPlugin
259 XenAPIPlugin.dispatch({
260 "multi": multi,
261 "is_open": is_open,
262 "refresh_lun_size_by_SCSIid": refresh_lun_size_by_SCSIid,
263 "is_openers": is_openers,
264 "commit_tapdisk": commit_tapdisk,
265 "commit_cancel": commit_cancel,
266 "cancel_coalesce_master": cancel_coalesce_master,
267 "make_chain_rw": make_chain_rw,
268 })