Update TemplateVM with running AppVM: part 2

- support for template modify in qvm-core
- tool for commit changes to template
This commit is contained in:
Marek Marczykowski 2011-02-27 00:06:46 +01:00
parent e104f82e36
commit 14aaccbc5f
3 changed files with 101 additions and 9 deletions

View File

@ -624,13 +624,14 @@ class QubesTemplateVm(QubesVm):
dir_path = kwargs["dir_path"]
# TempleteVM doesn't use root-cow image
if root_img is not None and os.path.isabs(root_img):
self.root_img = root_img
else:
self.root_img = dir_path + "/" + (
root_img if root_img is not None else default_root_img)
self.rootcow_img = dir_path + "/" + default_rootcow_img
if private_img is not None and os.path.isabs(private_img):
self.private_img = private_img
else:
@ -711,6 +712,14 @@ class QubesTemplateVm(QubesVm):
format(src_template_vm.root_img, self.root_img)
# We prefer to use Linux's cp, because it nicely handles sparse files
retcode = subprocess.call (["cp", src_template_vm.root_img, self.root_img])
if retcode != 0:
raise IOError ("Error while copying {0} to {1}".\
format(src_template_vm.root_img, self.root_img))
if verbose:
print "--> Copying the template's root COW image:\n{0} ==>\n{1}".\
format(src_template_vm.rootcow_img, self.rootcow_img)
# We prefer to use Linux's cp, because it nicely handles sparse files
retcode = subprocess.call (["cp", src_template_vm.rootcow_img, self.rootcow_img])
if retcode != 0:
raise IOError ("Error while copying {0} to {1}".\
format(src_template_vm.root_img, self.root_img))
@ -779,13 +788,29 @@ class QubesTemplateVm(QubesVm):
if not self.is_updateable():
raise QubesException ("Cannot start Template VM that is marked \"nonupdatable\"")
# First ensure that none of our appvms is running:
for appvm in self.appvms.values():
if appvm.is_running():
raise QubesException ("Cannot start TemplateVM when one of its AppVMs is running!")
# TODO?: check if none of running appvms are outdated
return super(QubesTemplateVm, self).start(debug_console=debug_console, verbose=verbose)
def commit_changes (self):
assert not self.is_running(), "Attempt to commit changes on running Template VM!"
print "--> Commiting template updates... COW: {0}...".format (self.rootcow_img)
if dry_run:
return
if os.path.exists (self.rootcow_img):
os.remove (self.rootcow_img)
f_cow = open (self.rootcow_img, "w")
f_root = open (self.root_img, "r")
f_root.seek(0, os.SEEK_END)
f_cow.truncate (f_root.tell()) # make empty sparse file of the same size as root.img
f_cow.close ()
f_root.close()
def create_xml_element(self):
element = xml.etree.ElementTree.Element(
"QubesTemplateVm",
@ -795,6 +820,7 @@ class QubesTemplateVm(QubesVm):
conf_file=self.conf_file,
appvms_conf_file=self.appvms_conf_file,
root_img=self.root_img,
rootcow_img=self.rootcow_img,
private_img=self.private_img,
uses_default_netvm=str(self.uses_default_netvm),
netvm_qid=str(self.netvm_vm.qid) if self.netvm_vm is not None else "none",
@ -1194,10 +1220,6 @@ class QubesAppVm(QubesVm):
if self.is_running():
raise QubesException("VM is already running!")
# First ensure that our template is *not* running:
if self.template_vm.is_running():
raise QubesException ("Cannot start AppVM when its template is running!")
if not self.is_updateable():
self.reset_cow_storage()
self.reset_swap_cow_storage()
@ -1728,3 +1750,4 @@ class QubesDaemonPidfile(object):
self.remove_pidfile()
# vim:sw=4:et:

View File

@ -42,6 +42,8 @@ def do_list(vm):
print fmt.format ("config", vm.conf_file)
if not vm.is_appvm():
print fmt.format ("root img", vm.root_img)
if vm.is_templete():
print fmt.format ("root COW img", vm.rootcow_img)
if vm.is_appvm():
print fmt.format ("root img", vm.template_vm.root_img)
print fmt.format ("root COW img", vm.rootcow_img)

View File

@ -0,0 +1,67 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser
import subprocess
qubes_guid_path = "/usr/bin/qubes_guid"
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if not vm.is_templatevm():
print "A VM '{0}' is not template.".format(vmname)
exit(1)
if vm.is_running():
print "You must stop VM first."
exit(1)
try:
vm.verify_files()
vm.commit_changes()
except (IOError, OSError, QubesException) as err:
print "ERROR: {0}".format(err)
exit (1)
exit (0)
main()