diff options
author | Rick Harris <rconradharris@gmail.com> | 2012-03-09 23:26:25 +0000 |
---|---|---|
committer | Rick Harris <rconradharris@gmail.com> | 2012-03-09 23:27:48 +0000 |
commit | e6cf7fc7f48a80e87f24e4f7b6f57d273f9d2a27 (patch) | |
tree | 643b94566b6ad72728c80ced99e58cd3af33a8ca /tools | |
parent | f936594d9e37abf4d8c22c2545a9b67ed8f25c90 (diff) | |
download | nova-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.py | 128 |
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() |