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:
parent
a96d49a40a
commit
522bfc427a
@ -96,7 +96,7 @@ class QubesHVm(QubesVm):
|
|||||||
(not 'xml_element' in kwargs or kwargs['xml_element'].get('guiagent_installed') is None):
|
(not 'xml_element' in kwargs or kwargs['xml_element'].get('guiagent_installed') is None):
|
||||||
self.services['meminfo-writer'] = False
|
self.services['meminfo-writer'] = False
|
||||||
|
|
||||||
self.storage.volatile_img = None
|
self.storage.rootcow_img = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
@ -233,9 +233,7 @@ class QubesHVm(QubesVm):
|
|||||||
if self.is_running():
|
if self.is_running():
|
||||||
raise NotImplementedError("Online resize of HVM's private.img not implemented, shutdown the VM first")
|
raise NotImplementedError("Online resize of HVM's private.img not implemented, shutdown the VM first")
|
||||||
|
|
||||||
f_private = open (self.private_img, "a+b")
|
self.storage.resize_private_img(size)
|
||||||
f_private.truncate (size)
|
|
||||||
f_private.close ()
|
|
||||||
|
|
||||||
def resize_root_img(self, size):
|
def resize_root_img(self, size):
|
||||||
if self.template:
|
if self.template:
|
||||||
@ -255,14 +253,6 @@ class QubesHVm(QubesVm):
|
|||||||
f_root.truncate (size)
|
f_root.truncate (size)
|
||||||
f_root.close ()
|
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):
|
def get_config_params(self):
|
||||||
|
|
||||||
params = super(QubesHVm, self).get_config_params()
|
params = super(QubesHVm, self).get_config_params()
|
||||||
@ -295,34 +285,6 @@ class QubesHVm(QubesVm):
|
|||||||
|
|
||||||
return True
|
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
|
@property
|
||||||
def vif(self):
|
def vif(self):
|
||||||
if self.xid < 0:
|
if self.xid < 0:
|
||||||
@ -463,7 +425,6 @@ class QubesHVm(QubesVm):
|
|||||||
guid_pid = open(guid_pidfile).read().strip()
|
guid_pid = open(guid_pidfile).read().strip()
|
||||||
os.kill(int(guid_pid), 15)
|
os.kill(int(guid_pid), 15)
|
||||||
|
|
||||||
|
|
||||||
def suspend(self):
|
def suspend(self):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
return
|
return
|
||||||
|
@ -76,7 +76,18 @@ class QubesXenVmStorage(QubesVmStorage):
|
|||||||
"{dir}/root.img:{dir}/root-cow.img".format(
|
"{dir}/root.img:{dir}/root-cow.img".format(
|
||||||
dir=self.vmdir),
|
dir=self.vmdir),
|
||||||
"block-origin", self.root_dev, True)
|
"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:
|
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(
|
return self._format_disk_dev(
|
||||||
"{dir}/root.img:{dir}/root-cow.img".format(
|
"{dir}/root.img:{dir}/root-cow.img".format(
|
||||||
dir=self.vm.template.dir_path),
|
dir=self.vm.template.dir_path),
|
||||||
@ -170,7 +181,8 @@ class QubesXenVmStorage(QubesVmStorage):
|
|||||||
|
|
||||||
def commit_template_changes(self):
|
def commit_template_changes(self):
|
||||||
assert self.vm.is_template()
|
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):
|
if os.path.exists (self.rootcow_img):
|
||||||
os.rename (self.rootcow_img, self.rootcow_img + '.old')
|
os.rename (self.rootcow_img, self.rootcow_img + '.old')
|
||||||
|
|
||||||
@ -183,3 +195,34 @@ class QubesXenVmStorage(QubesVmStorage):
|
|||||||
f_root.close()
|
f_root.close()
|
||||||
os.umask(old_umask)
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user