Merge branch 'hvm' of 10.141.1.101:/var/lib/qubes/git/marmarek/core into hvm

This commit is contained in:
Joanna Rutkowska 2012-04-15 16:39:07 +02:00
commit 11dbf9c385
3 changed files with 107 additions and 11 deletions

View File

@ -385,7 +385,7 @@ class QubesVm(object):
self._set_netvm(new_netvm)
def _set_netvm(self, new_netvm):
if self.is_running() and not new_netvm.is_running():
if self.is_running() and new_netvm is not None and not new_netvm.is_running():
raise QubesException("Cannot dynamically attach to stopped NetVM")
if self.netvm is not None:
self.netvm.connected_vms.pop(self.qid)
@ -2266,7 +2266,7 @@ class QubesHVm(QubesVm):
format(self.private_img)
f_private = open(self.private_img, "w")
f_private.truncate(default_hvm_private_img_size)
f_root.close()
f_private.close()
return True

View File

@ -93,6 +93,8 @@ def print_stdout(text):
def print_stderr(text):
print >> sys.stderr, (text)
###### Block devices ########
def block_devid_to_name(devid):
major = devid / 256
minor = devid % 256
@ -203,10 +205,11 @@ def block_list(vm = None, system_disks = False):
else:
vm_list = xs.ls('', '/local/domain')
xs_trans = xs.transaction_start()
devices_list = {}
for xid in vm_list:
vm_name = xs.read('', '/local/domain/%s/name' % xid)
vm_devices = xs.ls('', '/local/domain/%s/qubes-block-devices' % xid)
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid)
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-block-devices' % xid)
if vm_devices is None:
continue
for device in vm_devices:
@ -215,9 +218,9 @@ def block_list(vm = None, system_disks = False):
print >> sys.stderr, "Invalid device name in VM '%s'" % vm_name
continue
device_size = xs.read('', '/local/domain/%s/qubes-block-devices/%s/size' % (xid, device))
device_desc = xs.read('', '/local/domain/%s/qubes-block-devices/%s/desc' % (xid, device))
device_mode = xs.read('', '/local/domain/%s/qubes-block-devices/%s/mode' % (xid, device))
device_size = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/size' % (xid, device))
device_desc = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/desc' % (xid, device))
device_mode = xs.read(xs_trans, '/local/domain/%s/qubes-block-devices/%s/mode' % (xid, device))
if device_size is None or device_desc is None or device_mode is None:
print >> sys.stderr, "Missing field in %s device parameters" % device
@ -245,13 +248,16 @@ def block_list(vm = None, system_disks = False):
"vm": vm_name, "device":device, "size":int(device_size),
"desc":device_desc, "mode":device_mode}
xs.transaction_end(xs_trans)
return devices_list
def block_check_attached(backend_vm, device, backend_xid = None):
if backend_xid is None:
backend_xid = backend_vm.xid
vm_list = xs.ls('', '/local/domain/%d/backend/vbd' % backend_xid)
xs_trans = xs.transaction_start()
vm_list = xs.ls(xs_trans, '/local/domain/%d/backend/vbd' % backend_xid)
if vm_list is None:
xs.transaction_end(xs_trans)
return None
device_majorminor = None
try:
@ -260,10 +266,10 @@ def block_check_attached(backend_vm, device, backend_xid = None):
# Unknown devices will be compared directly - perhaps it is a filename?
pass
for vm_xid in vm_list:
for devid in xs.ls('', '/local/domain/%d/backend/vbd/%s' % (backend_xid, vm_xid)):
for devid in xs.ls(xs_trans, '/local/domain/%d/backend/vbd/%s' % (backend_xid, vm_xid)):
(tmp_major, tmp_minor) = (0, 0)
phys_device = xs.read('', '/local/domain/%d/backend/vbd/%s/%s/physical-device' % (backend_xid, vm_xid, devid))
dev_params = xs.read('', '/local/domain/%d/backend/vbd/%s/%s/params' % (backend_xid, vm_xid, devid))
phys_device = xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/physical-device' % (backend_xid, vm_xid, devid))
dev_params = xs.read(xs_trans, '/local/domain/%d/backend/vbd/%s/%s/params' % (backend_xid, vm_xid, devid))
if phys_device and phys_device.find(':'):
(tmp_major, tmp_minor) = phys_device.split(":")
tmp_major = int(tmp_major, 16)
@ -283,7 +289,9 @@ def block_check_attached(backend_vm, device, backend_xid = None):
(device_majorminor is None and dev_params == device):
vm_name = xl_ctx.domid_to_name(int(vm_xid))
frontend = block_devid_to_name(int(devid))
xs.transaction_end(xs_trans)
return {"xid":int(vm_xid), "frontend": frontend, "devid": int(devid), "vm": vm_name}
xs.transaction_end(xs_trans)
return None
def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False):
@ -334,6 +342,93 @@ def block_detach(vm, frontend = "xvdi", vm_xid = None):
xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), str(frontend)]
subprocess.check_call(xl_cmd)
####### QubesWatch ######
def only_in_first_list(l1, l2):
ret=[]
for i in l1:
if not i in l2:
ret.append(i)
return ret
class QubesWatch(object):
class WatchType(object):
def __init__(self, fn, param):
self.fn = fn
self.param = param
def __init__(self):
self.xs = xen.lowlevel.xs.xs()
self.watch_tokens_block = {}
self.watch_tokens_vbd = {}
self.block_callback = None
self.domain_callback = None
self.xs.watch('@introduceDomain', QubesWatch.WatchType(self.domain_list_changed, None))
self.xs.watch('@releaseDomain', QubesWatch.WatchType(self.domain_list_changed, None))
def setup_block_watch(self, callback):
old_block_callback = self.block_callback
self.block_callback = callback
if old_block_callback is not None and callback is None:
# remove watches
self.update_watches_vbd([])
self.update_watches_block([])
else:
# possibly add watches
self.domain_list_changed(None)
def setup_domain_watch(self, callback):
self.domain_callback = callback
def get_block_key(self, xid):
return '/local/domain/%s/qubes-block-devices' % xid
def get_vbd_key(self, xid):
return '/local/domain/%s/device/vbd' % xid
def update_watches_block(self, xid_list):
for i in only_in_first_list(xid_list, self.watch_tokens_block.keys()):
#new domain has been created
watch = QubesWatch.WatchType(self.block_callback, i)
self.watch_tokens_block[i] = watch
self.xs.watch(self.get_block_key(i), watch)
for i in only_in_first_list(self.watch_tokens_block.keys(), xid_list):
#domain destroyed
self.xs.unwatch(self.get_block_key(i), self.watch_tokens_block[i])
self.watch_tokens_block.pop(i)
def update_watches_vbd(self, xid_list):
for i in only_in_first_list(xid_list, self.watch_tokens_vbd.keys()):
#new domain has been created
watch = QubesWatch.WatchType(self.block_callback, i)
self.watch_tokens_block[i] = watch
self.xs.watch(self.get_vbd_key(i), watch)
for i in only_in_first_list(self.watch_tokens_vbd.keys(), xid_list):
#domain destroyed
self.xs.unwatch(self.get_vbd_key(i), self.watch_tokens_vbd[i])
self.watch_tokens_vbd.pop(i)
def domain_list_changed(self, param):
curr = self.xs.ls('', '/local/domain')
if curr == None:
return
if self.domain_callback:
self.domain_callback()
if self.block_callback:
self.update_watches_block(curr)
self.update_watches_vbd(curr)
def watch_single(self):
result = self.xs.read_watch()
token = result[1]
token.fn(token.param)
def watch_loop(self):
while True:
self.watch_single()
######## Backups #########
def get_disk_usage(file_or_dir):
if not os.path.exists(file_or_dir):
return 0

View File

@ -1 +1,2 @@
modprobe evtchn 2>/dev/null || modprobe xen-evtchn
modprobe xen-blkback 2> /dev/null || modprobe blkbk