core: fix template-based HVM disk handling

We use only one device-mapper layer for HVMs, and this isn't the same as
for PV - it is that one, which PV does in initramfs.
Device-mapper layers summary for template-based VMs:
PV: root.img+root-cow.img (dom0) -> xvda, xvda+volatile.img (VM)
HVM: root.img+volatile.img (dom0)
This commit is contained in:
Marek Marczykowski-Górecki 2015-07-01 04:35:09 +02:00
parent a96d49a40a
commit 522bfc427a
2 changed files with 46 additions and 42 deletions

View File

@ -96,7 +96,7 @@ class QubesHVm(QubesVm):
(not 'xml_element' in kwargs or kwargs['xml_element'].get('guiagent_installed') is None):
self.services['meminfo-writer'] = False
self.storage.volatile_img = None
self.storage.rootcow_img = None
@property
def type(self):
@ -233,9 +233,7 @@ class QubesHVm(QubesVm):
if self.is_running():
raise NotImplementedError("Online resize of HVM's private.img not implemented, shutdown the VM first")
f_private = open (self.private_img, "a+b")
f_private.truncate (size)
f_private.close ()
self.storage.resize_private_img(size)
def resize_root_img(self, size):
if self.template:
@ -255,14 +253,6 @@ class QubesHVm(QubesVm):
f_root.truncate (size)
f_root.close ()
def get_rootdev(self, source_template=None):
if self.template:
return "'script:snapshot:{template_root}:{volatile},xvda,w',".format(
template_root=self.template.root_img,
volatile=self.volatile_img)
else:
return "'script:file:{root_img},xvda,w',".format(root_img=self.root_img)
def get_config_params(self):
params = super(QubesHVm, self).get_config_params()
@ -295,34 +285,6 @@ class QubesHVm(QubesVm):
return True
def reset_volatile_storage(self, **kwargs):
assert not self.is_running(), "Attempt to clean volatile image of running VM!"
source_template = kwargs.get("source_template", self.template)
if source_template is None:
# Nothing to do on non-template based VM
return
if os.path.exists (self.volatile_img):
if self.debug:
if os.path.getmtime(self.template.root_img) > os.path.getmtime(self.volatile_img):
if kwargs.get("verbose", False):
print >>sys.stderr, "--> WARNING: template have changed, resetting root.img"
else:
if kwargs.get("verbose", False):
print >>sys.stderr, "--> Debug mode: not resetting root.img"
print >>sys.stderr, "--> Debug mode: if you want to force root.img reset, either update template VM, or remove volatile.img file"
return
os.remove (self.volatile_img)
f_volatile = open (self.volatile_img, "w")
f_root = open (self.template.root_img, "r")
f_root.seek(0, os.SEEK_END)
f_volatile.truncate (f_root.tell()) # make empty sparse file of the same size as root.img
f_volatile.close ()
f_root.close()
@property
def vif(self):
if self.xid < 0:
@ -463,7 +425,6 @@ class QubesHVm(QubesVm):
guid_pid = open(guid_pidfile).read().strip()
os.kill(int(guid_pid), 15)
def suspend(self):
if dry_run:
return

View File

@ -76,7 +76,18 @@ class QubesXenVmStorage(QubesVmStorage):
"{dir}/root.img:{dir}/root-cow.img".format(
dir=self.vmdir),
"block-origin", self.root_dev, True)
elif self.vm.template and not self.vm.template.storage.rootcow_img:
# HVM template-based VM - template doesn't have own
# root-cow.img, only one device-mapper layer
return self._format_disk_dev(
"{tpldir}/root.img:{vmdir}/volatile.img".format(
tpldir=self.vm.template.dir_path,
vmdir=self.vmdir),
"block-snapshot", self.root_dev, True)
elif self.vm.template:
# any other template-based VM - two device-mapper layers: one
# in dom0 (here) from root+root-cow, and another one from
# this+volatile.img
return self._format_disk_dev(
"{dir}/root.img:{dir}/root-cow.img".format(
dir=self.vm.template.dir_path),
@ -170,7 +181,8 @@ class QubesXenVmStorage(QubesVmStorage):
def commit_template_changes(self):
assert self.vm.is_template()
# TODO: move rootcow_img to this class; the same for vm.is_outdated()
if not self.rootcow_img:
return
if os.path.exists (self.rootcow_img):
os.rename (self.rootcow_img, self.rootcow_img + '.old')
@ -183,3 +195,34 @@ class QubesXenVmStorage(QubesVmStorage):
f_root.close()
os.umask(old_umask)
def reset_volatile_storage(self, verbose = False, source_template = None):
if source_template is None:
source_template = self.vm.template
if source_template is not None:
# template-based VM with only one device-mapper layer -
# volatile.img used as upper layer on root.img, no root-cow.img
# intermediate layer
if not source_template.storage.rootcow_img:
if os.path.exists(self.volatile_img):
if self.vm.debug:
if os.path.getmtime(source_template.storage.root_img)\
> os.path.getmtime(self.volatile_img):
if verbose:
print >>sys.stderr, "--> WARNING: template have changed, resetting root.img"
else:
if verbose:
print >>sys.stderr, "--> Debug mode: not resetting root.img"
print >>sys.stderr, "--> Debug mode: if you want to force root.img reset, either update template VM, or remove volatile.img file"
return
os.remove(self.volatile_img)
f_volatile = open(self.volatile_img, "w")
f_root = open(source_template.storage.root_img, "r")
f_root.seek(0, os.SEEK_END)
f_volatile.truncate(f_root.tell()) # make empty sparse file of the same size as root.img
f_volatile.close()
f_root.close()
return
super(QubesXenVmStorage, self).reset_volatile_storage(
verbose=verbose, source_template=source_template)