#!/usr/bin/env python # Copyright 2012 OpenStack Foundation # # 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 "" % ( 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 " % 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()