From 91428ebaa18c92c87dadf4c7341640fa77bcb0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 21 Mar 2014 18:43:13 +0100 Subject: [PATCH] core: method to resize root.img (#699) --- core-modules/000QubesVm.py | 1 + core-modules/01QubesHVm.py | 18 ++++++++ core-modules/02QubesTemplateHVm.py | 7 ++++ qvm-tools/qvm-grow-root | 67 ++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100755 qvm-tools/qvm-grow-root diff --git a/core-modules/000QubesVm.py b/core-modules/000QubesVm.py index 8b7c9072..a79f726d 100644 --- a/core-modules/000QubesVm.py +++ b/core-modules/000QubesVm.py @@ -778,6 +778,7 @@ class QubesVm(object): raise QubesException("resize2fs failed") + # FIXME: should be outside of QubesVM? def get_timezone(self): # fc18 diff --git a/core-modules/01QubesHVm.py b/core-modules/01QubesHVm.py index 6ef2cc59..dd6869d3 100644 --- a/core-modules/01QubesHVm.py +++ b/core-modules/01QubesHVm.py @@ -231,6 +231,24 @@ class QubesHVm(QubesVm): f_private.truncate (size) f_private.close () + def resize_root_img(self, size): + if self.template: + raise QubesException("Cannot resize root.img of template-based VM" + ". Resize the root.img of the template " + "instead.") + + if self.is_running(): + raise QubesException("Cannot resize root.img of running HVM") + + if size < self.get_root_img_sz(): + raise QubesException( + "For your own safety shringing of root.img is disabled. If " + "you really know what you are doing, use 'truncate' manually.") + + f_root = open (self.root_img, "a+b") + 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( diff --git a/core-modules/02QubesTemplateHVm.py b/core-modules/02QubesTemplateHVm.py index 455cf17f..e1ab1325 100644 --- a/core-modules/02QubesTemplateHVm.py +++ b/core-modules/02QubesTemplateHVm.py @@ -71,6 +71,13 @@ class QubesTemplateHVm(QubesHVm): def is_template_compatible(cls, template): return False + def resize_root_img(self, size): + for vm in self.appvms.values(): + if vm.is_running(): + raise QubesException("Cannot resize root.img while any VM " + "based on this tempate is running") + return super(QubesTemplateHVm, self).resize_root_img() + def start(self, *args, **kwargs): for vm in self.appvms.values(): if vm.is_running(): diff --git a/qvm-tools/qvm-grow-root b/qvm-tools/qvm-grow-root new file mode 100755 index 00000000..36baa7c9 --- /dev/null +++ b/qvm-tools/qvm-grow-root @@ -0,0 +1,67 @@ +#!/usr/bin/python2 +# +# The Qubes OS Project, http://www.qubes-os.org +# +# Copyright (C) 2014 Marek Marczykowski-Górecki +# +# 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 qubes.qubesutils import parse_size +from optparse import OptionParser +import subprocess +import os +import re +import sys + +def main(): + usage = "usage: %prog " + parser = OptionParser (usage) + + (options, args) = parser.parse_args () + if (len (args) != 2): + parser.error ("You must specify VM name and new size!") + vmname = args[0] + size = args[1] + + 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 >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname) + exit(1) + + size_bytes = parse_size(size) + + if not hasattr(vm, 'resize_root_img'): + print >> sys.stderr, "Operation not supported for this VM type" + exit(1) + + try: + vm.resize_root_img(size_bytes) + except (IOError, OSError, QubesException) as err: + print >> sys.stderr, "ERROR: {0}".format(err) + exit (1) + + exit (0) + + +main()