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