~ubuntu-branches/ubuntu/quantal/virtinst/quantal-proposed

« back to all changes in this revision

Viewing changes to virt-image

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2007-11-20 13:40:28 UTC
  • Revision ID: james.westby@ubuntu.com-20071120134028-rg0pjby0jc4mycks
Tags: upstream-0.300.1+hg20071120
ImportĀ upstreamĀ versionĀ 0.300.1+hg20071120

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python -tt
 
2
#
 
3
# Create a virtual machine from an XML image description
 
4
#
 
5
# Copyright 2007  Red Hat, Inc.
 
6
# David Lutterkort <dlutter@redhat.com>
 
7
#
 
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.
 
12
#
 
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.
 
17
#
 
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,
 
21
# MA 02110-1301 USA.
 
22
 
 
23
import os, sys, string
 
24
from optparse import OptionParser, OptionValueError
 
25
import subprocess
 
26
import logging
 
27
import libxml2
 
28
import urlgrabber.progress as progress
 
29
 
 
30
import virtinst
 
31
import virtinst.ImageParser
 
32
import virtinst.CapabilitiesParser
 
33
import virtinst.cli as cli
 
34
 
 
35
import gettext
 
36
import locale
 
37
 
 
38
locale.setlocale(locale.LC_ALL, '')
 
39
gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir)
 
40
gettext.install(virtinst.gettext_app, virtinst.gettext_dir)
 
41
 
 
42
### General input gathering functions
 
43
 
 
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)
 
48
 
 
49
def get_vcpus(vcpus, image_vcpus, check_cpu, guest, conn):
 
50
    if vcpus is None:
 
51
        vcpus = int(image_vcpus)
 
52
    cli.get_vcpus(vcpus, check_cpu, guest, conn)
 
53
 
 
54
def get_networks(domain, macs, bridges, networks, guest):
 
55
    (macs, networks) = cli.digest_networks(macs, bridges, networks)
 
56
 
 
57
    nnics = 0
 
58
    if domain.interface:
 
59
        nnics = 1
 
60
 
 
61
    if nnics == 0 and len(networks) > 0:
 
62
        print >> sys.stderr, _("Warning: image does not support networking, ignoring network related options")
 
63
        return
 
64
    elif nnics == 1 and len(networks) == 0:
 
65
        print >> sys.stderr, _("The image needs one network interface")
 
66
        sys.exit(1)
 
67
 
 
68
    map(lambda m, n: cli.get_network(m, n, guest), macs, networks)
 
69
 
 
70
def get_graphics(domain, vnc, vncport, nographics, sdl, keymap, guest):
 
71
    if not domain.graphics:
 
72
        guest.graphics = False
 
73
        return
 
74
    else:
 
75
        cli.get_graphics(vnc, vncport, nographics, sdl, keymap, guest)
 
76
 
 
77
### Option parsing
 
78
def parse_args():
 
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."))
 
93
 
 
94
    # network options
 
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"))
 
104
 
 
105
    # graphics options
 
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."))
 
114
 
 
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"))
 
118
 
 
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())
 
123
 
 
124
    # fullvirt options
 
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)
 
127
 
 
128
    # Misc options
 
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"))
 
135
 
 
136
    (options,args) = parser.parse_args()
 
137
    if len(args) < 1:
 
138
        parser.error(_("You need to provide an image XML descriptor"))
 
139
    options.image = args[0]
 
140
    
 
141
    return options
 
142
 
 
143
def parse_image_xml(fname):
 
144
    if fname is None:
 
145
        print >> sys.stderr, _("Must provide the location of an image XML file with --image")
 
146
        sys.exit(1)
 
147
    if not os.access(fname, os.R_OK):
 
148
        print >> sys.stderr, _("Can not read %s") % fname
 
149
    file = open(fname, "r")
 
150
    xml = file.read()
 
151
    file.close()
 
152
    return virtinst.ImageParser.parse(xml, os.path.dirname(fname))
 
153
 
 
154
def main():
 
155
    options = parse_args()
 
156
 
 
157
    cli.setupLogging("virt-image", options.debug)
 
158
 
 
159
    conn = cli.getConnection(options.connect)
 
160
    type = None
 
161
 
 
162
    image = parse_image_xml(options.image)
 
163
    capabilities = virtinst.CapabilitiesParser.parse(conn.getCapabilities())
 
164
 
 
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)
 
169
            sys.exit(1)
 
170
 
 
171
    installer = virtinst.ImageInstaller(boot_index = options.boot,
 
172
                                        image = image,
 
173
                                        capabilities = capabilities)
 
174
 
 
175
    try:
 
176
        boot = installer.boot
 
177
    except virtinst.ImageManager.ImageInstallerException, e:
 
178
        print >> sys.stderr, _("ERROR: "), e
 
179
        sys.exit(1)
 
180
 
 
181
    hvm = boot.type == "hvm"
 
182
 
 
183
    if hvm:
 
184
        guest = virtinst.FullVirtGuest(connection=conn, installer=installer, arch=boot.arch)
 
185
    else:
 
186
        guest = virtinst.ParaVirtGuest(connection=conn, installer=installer)
 
187
 
 
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,
 
193
              guest, conn)
 
194
    # For now, we only allow one NIC
 
195
    get_networks(image.domain, options.mac, options.bridge,
 
196
                 options.network, guest)
 
197
 
 
198
    get_graphics(image.domain, options.vnc, options.vncport,
 
199
                 options.nographics, options.sdl, options.keymap, guest)
 
200
 
 
201
    if hvm:
 
202
        if options.noacpi:
 
203
            guest.features["acpi"] = False
 
204
        if options.noapic:
 
205
            guest.features["apic"] = False
 
206
 
 
207
    progresscb = progress.TextMeter()
 
208
 
 
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()
 
218
    else:
 
219
        try:
 
220
            print _("\n\nCreating guest %s...") % guest.name
 
221
 
 
222
            dom = guest.start_install(None, progresscb)
 
223
            if dom is None:
 
224
                print _("Guest creation failed")
 
225
                sys.exit(1)
 
226
 
 
227
        except RuntimeError, e:
 
228
            print >> sys.stderr, _("ERROR: "), e
 
229
            sys.exit(1)
 
230
        except Exception, 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,)
 
235
            raise
 
236
 
 
237
if __name__ == "__main__":
 
238
    main()
 
239