core-admin/qvm-tools/qvm-create
Marek Marczykowski-Górecki 90393c33f2
core: add offline mode to qvm-create, qvm-prefs
This is required to create VMs in process of building Live system, where
libvirt isn't running.

Additionally there is no udev in the build environment, so needs to
manually create /dev/loop*p* based on sysfs info.
2015-08-01 21:58:38 +02:00

214 lines
8.5 KiB
Python
Executable File

#!/usr/bin/python2
# -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
#
# 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 QubesVmLabels
from qubes.qubes import QubesException
from optparse import OptionParser;
import subprocess
import re
import os
import sys
from qubes.qubes import vmm
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
parser.add_option ("-t", "--template", dest="template",
help="Specify the TemplateVM to use")
parser.add_option ("-l", "--label", dest="label",
help="Specify the label to use for the new VM (e.g. red, yellow, green, ...)")
parser.add_option ("-p", "--proxy", action="store_true", dest="proxyvm", default=False,
help="Create ProxyVM")
parser.add_option ("-H", "--hvm", action="store_true", dest="hvm", default=False,
help="Create HVM (standalone unless --template option used)")
parser.add_option ("--hvm-template", action="store_true", dest="hvm_template", default=False,
help="Create HVM template")
parser.add_option ("-n", "--net", action="store_true", dest="netvm", default=False,
help="Create NetVM")
parser.add_option ("-s", "--standalone", action="store_true", dest="standalone", default=False,
help="Create standalone VM - independent of template ")
parser.add_option ("-R", "--root-move-from", dest="root_move", default=None,
help="Use provided root.img instead of default/empty one (file will be MOVED)")
parser.add_option ("-r", "--root-copy-from", dest="root_copy", default=None,
help="Use provided root.img instead of default/empty one (file will be COPIED)")
parser.add_option ("-m", "--mem", dest="mem", default=None,
help="Initial memory size (in MB)")
parser.add_option ("-c", "--vcpus", dest="vcpus", default=None,
help="VCPUs count")
parser.add_option ("--offline-mode", dest="offline_mode",
action="store_true", default=False,
help="Offline mode")
parser.add_option ("-i", "--internal", action="store_true", dest="internal", default=False,
help="Create VM for internal use only (hidden in qubes-manager, no appmenus)")
parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
help="Force to run, even with root privileges")
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
if (options.netvm + options.proxyvm + options.hvm + options.hvm_template) > 1:
parser.error ("You must specify at most one VM type switch")
if hasattr(os, "geteuid") and os.geteuid() == 0:
print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems."
if options.force_root:
print >> sys.stderr, "Continuing as commanded. You have been warned."
else:
print >> sys.stderr, "Retry as unprivileged user."
print >> sys.stderr, "... or use --force-root to continue anyway."
exit(1)
if options.label is None:
print >> sys.stderr, "You must choose a label for the new VM by passing the --label option."
print >> sys.stderr, "Possible values are:"
for l in QubesVmLabels.values():
print >> sys.stderr, "* {0}".format(l.name)
exit (1)
if options.label not in QubesVmLabels:
print >> sys.stderr, "Wrong label name, supported values are the following:"
for l in QubesVmLabels.values():
print >> sys.stderr, "* {0}".format(l.name)
exit (1)
label = QubesVmLabels[options.label]
if options.hvm and not options.template:
options.standalone = True
if options.hvm_template:
options.standalone = True
if not options.standalone and any([options.root_copy, options.root_move]):
print >> sys.stderr, "root.img can be specified only for standalone VMs"
exit (1)
if options.hvm_template and options.template is not None:
print >> sys.stderr, "Template VM cannot be based on another template"
exit (1)
if options.root_copy and options.root_move:
print >> sys.stderr, "Only one of --root-move-from and --root-copy from can be specified"
exit(1)
if options.root_copy is not None and not os.path.exists(options.root_copy):
print >> sys.stderr, "File specified as root.img does not exists"
exit (1)
if options.root_move is not None and not os.path.exists(options.root_move):
print >> sys.stderr, "File specified as root.img does not exists"
exit (1)
if options.offline_mode:
vmm.offline_mode = True
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
if qvm_collection.get_vm_by_name(vmname) is not None:
print >> sys.stderr, "A VM with the name '{0}' already exists in the system.".format(vmname)
exit(1)
template = None
if options.template is not None:
template = qvm_collection.get_vm_by_name(options.template)
if template is None:
print >> sys.stderr, "There is no (Template)VM with the name '{0}'".format(options.template)
exit (1)
if not template.is_template():
print >> sys.stderr, "VM '{0}' is not a TemplateVM".format(options.template)
exit (1)
if (options.verbose):
print "--> Using TemplateVM: {0}".format(template.name)
elif not options.hvm and not options.hvm_template:
if qvm_collection.get_default_template() is None:
print >> sys.stderr, "No default TemplateVM defined!"
exit (1)
else:
template = qvm_collection.get_default_template()
if (options.verbose):
print "--> Using default TemplateVM: {0}".format(template.name)
if options.standalone:
new_vm_template = None
else:
new_vm_template = template
vm = None
if options.netvm:
vmtype = "QubesNetVm"
elif options.proxyvm:
vmtype = "QubesProxyVm"
elif options.hvm:
vmtype = "QubesHVm"
elif options.hvm_template:
vmtype = "QubesTemplateHVm"
else:
vmtype = "QubesAppVm"
try:
vm = qvm_collection.add_new_vm(vmtype, name=vmname, template=new_vm_template, label = label)
except QubesException as err:
print >> sys.stderr, "ERROR: {0}".format(err)
exit (1)
if options.internal:
vm.internal = True
if options.mem is not None:
vm.memory = options.mem
if options.vcpus is not None:
vm.vcpus = options.vcpus
try:
vm.create_on_disk(verbose=options.verbose, source_template=template)
if options.root_move:
if (options.verbose):
print "--> Replacing root.img with provided file"
os.unlink(vm.root_img)
os.rename(options.root_move, vm.root_img)
elif options.root_copy:
if (options.verbose):
print "--> Replacing root.img with provided file"
os.unlink(vm.root_img)
# use "cp" to preserve sparse file
subprocess.check_call(["cp", options.root_copy, vm.root_img])
except (IOError, OSError) as err:
print >> sys.stderr, "ERROR: {0}".format(err)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()