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:
parent
e104f82e36
commit
14aaccbc5f
@ -624,13 +624,14 @@ class QubesTemplateVm(QubesVm):
|
|||||||
|
|
||||||
dir_path = kwargs["dir_path"]
|
dir_path = kwargs["dir_path"]
|
||||||
|
|
||||||
# TempleteVM doesn't use root-cow image
|
|
||||||
if root_img is not None and os.path.isabs(root_img):
|
if root_img is not None and os.path.isabs(root_img):
|
||||||
self.root_img = root_img
|
self.root_img = root_img
|
||||||
else:
|
else:
|
||||||
self.root_img = dir_path + "/" + (
|
self.root_img = dir_path + "/" + (
|
||||||
root_img if root_img is not None else default_root_img)
|
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):
|
if private_img is not None and os.path.isabs(private_img):
|
||||||
self.private_img = private_img
|
self.private_img = private_img
|
||||||
else:
|
else:
|
||||||
@ -711,6 +712,14 @@ class QubesTemplateVm(QubesVm):
|
|||||||
format(src_template_vm.root_img, self.root_img)
|
format(src_template_vm.root_img, self.root_img)
|
||||||
# We prefer to use Linux's cp, because it nicely handles sparse files
|
# 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])
|
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:
|
if retcode != 0:
|
||||||
raise IOError ("Error while copying {0} to {1}".\
|
raise IOError ("Error while copying {0} to {1}".\
|
||||||
format(src_template_vm.root_img, self.root_img))
|
format(src_template_vm.root_img, self.root_img))
|
||||||
@ -779,13 +788,29 @@ class QubesTemplateVm(QubesVm):
|
|||||||
if not self.is_updateable():
|
if not self.is_updateable():
|
||||||
raise QubesException ("Cannot start Template VM that is marked \"nonupdatable\"")
|
raise QubesException ("Cannot start Template VM that is marked \"nonupdatable\"")
|
||||||
|
|
||||||
# First ensure that none of our appvms is running:
|
# TODO?: check if none of running appvms are outdated
|
||||||
for appvm in self.appvms.values():
|
|
||||||
if appvm.is_running():
|
|
||||||
raise QubesException ("Cannot start TemplateVM when one of its AppVMs is running!")
|
|
||||||
|
|
||||||
return super(QubesTemplateVm, self).start(debug_console=debug_console, verbose=verbose)
|
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):
|
def create_xml_element(self):
|
||||||
element = xml.etree.ElementTree.Element(
|
element = xml.etree.ElementTree.Element(
|
||||||
"QubesTemplateVm",
|
"QubesTemplateVm",
|
||||||
@ -795,6 +820,7 @@ class QubesTemplateVm(QubesVm):
|
|||||||
conf_file=self.conf_file,
|
conf_file=self.conf_file,
|
||||||
appvms_conf_file=self.appvms_conf_file,
|
appvms_conf_file=self.appvms_conf_file,
|
||||||
root_img=self.root_img,
|
root_img=self.root_img,
|
||||||
|
rootcow_img=self.rootcow_img,
|
||||||
private_img=self.private_img,
|
private_img=self.private_img,
|
||||||
uses_default_netvm=str(self.uses_default_netvm),
|
uses_default_netvm=str(self.uses_default_netvm),
|
||||||
netvm_qid=str(self.netvm_vm.qid) if self.netvm_vm is not None else "none",
|
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():
|
if self.is_running():
|
||||||
raise QubesException("VM is already 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():
|
if not self.is_updateable():
|
||||||
self.reset_cow_storage()
|
self.reset_cow_storage()
|
||||||
self.reset_swap_cow_storage()
|
self.reset_swap_cow_storage()
|
||||||
@ -1728,3 +1750,4 @@ class QubesDaemonPidfile(object):
|
|||||||
self.remove_pidfile()
|
self.remove_pidfile()
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:et:
|
||||||
|
@ -42,6 +42,8 @@ def do_list(vm):
|
|||||||
print fmt.format ("config", vm.conf_file)
|
print fmt.format ("config", vm.conf_file)
|
||||||
if not vm.is_appvm():
|
if not vm.is_appvm():
|
||||||
print fmt.format ("root img", vm.root_img)
|
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():
|
if vm.is_appvm():
|
||||||
print fmt.format ("root img", vm.template_vm.root_img)
|
print fmt.format ("root img", vm.template_vm.root_img)
|
||||||
print fmt.format ("root COW img", vm.rootcow_img)
|
print fmt.format ("root COW img", vm.rootcow_img)
|
||||||
|
67
dom0/qvm-tools/qvm-template-commit
Executable file
67
dom0/qvm-tools/qvm-template-commit
Executable 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()
|
Loading…
Reference in New Issue
Block a user