Coverage for drivers/resetvdis.py : 5%

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# Clear the attach status for all VDIs in the given SR on this host.
19# Additionally, reset the paused state if this host is the master.
21import cleanup
22import util
23import lock
24import XenAPI # pylint: disable=import-error
27def reset_sr(session, host_uuid, sr_uuid, is_sr_master):
28 from vhdutil import LOCK_TYPE_SR
30 cleanup.abort(sr_uuid)
32 gc_lock = lock.Lock(lock.LOCK_TYPE_GC_RUNNING, sr_uuid)
33 sr_lock = lock.Lock(LOCK_TYPE_SR, sr_uuid)
34 gc_lock.acquire()
35 sr_lock.acquire()
37 sr_ref = session.xenapi.SR.get_by_uuid(sr_uuid)
39 host_ref = session.xenapi.host.get_by_uuid(host_uuid)
40 host_key = "host_%s" % host_ref
42 util.SMlog("RESET for SR %s (master: %s)" % (sr_uuid, is_sr_master))
44 vdi_recs = session.xenapi.VDI.get_all_records_where( \
45 "field \"SR\" = \"%s\"" % sr_ref)
47 for vdi_ref, vdi_rec in vdi_recs.items():
48 vdi_uuid = vdi_rec["uuid"]
49 sm_config = vdi_rec["sm_config"]
50 if sm_config.get(host_key):
51 util.SMlog("Clearing attached status for VDI %s" % vdi_uuid)
52 session.xenapi.VDI.remove_from_sm_config(vdi_ref, host_key)
53 if is_sr_master and sm_config.get("paused"):
54 util.SMlog("Clearing paused status for VDI %s" % vdi_uuid)
55 session.xenapi.VDI.remove_from_sm_config(vdi_ref, "paused")
57 sr_lock.release()
58 gc_lock.release()
61def reset_vdi(session, vdi_uuid, force, term_output=True, writable=True):
62 vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
63 vdi_rec = session.xenapi.VDI.get_record(vdi_ref)
64 sm_config = vdi_rec["sm_config"]
65 host_ref = None
66 clean = True
67 for key, val in sm_config.items():
68 if key.startswith("host_"):
69 host_ref = key[len("host_"):]
70 host_uuid = None
71 host_invalid = False
72 host_str = host_ref
73 try:
74 host_rec = session.xenapi.host.get_record(host_ref)
75 host_uuid = host_rec["uuid"]
76 host_str = "%s (%s)" % (host_uuid, host_rec["name_label"])
77 except XenAPI.Failure as e:
78 msg = "Invalid host: %s (%s)" % (host_ref, e)
79 util.SMlog(msg)
80 if term_output:
81 print(msg)
82 host_invalid = True
84 if host_invalid:
85 session.xenapi.VDI.remove_from_sm_config(vdi_ref, key)
86 msg = "Invalid host: Force-cleared %s for %s on host %s" % \
87 (val, vdi_uuid, host_str)
88 util.SMlog(msg)
89 if term_output:
90 print(msg)
91 continue
93 if force:
94 session.xenapi.VDI.remove_from_sm_config(vdi_ref, key)
95 msg = "Force-cleared %s for %s on host %s" % \
96 (val, vdi_uuid, host_str)
97 util.SMlog(msg)
98 if term_output:
99 print(msg)
100 continue
102 ret = session.xenapi.host.call_plugin(
103 host_ref, "on-slave", "is_open",
104 {"vdiUuid": vdi_uuid, "srRef": vdi_rec["SR"]})
105 if ret != "False":
106 util.SMlog("VDI %s is still open on host %s, not resetting" % \
107 (vdi_uuid, host_str))
108 if term_output:
109 print("ERROR: VDI %s is still open on host %s" % \
110 (vdi_uuid, host_str))
111 if writable:
112 return False
113 else:
114 clean = False
115 else:
116 session.xenapi.VDI.remove_from_sm_config(vdi_ref, key)
117 msg = "Cleared %s for %s on host %s" % \
118 (val, vdi_uuid, host_str)
119 util.SMlog(msg)
120 if term_output:
121 print(msg)
123 if not host_ref:
124 msg = "VDI %s is not marked as attached anywhere, nothing to do" \
125 % vdi_uuid
126 util.SMlog(msg)
127 if term_output:
128 print(msg)
129 return clean
132def usage():
133 print("Usage:")
134 print("all <HOST UUID> <SR UUID> [--master]")
135 print("single <VDI UUID> [--force]")
136 print()
137 print("*WARNING!* calling with 'all' on an attached SR, or using " + \
138 "--force may cause DATA CORRUPTION if the VDI is still " + \
139 "attached somewhere. Always manually double-check that " + \
140 "the VDI is not in use before running this script.")
141 sys.exit(1)
143if __name__ == '__main__': 143 ↛ 144line 143 didn't jump to line 144, because the condition on line 143 was never true
144 import sys
145 import atexit
147 if len(sys.argv) not in [3, 4, 5]:
148 usage()
150 session = XenAPI.xapi_local()
151 session.xenapi.login_with_password('root', '', '', 'SM')
152 atexit.register(session.xenapi.session.logout)
154 mode = sys.argv[1]
155 if mode == "all":
156 if len(sys.argv) not in [4, 5]:
157 usage()
158 host_uuid = sys.argv[2]
159 sr_uuid = sys.argv[3]
160 is_master = False
161 if len(sys.argv) == 5:
162 if sys.argv[4] == "--master":
163 is_master = True
164 else:
165 usage()
166 reset_sr(session, host_uuid, sr_uuid, is_master)
167 elif mode == "single":
168 vdi_uuid = sys.argv[2]
169 force = False
170 if len(sys.argv) == 4 and sys.argv[3] == "--force":
171 force = True
172 reset_vdi(session, vdi_uuid, force)
173 elif len(sys.argv) in [3, 4]:
174 # backwards compatibility: the arguments for the "all" case used to be
175 # just host_uuid, sr_uuid, [is_master] (i.e., no "all" string, since it
176 # was the only mode available). To avoid having to change XAPI, accept
177 # the old format here as well.
178 host_uuid = sys.argv[1]
179 sr_uuid = sys.argv[2]
180 is_master = False
181 if len(sys.argv) == 4:
182 if sys.argv[3] == "--master":
183 is_master = True
184 else:
185 usage()
186 reset_sr(session, host_uuid, sr_uuid, is_master)
187 else:
188 usage()