summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRick Harris <rconradharris@gmail.com>2012-03-09 23:26:25 +0000
committerRick Harris <rconradharris@gmail.com>2012-03-09 23:27:48 +0000
commite6cf7fc7f48a80e87f24e4f7b6f57d273f9d2a27 (patch)
tree643b94566b6ad72728c80ced99e58cd3af33a8ca /tools
parentf936594d9e37abf4d8c22c2545a9b67ed8f25c90 (diff)
downloadnova-e6cf7fc7f48a80e87f24e4f7b6f57d273f9d2a27.tar.gz
Add VDI chain cleanup script.
References bug 949477 Change-Id: I819d4ed56675a4ef4e46adca2978b433386e128d
Diffstat (limited to 'tools')
-rw-r--r--tools/xenserver/vdi_chain_cleanup.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/tools/xenserver/vdi_chain_cleanup.py b/tools/xenserver/vdi_chain_cleanup.py
new file mode 100644
index 0000000000..4d4892d8be
--- /dev/null
+++ b/tools/xenserver/vdi_chain_cleanup.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+
+# Copyright 2012 OpenStack, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+This script is designed to cleanup any VHDs (and their descendents) which have
+a bad parent pointer.
+
+The script needs to be run in the dom0 of the affected host.
+
+The available actions are:
+
+ - print: display the filenames of the affected VHDs
+ - delete: remove the affected VHDs
+ - move: move the affected VHDs out of the SR into another directory
+"""
+import glob
+import os
+import subprocess
+import sys
+
+
+class ExecutionFailed(Exception):
+ def __init__(self, returncode, stdout, stderr, max_stream_length=32):
+ self.returncode = returncode
+ self.stdout = stdout[:max_stream_length]
+ self.stderr = stderr[:max_stream_length]
+ self.max_stream_length = max_stream_length
+
+ def __repr__(self):
+ return "<ExecutionFailed returncode=%s out='%s' stderr='%s'>" % (
+ self.returncode, self.stdout, self.stderr)
+
+ __str__ = __repr__
+
+
+def execute(cmd, ok_exit_codes=None):
+ if ok_exit_codes is None:
+ ok_exit_codes = [0]
+
+ proc = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ (stdout, stderr) = proc.communicate()
+
+ if proc.returncode not in ok_exit_codes:
+ raise ExecutionFailed(proc.returncode, stdout, stderr)
+
+ return proc.returncode, stdout, stderr
+
+
+def usage():
+ print "usage: %s <SR PATH> <print|delete|move>" % sys.argv[0]
+ sys.exit(1)
+
+
+def main():
+ if len(sys.argv) < 3:
+ usage()
+
+ sr_path = sys.argv[1]
+ action = sys.argv[2]
+
+ if action not in ('print', 'delete', 'move'):
+ usage()
+
+ if action == 'move':
+ if len(sys.argv) < 4:
+ print "error: must specify where to move bad VHDs"
+ sys.exit(1)
+
+ bad_vhd_path = sys.argv[3]
+ if not os.path.exists(bad_vhd_path):
+ os.makedirs(bad_vhd_path)
+
+ bad_leaves = []
+ descendents = {}
+
+ for fname in glob.glob(os.path.join(sr_path, "*.vhd")):
+ (returncode, stdout, stderr) = execute(
+ ['vhd-util', 'query', '-n', fname, '-p'], ok_exit_codes=[0, 22])
+
+ stdout = stdout.strip()
+
+ if stdout.endswith('.vhd'):
+ try:
+ descendents[stdout].append(fname)
+ except KeyError:
+ descendents[stdout] = [fname]
+ elif 'query failed' in stdout:
+ bad_leaves.append(fname)
+
+ def walk_vhds(root):
+ yield root
+ if root in descendents:
+ for child in descendents[root]:
+ for vhd in walk_vhds(child):
+ yield vhd
+
+ for bad_leaf in bad_leaves:
+ for bad_vhd in walk_vhds(bad_leaf):
+ print bad_vhd
+ if action == "print":
+ pass
+ elif action == "delete":
+ os.unlink(bad_vhd)
+ elif action == "move":
+ new_path = os.path.join(bad_vhd_path,
+ os.path.basename(bad_vhd))
+ os.rename(bad_vhd, new_path)
+ else:
+ raise Exception("invalid action %s" % action)
+
+
+if __name__ == '__main__':
+ main()