dom0/qvm-block: handle block-attach errors (#515)

This commit is contained in:
Marek Marczykowski 2012-04-12 18:03:40 +02:00
parent 5ae9f98c8c
commit 1a07bc241d
2 changed files with 37 additions and 3 deletions

View File

@ -294,7 +294,7 @@ def block_check_attached(backend_vm, device, backend_xid = None):
xs.transaction_end(xs_trans) xs.transaction_end(xs_trans)
return None return None
def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False): def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False, wait=True):
if not vm.is_running(): if not vm.is_running():
raise QubesException("VM %s not running" % vm.name) raise QubesException("VM %s not running" % vm.name)
@ -325,6 +325,36 @@ def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=Fa
xl_cmd = [ '/usr/sbin/xl', 'block-attach', vm.name, backend_dev, frontend, mode, str(backend_vm.xid) ] xl_cmd = [ '/usr/sbin/xl', 'block-attach', vm.name, backend_dev, frontend, mode, str(backend_vm.xid) ]
subprocess.check_call(xl_cmd) subprocess.check_call(xl_cmd)
if wait:
be_path = '/local/domain/%d/backend/vbd/%d/%d' % (backend_vm.xid, vm.xid, block_name_to_devid(frontend))
# There is no way to use xenstore watch with a timeout, so must check in a loop
interval = 0.100
# 5sec timeout
timeout = 5/interval
while timeout > 0:
be_state = xs.read('', be_path + '/state')
hotplug_state = xs.read('', be_path + '/hotplug-status')
if be_state is None:
raise QubesException("Backend device disappeared, something weird happend")
elif int(be_state) == 4:
# Ok
return
elif int(be_state) > 4:
# Error
error = xs.read('/local/domain/%d/error/backend/vbd/%d/%d/error' % (backend_vm.xid, vm.xid, block_name_to_devid(frontend)))
if error is None:
raise QubesException("Error while connecting block device: " + error)
else:
raise QubesException("Unknown error while connecting block device")
elif hotplug_state == 'error':
hotplug_error = xs.read('', be_path + '/hotplug-error')
if hotplug_error:
raise QubesException("Error while connecting block device: " + hotplug_error)
else:
raise QubesException("Unknown hotplug error while connecting block device")
time.sleep(interval)
timeout -= interval
raise QubesException("Timeout while waiting for block defice connection")
def block_detach(vm, frontend = "xvdi", vm_xid = None): def block_detach(vm, frontend = "xvdi", vm_xid = None):
# Get XID if not provided already # Get XID if not provided already

View File

@ -20,7 +20,7 @@
# #
# #
from qubes.qubes import QubesVmCollection from qubes.qubes import QubesVmCollection, QubesException
from qubes.qubesutils import block_list,block_attach,block_detach,block_check_attached from qubes.qubesutils import block_list,block_attach,block_detach,block_check_attached
from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg
from optparse import OptionParser from optparse import OptionParser
@ -94,7 +94,11 @@ def main():
else: else:
kwargs['mode'] = dev['mode'] kwargs['mode'] = dev['mode']
kwargs['auto_detach'] = options.auto_detach kwargs['auto_detach'] = options.auto_detach
try:
block_attach(vm, backend_vm, dev['device'], **kwargs) block_attach(vm, backend_vm, dev['device'], **kwargs)
except QubesException as e:
print >> sys.stderr, "ERROR: %s" % str(e)
sys.exit(1)
elif options.do_detach: elif options.do_detach:
if (len (args) < 1): if (len (args) < 1):
parser.error ("You must provide device or vm name!") parser.error ("You must provide device or vm name!")