3
# Create a virtual machine from an XML image description
5
# Copyright 2007 Red Hat, Inc.
6
# David Lutterkort <dlutter@redhat.com>
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, write to the Free Software
20
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23
import os, sys, string
24
from optparse import OptionParser, OptionValueError
28
import urlgrabber.progress as progress
31
import virtinst.ImageParser
32
import virtinst.CapabilitiesParser
33
import virtinst.cli as cli
38
locale.setlocale(locale.LC_ALL, '')
39
gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir)
40
gettext.install(virtinst.gettext_app, virtinst.gettext_dir)
42
### General input gathering functions
44
def get_memory(memory, image_memory, guest):
45
if memory is None and image_memory is not None:
46
memory = int(image_memory)/1024
47
cli.get_memory(memory, guest)
49
def get_vcpus(vcpus, image_vcpus, check_cpu, guest, conn):
51
vcpus = int(image_vcpus)
52
cli.get_vcpus(vcpus, check_cpu, guest, conn)
54
def get_networks(domain, macs, bridges, networks, guest):
55
(macs, networks) = cli.digest_networks(macs, bridges, networks)
61
if nnics == 0 and len(networks) > 0:
62
print >> sys.stderr, _("Warning: image does not support networking, ignoring network related options")
64
elif nnics == 1 and len(networks) == 0:
65
print >> sys.stderr, _("The image needs one network interface")
68
map(lambda m, n: cli.get_network(m, n, guest), macs, networks)
70
def get_graphics(domain, vnc, vncport, nographics, sdl, keymap, guest):
71
if not domain.graphics:
72
guest.graphics = False
75
cli.get_graphics(vnc, vncport, nographics, sdl, keymap, guest)
79
parser = OptionParser()
80
parser.set_usage("%prog [options] image.xml")
81
parser.add_option("-n", "--name", type="string", dest="name",
82
action="callback", callback=cli.check_before_store,
83
help=_("Name of the guest instance"))
84
parser.add_option("-r", "--ram", type="int", dest="memory",
85
help=_("Memory to allocate for guest instance in megabytes"))
86
parser.add_option("-u", "--uuid", type="string", dest="uuid",
87
action="callback", callback=cli.check_before_store,
88
help=_("UUID for the guest; if none is given a random UUID will be generated. If you specify UUID, you should use a 32-digit hexadecimal number."))
89
parser.add_option("", "--vcpus", type="int", dest="vcpus",
90
help=_("Number of vcpus to configure for your guest"))
91
parser.add_option("", "--check-cpu", action="store_true", dest="check_cpu",
92
help=_("Check that vcpus do not exceed physical CPUs and warn if they do."))
95
parser.add_option("-m", "--mac", type="string",
96
dest="mac", action="callback", callback=cli.check_before_append,
97
help=_("Fixed MAC address for the guest; if none or RANDOM is given a random address will be used"))
98
parser.add_option("-b", "--bridge", type="string",
99
dest="bridge", action="callback", callback=cli.check_before_append,
100
help=_("Bridge to connect guest NIC to; if none given, will try to determine the default"))
101
parser.add_option("-w", "--network", type="string",
102
dest="network", action="callback", callback=cli.check_before_append,
103
help=_("Connect the guest to a virtual network, forwarding to the physical network with NAT"))
106
parser.add_option("", "--vnc", action="store_true", dest="vnc",
107
help=_("Use VNC for graphics support"))
108
parser.add_option("", "--vncport", type="int", dest="vncport",
109
help=_("Port to use for VNC"))
110
parser.add_option("", "--sdl", action="store_true", dest="sdl",
111
help=_("Use SDL for graphics support"))
112
parser.add_option("", "--nographics", action="store_true",
113
help=_("Don't set up a graphical console for the guest."))
115
parser.add_option("-k", "--keymap", type="string", dest="keymap",
116
action="callback", callback=cli.check_before_store,
117
help=_("set up keymap for a graphical console"))
119
parser.add_option("", "--connect", type="string", dest="connect",
120
action="callback", callback=cli.check_before_store,
121
help=_("Connect to hypervisor with URI"),
122
default=virtinst.util.default_connection())
125
parser.add_option("", "--noapic", action="store_true", dest="noapic", help=_("Disables APIC for fully virtualized guest (overrides value in os-type/os-variant db)"), default=False)
126
parser.add_option("", "--noacpi", action="store_true", dest="noacpi", help=_("Disables ACPI for fully virtualized guest (overrides value in os-type/os-variant db)"), default=False)
129
parser.add_option("-d", "--debug", action="store_true", dest="debug",
130
help=_("Print debugging information"))
131
parser.add_option("-p", "--print", action="store_true", dest="print_only",
132
help=_("Print the libvirt XML, but do not start the domain"))
133
parser.add_option("", "--boot", type="int", dest="boot",
134
help=_("The zero-based index of the boot record to use"))
136
(options,args) = parser.parse_args()
138
parser.error(_("You need to provide an image XML descriptor"))
139
options.image = args[0]
143
def parse_image_xml(fname):
145
print >> sys.stderr, _("Must provide the location of an image XML file with --image")
147
if not os.access(fname, os.R_OK):
148
print >> sys.stderr, _("Can not read %s") % fname
149
file = open(fname, "r")
152
return virtinst.ImageParser.parse(xml, os.path.dirname(fname))
155
options = parse_args()
157
cli.setupLogging("virt-image", options.debug)
159
conn = cli.getConnection(options.connect)
162
image = parse_image_xml(options.image)
163
capabilities = virtinst.CapabilitiesParser.parse(conn.getCapabilities())
165
if options.boot is not None:
166
nboots = len(image.domain.boots)
167
if options.boot < 0 or options.boot >= nboots:
168
print >> sys.stderr, _("The index for --boot must be between 0 and %d") % (nboots - 1)
171
installer = virtinst.ImageInstaller(boot_index = options.boot,
173
capabilities = capabilities)
176
boot = installer.boot
177
except virtinst.ImageManager.ImageInstallerException, e:
178
print >> sys.stderr, _("ERROR: "), e
181
hvm = boot.type == "hvm"
184
guest = virtinst.FullVirtGuest(connection=conn, installer=installer, arch=boot.arch)
186
guest = virtinst.ParaVirtGuest(connection=conn, installer=installer)
188
# now let's get some of the common questions out of the way
189
cli.get_name(options.name, guest)
190
get_memory(options.memory, image.domain.memory, guest)
191
cli.get_uuid(options.uuid, guest)
192
get_vcpus(options.vcpus, image.domain.vcpu, options.check_cpu,
194
# For now, we only allow one NIC
195
get_networks(image.domain, options.mac, options.bridge,
196
options.network, guest)
198
get_graphics(image.domain, options.vnc, options.vncport,
199
options.nographics, options.sdl, options.keymap, guest)
203
guest.features["acpi"] = False
205
guest.features["apic"] = False
207
progresscb = progress.TextMeter()
209
# we've got everything -- try to start the install
210
if options.print_only:
211
# FIXME: Ugly remix of Guest.start_install/_do_install
212
# Should be exposed by Guest in a different way
213
meter = progress.BaseMeter()
214
guest.validate_parms()
215
guest._prepare_install(meter)
216
guest._create_devices(meter)
217
print guest.get_config_xml()
220
print _("\n\nCreating guest %s...") % guest.name
222
dom = guest.start_install(None, progresscb)
224
print _("Guest creation failed")
227
except RuntimeError, e:
228
print >> sys.stderr, _("ERROR: "), e
231
print _("Domain creation may not have been\n"
232
"successful. If it was, you can restart your domain\n"
233
"by running 'virsh start %s'; otherwise, please\n"
234
"restart your installation.") %(guest.name,)
237
if __name__ == "__main__":