~ubuntu-branches/ubuntu/precise/nova/precise

1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3
# Copyright 2010 United States Government as represented by the
4
# Administrator of the National Aeronautics and Space Administration.
5
# All Rights Reserved.
6
# Copyright (c) 2010 Citrix Systems, Inc.
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
7
# Copyright (c) 2011 Piston Cloud Computing, Inc
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
8
#
9
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
10
#    not use this file except in compliance with the License. You may obtain
11
#    a copy of the License at
12
#
13
#         http://www.apache.org/licenses/LICENSE-2.0
14
#
15
#    Unless required by applicable law or agreed to in writing, software
16
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18
#    License for the specific language governing permissions and limitations
19
#    under the License.
20
21
"""
22
A connection to a hypervisor through libvirt.
23
24
Supports KVM, LXC, QEMU, UML, and XEN.
25
26
**Related Flags**
27
28
:libvirt_type:  Libvirt domain type.  Can be kvm, qemu, uml, xen
29
                (default: kvm).
30
:libvirt_uri:  Override for the default libvirt URI (depends on libvirt_type).
31
:libvirt_xml_template:  Libvirt XML Template.
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
32
:libvirt_disk_prefix:  Override the default disk prefix for the devices
33
                       attached to a server.
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
34
:rescue_image_id:  Rescue ami image (None = original image).
35
:rescue_kernel_id:  Rescue aki image (None = original image).
36
:rescue_ramdisk_id:  Rescue ari image (None = original image).
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
37
:injected_network_template:  Template file for injected network
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
38
:allow_same_net_traffic:  Whether to allow in project network traffic
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
39
40
"""
41
67 by Chuck Short, Monty Taylor, Chuck Short, Joseph Heck
[ Monty Taylor ]
42
import errno
1.1.19 by Chuck Short
Import upstream version 2011.3~d2~20110617.1191
43
import hashlib
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
44
import functools
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
45
import glob
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
46
import multiprocessing
47
import os
48
import shutil
49
import sys
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
50
import time
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
51
import uuid
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
52
53
from eventlet import greenthread
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
54
from eventlet import tpool
55
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
56
from xml.dom import minidom
57
from xml.etree import ElementTree
58
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
59
from nova import block_device
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
60
from nova.compute import instance_types
61
from nova.compute import power_state
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
62
from nova import context as nova_context
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
63
from nova import db
64
from nova import exception
65
from nova import flags
1.1.19 by Chuck Short
Import upstream version 2011.3~d2~20110617.1191
66
import nova.image
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
67
from nova import log as logging
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
68
from nova.openstack.common import cfg
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
69
from nova import utils
70
from nova.virt import driver
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
71
from nova.virt.disk import api as disk
72
from nova.virt.libvirt import firewall
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
73
from nova.virt.libvirt import imagecache
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
74
from nova.virt.libvirt import utils as libvirt_utils
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
75
76
77
libvirt = None
78
Template = None
79
80
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
81
LOG = logging.getLogger(__name__)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
82
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
83
libvirt_opts = [
84
    cfg.StrOpt('rescue_image_id',
85
               default=None,
86
               help='Rescue ami image'),
87
    cfg.StrOpt('rescue_kernel_id',
88
               default=None,
89
               help='Rescue aki image'),
90
    cfg.StrOpt('rescue_ramdisk_id',
91
               default=None,
92
               help='Rescue ari image'),
93
    cfg.StrOpt('libvirt_xml_template',
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
94
               default='$pybasedir/nova/virt/libvirt.xml.template',
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
95
               help='Libvirt XML Template'),
96
    cfg.StrOpt('libvirt_type',
97
               default='kvm',
98
               help='Libvirt domain type (valid options are: '
99
                    'kvm, lxc, qemu, uml, xen)'),
100
    cfg.StrOpt('libvirt_uri',
101
               default='',
102
               help='Override the default libvirt URI '
103
                    '(which is dependent on libvirt_type)'),
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
104
    cfg.BoolOpt('libvirt_inject_password',
105
                default=False,
106
                help='Inject the admin password at boot time, '
107
                     'without an agent.'),
108
    cfg.BoolOpt('use_usb_tablet',
109
                default=True,
110
                help='Sync virtual and real mouse cursors in Windows VMs'),
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
111
    cfg.StrOpt('cpuinfo_xml_template',
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
112
               default='$pybasedir/nova/virt/cpuinfo.xml.template',
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
113
               help='CpuInfo XML Template (Used only live migration now)'),
114
    cfg.StrOpt('live_migration_uri',
115
               default="qemu+tcp://%s/system",
116
               help='Define protocol used by live_migration feature'),
117
    cfg.StrOpt('live_migration_flag',
118
               default='VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER',
119
               help='Define live migration behavior.'),
120
    cfg.StrOpt('block_migration_flag',
121
               default='VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, '
122
                       'VIR_MIGRATE_NON_SHARED_INC',
123
               help='Define block migration behavior.'),
124
    cfg.IntOpt('live_migration_bandwidth',
125
               default=0,
126
               help='Define live migration behavior'),
127
    cfg.StrOpt('snapshot_image_format',
128
               default=None,
129
               help='Snapshot image format (valid options are : '
130
                    'raw, qcow2, vmdk, vdi). '
131
                    'Defaults to same as source image'),
132
    cfg.StrOpt('libvirt_vif_type',
133
               default='bridge',
134
               help='Type of VIF to create.'),
135
    cfg.StrOpt('libvirt_vif_driver',
136
               default='nova.virt.libvirt.vif.LibvirtBridgeDriver',
137
               help='The libvirt VIF driver to configure the VIFs.'),
138
    cfg.ListOpt('libvirt_volume_drivers',
139
                default=[
140
                  'iscsi=nova.virt.libvirt.volume.LibvirtISCSIVolumeDriver',
141
                  'local=nova.virt.libvirt.volume.LibvirtVolumeDriver',
142
                  'fake=nova.virt.libvirt.volume.LibvirtFakeVolumeDriver',
143
                  'rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver',
144
                  'sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver'
145
                  ],
146
                help='Libvirt handlers for remote volumes.'),
147
    cfg.BoolOpt('libvirt_use_virtio_for_bridges',
148
                default=False,
149
                help='Use virtio for bridge interfaces'),
150
    cfg.StrOpt('libvirt_disk_prefix',
151
               default=None,
152
               help='Override the default disk prefix for the devices attached'
153
                    ' to a server, which is dependent on libvirt_type. '
154
                    '(valid options are: sd, xvd, uvd, vd)'),
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
155
    cfg.IntOpt('libvirt_wait_soft_reboot_seconds',
156
               default=120,
157
               help='Number of seconds to wait for instance to shut down after'
158
                    ' soft reboot request is made. We fall back to hard reboot'
159
                    ' if instance does not shutdown within this window.'),
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
160
    cfg.BoolOpt('libvirt_nonblocking',
161
                default=False,
162
                help='Use a separated OS thread pool to realize non-blocking'
163
                     ' libvirt calls')
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
164
    ]
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
165
166
FLAGS = flags.FLAGS
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
167
FLAGS.register_opts(libvirt_opts)
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
168
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
169
flags.DECLARE('live_migration_retry_count', 'nova.compute.manager')
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
170
flags.DECLARE('vncserver_proxyclient_address', 'nova.vnc')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
171
172
173
def get_connection(read_only):
174
    # These are loaded late so that there's no need to install these
175
    # libraries when not using libvirt.
176
    # Cheetah is separate because the unit tests want to load Cheetah,
177
    # but not libvirt.
178
    global libvirt
179
    if libvirt is None:
180
        libvirt = __import__('libvirt')
181
    _late_load_cheetah()
182
    return LibvirtConnection(read_only)
183
184
185
def _late_load_cheetah():
186
    global Template
187
    if Template is None:
188
        t = __import__('Cheetah.Template', globals(), locals(),
189
                       ['Template'], -1)
190
        Template = t.Template
191
192
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
193
def _get_eph_disk(ephemeral):
194
    return 'disk.eph' + str(ephemeral['num'])
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
195
196
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
197
class LibvirtConnection(driver.ComputeDriver):
198
199
    def __init__(self, read_only):
200
        super(LibvirtConnection, self).__init__()
201
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
202
        self._host_state = None
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
203
        self._initiator = None
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
204
        self._wrapped_conn = None
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
205
        self.container = None
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
206
        self.read_only = read_only
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
207
        if FLAGS.firewall_driver not in firewall.drivers:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
208
            FLAGS.set_default('firewall_driver', firewall.drivers[0])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
209
        fw_class = utils.import_class(FLAGS.firewall_driver)
210
        self.firewall_driver = fw_class(get_connection=self._get_connection)
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
211
        self.vif_driver = utils.import_object(FLAGS.libvirt_vif_driver)
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
212
        self.volume_drivers = {}
213
        for driver_str in FLAGS.libvirt_volume_drivers:
214
            driver_type, _sep, driver = driver_str.partition('=')
215
            driver_class = utils.import_class(driver)
216
            self.volume_drivers[driver_type] = driver_class(self)
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
217
        self._host_state = None
43 by Chuck Short, James Page, Adam Gandelman, Ante Karamatic, Chuck Short
[James Page]
218
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
219
        disk_prefix_map = {"lxc": "", "uml": "ubd", "xen": "sd"}
220
        if FLAGS.libvirt_disk_prefix:
221
            self._disk_prefix = FLAGS.libvirt_disk_prefix
222
        else:
223
            self._disk_prefix = disk_prefix_map.get(FLAGS.libvirt_type, 'vd')
224
        self.default_root_device = self._disk_prefix + 'a'
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
225
        self.default_second_device = self._disk_prefix + 'b'
226
        self.default_third_device = self._disk_prefix + 'c'
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
227
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
228
        self._disk_cachemode = None
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
229
        self.image_cache_manager = imagecache.ImageCacheManager()
230
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
231
    @property
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
232
    def disk_cachemode(self):
233
        if self._disk_cachemode is None:
234
            # We prefer 'none' for consistent performance, host crash
235
            # safety & migration correctness by avoiding host page cache.
236
            # Some filesystems (eg GlusterFS via FUSE) don't support
237
            # O_DIRECT though. For those we fallback to 'writethrough'
238
            # which gives host crash safety, and is safe for migration
239
            # provided the filesystem is cache coherant (cluster filesystems
240
            # typically are, but things like NFS are not).
241
            self._disk_cachemode = "none"
242
            if not self._supports_direct_io(FLAGS.instances_path):
243
                self._disk_cachemode = "writethrough"
244
        return self._disk_cachemode
67 by Chuck Short, Monty Taylor, Chuck Short, Joseph Heck
[ Monty Taylor ]
245
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
246
    @property
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
247
    def host_state(self):
248
        if not self._host_state:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
249
            self._host_state = HostState(self.read_only)
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
250
        return self._host_state
251
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
252
    def init_host(self, host):
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
253
        # NOTE(nsokolov): moved instance restarting to ComputeManager
254
        pass
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
255
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
256
    @property
257
    def libvirt_xml(self):
258
        if not hasattr(self, '_libvirt_xml_cache_info'):
259
            self._libvirt_xml_cache_info = {}
260
261
        return utils.read_cached_file(FLAGS.libvirt_xml_template,
262
                self._libvirt_xml_cache_info)
263
264
    @property
265
    def cpuinfo_xml(self):
266
        if not hasattr(self, '_cpuinfo_xml_cache_info'):
267
            self._cpuinfo_xml_cache_info = {}
268
269
        return utils.read_cached_file(FLAGS.cpuinfo_xml_template,
270
                self._cpuinfo_xml_cache_info)
271
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
272
    def _get_connection(self):
273
        if not self._wrapped_conn or not self._test_connection():
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
274
            LOG.debug(_('Connecting to libvirt: %s'), self.uri)
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
275
            if not FLAGS.libvirt_nonblocking:
276
                self._wrapped_conn = self._connect(self.uri,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
277
                                               self.read_only)
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
278
            else:
279
                self._wrapped_conn = tpool.proxy_call(
280
                    (libvirt.virDomain, libvirt.virConnect),
281
                    self._connect, self.uri, self.read_only)
282
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
283
        return self._wrapped_conn
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
284
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
285
    _conn = property(_get_connection)
286
287
    def _test_connection(self):
288
        try:
1.1.32 by Chuck Short
Import upstream version 2011.3
289
            self._wrapped_conn.getCapabilities()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
290
            return True
291
        except libvirt.libvirtError as e:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
292
            if (e.get_error_code() == libvirt.VIR_ERR_SYSTEM_ERROR and
293
                e.get_error_domain() in (libvirt.VIR_FROM_REMOTE,
294
                                         libvirt.VIR_FROM_RPC)):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
295
                LOG.debug(_('Connection to libvirt broke'))
296
                return False
297
            raise
298
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
299
    @property
300
    def uri(self):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
301
        if FLAGS.libvirt_type == 'uml':
302
            uri = FLAGS.libvirt_uri or 'uml:///system'
303
        elif FLAGS.libvirt_type == 'xen':
304
            uri = FLAGS.libvirt_uri or 'xen:///'
305
        elif FLAGS.libvirt_type == 'lxc':
306
            uri = FLAGS.libvirt_uri or 'lxc:///'
307
        else:
308
            uri = FLAGS.libvirt_uri or 'qemu:///system'
309
        return uri
310
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
311
    @staticmethod
312
    def _connect(uri, read_only):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
313
        auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT],
314
                'root',
315
                None]
316
317
        if read_only:
318
            return libvirt.openReadOnly(uri)
319
        else:
320
            return libvirt.openAuth(uri, auth, 0)
321
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
322
    def get_num_instances(self):
323
        """Efficient override of base instance_exists method."""
324
        return self._conn.numOfDomains()
65 by Chuck Short, Chuck Short, Adam Gandleman
[Chuck Short]
325
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
326
    def instance_exists(self, instance_id):
327
        """Efficient override of base instance_exists method."""
328
        try:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
329
            self._conn.lookupByName(instance_id)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
330
            return True
331
        except libvirt.libvirtError:
332
            return False
65 by Chuck Short, Chuck Short, Adam Gandleman
[Chuck Short]
333
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
334
    def list_instances(self):
335
        return [self._conn.lookupByID(x).name()
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
336
                for x in self._conn.listDomainsID()
337
                if x != 0]  # We skip domains with ID 0 (hypervisors).
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
338
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
339
    @staticmethod
340
    def _map_to_instance_info(domain):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
341
        """Gets info from a virsh domain object into an InstanceInfo"""
342
343
        # domain.info() returns a list of:
344
        #    state:       one of the state values (virDomainState)
345
        #    maxMemory:   the maximum memory used by the domain
346
        #    memory:      the current amount of memory used by the domain
347
        #    nbVirtCPU:   the number of virtual CPU
348
        #    puTime:      the time used by the domain in nanoseconds
349
350
        (state, _max_mem, _mem, _num_cpu, _cpu_time) = domain.info()
351
        name = domain.name()
352
353
        return driver.InstanceInfo(name, state)
354
355
    def list_instances_detail(self):
356
        infos = []
357
        for domain_id in self._conn.listDomainsID():
358
            domain = self._conn.lookupByID(domain_id)
359
            info = self._map_to_instance_info(domain)
360
            infos.append(info)
361
        return infos
362
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
363
    def plug_vifs(self, instance, network_info):
1.1.39 by Chuck Short
Import upstream version 2012.1~e2
364
        """Plug VIFs into networks."""
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
365
        for (network, mapping) in network_info:
366
            self.vif_driver.plug(instance, network, mapping)
367
1.1.39 by Chuck Short
Import upstream version 2012.1~e2
368
    def unplug_vifs(self, instance, network_info):
369
        """Unplug VIFs from networks."""
370
        for (network, mapping) in network_info:
371
            self.vif_driver.unplug(instance, network, mapping)
372
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
373
    def _destroy(self, instance, network_info, block_device_info=None,
374
                 cleanup=True):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
375
        try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
376
            virt_dom = self._lookup_by_name(instance['name'])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
377
        except exception.NotFound:
378
            virt_dom = None
379
380
        # If the instance is already terminated, we're still happy
381
        # Otherwise, destroy it
382
        if virt_dom is not None:
383
            try:
384
                virt_dom.destroy()
385
            except libvirt.libvirtError as e:
386
                is_okay = False
387
                errcode = e.get_error_code()
388
                if errcode == libvirt.VIR_ERR_OPERATION_INVALID:
389
                    # If the instance if already shut off, we get this:
390
                    # Code=55 Error=Requested operation is not valid:
391
                    # domain is not running
392
                    (state, _max_mem, _mem, _cpus, _t) = virt_dom.info()
393
                    if state == power_state.SHUTOFF:
394
                        is_okay = True
395
396
                if not is_okay:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
397
                    LOG.warning(_("Error from libvirt during destroy. "
398
                                  "Code=%(errcode)s Error=%(e)s") %
399
                                locals(), instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
400
                    raise
401
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
402
            try:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
403
                # NOTE(derekh): we can switch to undefineFlags and
404
                # VIR_DOMAIN_UNDEFINE_MANAGED_SAVE once we require 0.9.4
405
                if virt_dom.hasManagedSaveImage(0):
406
                    virt_dom.managedSaveRemove(0)
407
            except libvirt.libvirtError as e:
408
                errcode = e.get_error_code()
409
                LOG.warning(_("Error from libvirt during saved instance "
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
410
                              "removal. Code=%(errcode)s Error=%(e)s") %
411
                            locals(), instance=instance)
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
412
413
            try:
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
414
                # NOTE(justinsb): We remove the domain definition. We probably
415
                # would do better to keep it if cleanup=False (e.g. volumes?)
416
                # (e.g. #2 - not losing machines on failure)
417
                virt_dom.undefine()
418
            except libvirt.libvirtError as e:
419
                errcode = e.get_error_code()
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
420
                LOG.warning(_("Error from libvirt during undefine. "
421
                              "Code=%(errcode)s Error=%(e)s") %
422
                            locals(), instance=instance)
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
423
                raise
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
424
1.1.39 by Chuck Short
Import upstream version 2012.1~e2
425
        self.unplug_vifs(instance, network_info)
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
426
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
427
        def _wait_for_destroy():
428
            """Called at an interval until the VM is gone."""
429
            try:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
430
                self.get_info(instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
431
            except exception.NotFound:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
432
                LOG.info(_("Instance destroyed successfully."),
433
                         instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
434
                raise utils.LoopingCallDone
435
436
        timer = utils.LoopingCall(_wait_for_destroy)
437
        timer.start(interval=0.5, now=True)
438
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
439
        try:
440
            self.firewall_driver.unfilter_instance(instance,
441
                                                   network_info=network_info)
442
        except libvirt.libvirtError as e:
443
            errcode = e.get_error_code()
444
            LOG.warning(_("Error from libvirt during unfilter. "
445
                          "Code=%(errcode)s Error=%(e)s") %
446
                        locals(), instance=instance)
447
            reason = "Error unfiltering instance."
448
            raise exception.InstanceTerminationFailure(reason=reason)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
449
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
450
        # NOTE(vish): we disconnect from volumes regardless
451
        block_device_mapping = driver.block_device_info_get_mapping(
452
            block_device_info)
453
        for vol in block_device_mapping:
454
            connection_info = vol['connection_info']
455
            mountpoint = vol['mount_device']
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
456
            self.volume_driver_method('disconnect_volume',
457
                                      connection_info,
458
                                      mountpoint)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
459
        if cleanup:
460
            self._cleanup(instance)
461
462
        return True
463
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
464
    def destroy(self, instance, network_info, block_device_info=None):
465
        return self._destroy(instance, network_info, block_device_info,
466
                             cleanup=True)
467
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
468
    def _cleanup(self, instance):
469
        target = os.path.join(FLAGS.instances_path, instance['name'])
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
470
        LOG.info(_('Deleting instance files %(target)s') % locals(),
471
                 instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
472
        if FLAGS.libvirt_type == 'lxc':
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
473
            disk.destroy_container(self.container)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
474
        if os.path.exists(target):
475
            shutil.rmtree(target)
476
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
477
    def get_volume_connector(self, instance):
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
478
        if not self._initiator:
479
            self._initiator = libvirt_utils.get_iscsi_initiator()
480
            if not self._initiator:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
481
                LOG.warn(_('Could not determine iscsi initiator name'),
482
                         instance=instance)
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
483
        return {
484
            'ip': FLAGS.my_ip,
485
            'initiator': self._initiator,
486
        }
487
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
488
    def _cleanup_resize(self, instance):
489
        target = os.path.join(FLAGS.instances_path,
490
                              instance['name'] + "_resize")
491
        if os.path.exists(target):
492
            shutil.rmtree(target)
493
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
494
    def volume_driver_method(self, method_name, connection_info,
495
                             *args, **kwargs):
496
        driver_type = connection_info.get('driver_volume_type')
497
        if not driver_type in self.volume_drivers:
498
            raise exception.VolumeDriverNotFound(driver_type=driver_type)
499
        driver = self.volume_drivers[driver_type]
500
        method = getattr(driver, method_name)
501
        return method(connection_info, *args, **kwargs)
502
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
503
    @exception.wrap_exception()
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
504
    def attach_volume(self, connection_info, instance_name, mountpoint):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
505
        virt_dom = self._lookup_by_name(instance_name)
506
        mount_device = mountpoint.rpartition("/")[2]
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
507
        xml = self.volume_driver_method('connect_volume',
508
                                        connection_info,
509
                                        mount_device)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
510
511
        if FLAGS.libvirt_type == 'lxc':
512
            self._attach_lxc_volume(xml, virt_dom, instance_name)
513
        else:
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
514
            try:
515
                virt_dom.attachDevice(xml)
516
            except Exception, ex:
517
                self.volume_driver_method('disconnect_volume',
518
                                           connection_info,
519
                                           mount_device)
520
521
                if isinstance(ex, libvirt.libvirtError):
522
                    errcode = ex.get_error_code()
523
                    if errcode == libvirt.VIR_ERR_OPERATION_FAILED:
524
                        raise exception.DeviceIsBusy(device=mount_device)
525
                raise
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
526
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
527
    @staticmethod
528
    def _get_disk_xml(xml, device):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
529
        """Returns the xml for the disk mounted at device"""
530
        try:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
531
            doc = ElementTree.fromstring(xml)
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
532
        except Exception:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
533
            return None
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
534
        ret = doc.findall('./devices/disk')
535
        for node in ret:
536
            for child in node.getchildren():
537
                if child.tag == 'target':
538
                    if child.get('dev') == device:
539
                        return ElementTree.tostring(node)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
540
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
541
    @exception.wrap_exception()
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
542
    def detach_volume(self, connection_info, instance_name, mountpoint):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
543
        mount_device = mountpoint.rpartition("/")[2]
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
544
        try:
545
            # NOTE(vish): This is called to cleanup volumes after live
546
            #             migration, so we should still logout even if
547
            #             the instance doesn't exist here anymore.
548
            virt_dom = self._lookup_by_name(instance_name)
549
            xml = self._get_disk_xml(virt_dom.XMLDesc(0), mount_device)
550
            if not xml:
551
                raise exception.DiskNotFound(location=mount_device)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
552
            if FLAGS.libvirt_type == 'lxc':
553
                self._detach_lxc_volume(xml, virt_dom, instance_name)
554
            else:
555
                virt_dom.detachDevice(xml)
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
556
        finally:
557
            self.volume_driver_method('disconnect_volume',
558
                                      connection_info,
559
                                      mount_device)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
560
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
561
    @exception.wrap_exception()
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
562
    def _attach_lxc_volume(self, xml, virt_dom, instance_name):
563
        LOG.info(_('attaching LXC block device'))
564
565
        lxc_container_root = self.get_lxc_container_root(virt_dom)
566
        lxc_host_volume = self.get_lxc_host_device(xml)
567
        lxc_container_device = self.get_lxc_container_target(xml)
568
        lxc_container_target = "%s/%s" % (lxc_container_root,
569
                                          lxc_container_device)
570
571
        if lxc_container_target:
572
            disk.bind(lxc_host_volume, lxc_container_target, instance_name)
573
574
    @exception.wrap_exception()
575
    def _detach_lxc_volume(self, xml, virt_dom, instance_name):
576
        LOG.info(_('detaching LXC block device'))
577
578
        lxc_container_root = self.get_lxc_container_root(virt_dom)
579
        lxc_container_device = self.get_lxc_container_target(xml)
580
        lxc_container_target = "%s/%s" % (lxc_container_root,
581
                                          lxc_container_device)
582
583
        if lxc_container_target:
584
            disk.unbind(lxc_container_target)
585
586
    @staticmethod
587
    def get_lxc_container_root(virt_dom):
588
        xml = virt_dom.XMLDesc(0)
589
        doc = ElementTree.fromstring(xml)
590
        filesystem_block = doc.findall('./devices/filesystem')
591
        for cnt, filesystem_nodes in enumerate(filesystem_block):
592
            return filesystem_nodes[cnt].get('dir')
593
594
    @staticmethod
595
    def get_lxc_host_device(xml):
596
        dom = minidom.parseString(xml)
597
598
        for device in dom.getElementsByTagName('source'):
599
            return device.getAttribute('dev')
600
601
    @staticmethod
602
    def get_lxc_container_target(xml):
603
        dom = minidom.parseString(xml)
604
605
        for device in dom.getElementsByTagName('target'):
606
            filesystem = device.getAttribute('dev')
607
            return 'dev/%s' % filesystem
608
609
    @exception.wrap_exception()
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
610
    def snapshot(self, context, instance, image_href):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
611
        """Create snapshot from a running VM instance.
612
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
613
        This command only works with qemu 0.14+
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
614
        """
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
615
        try:
616
            virt_dom = self._lookup_by_name(instance['name'])
617
        except exception.InstanceNotFound:
618
            raise exception.InstanceNotRunning()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
619
1.1.19 by Chuck Short
Import upstream version 2011.3~d2~20110617.1191
620
        (image_service, image_id) = nova.image.get_image_service(
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
621
            context, instance['image_ref'])
1.1.52 by Chuck Short
Import upstream version 2012.1~rc3
622
        try:
623
            base = image_service.show(context, image_id)
624
        except exception.ImageNotFound:
625
            base = {}
626
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
627
        _image_service = nova.image.get_image_service(context, image_href)
628
        snapshot_image_service, snapshot_image_id = _image_service
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
629
        snapshot = snapshot_image_service.show(context, snapshot_image_id)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
630
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
631
        metadata = {'is_public': False,
1.1.19 by Chuck Short
Import upstream version 2011.3~d2~20110617.1191
632
                    'status': 'active',
633
                    'name': snapshot['name'],
634
                    'properties': {
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
635
                                   'kernel_id': instance['kernel_id'],
636
                                   'image_location': 'snapshot',
637
                                   'image_state': 'available',
638
                                   'owner_id': instance['project_id'],
639
                                   'ramdisk_id': instance['ramdisk_id'],
640
                                   }
641
                    }
1.1.52 by Chuck Short
Import upstream version 2012.1~rc3
642
        if 'architecture' in base.get('properties', {}):
1.1.19 by Chuck Short
Import upstream version 2011.3~d2~20110617.1191
643
            arch = base['properties']['architecture']
644
            metadata['properties']['architecture'] = arch
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
645
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
646
        source_format = base.get('disk_format') or 'raw'
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
647
        if source_format == 'ami':
648
            # NOTE(vish): assume amis are raw
649
            source_format = 'raw'
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
650
        image_format = FLAGS.snapshot_image_format or source_format
651
        if FLAGS.use_cow_images:
652
            source_format = 'qcow2'
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
653
        # NOTE(vish): glance forces ami disk format to be ami
654
        if base.get('disk_format') == 'ami':
655
            metadata['disk_format'] = 'ami'
656
        else:
657
            metadata['disk_format'] = image_format
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
658
659
        if 'container_format' in base:
660
            metadata['container_format'] = base['container_format']
661
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
662
        # Find the disk
663
        xml_desc = virt_dom.XMLDesc(0)
664
        domain = ElementTree.fromstring(xml_desc)
665
        source = domain.find('devices/disk/source')
666
        disk_path = source.get('file')
667
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
668
        snapshot_name = uuid.uuid4().hex
669
670
        (state, _max_mem, _mem, _cpus, _t) = virt_dom.info()
671
        if state == power_state.RUNNING:
672
            virt_dom.managedSave(0)
673
        # Make the snapshot
674
        libvirt_utils.create_snapshot(disk_path, snapshot_name)
675
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
676
        # Export the snapshot to a raw image
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
677
        with utils.tempdir() as tmpdir:
678
            try:
679
                out_path = os.path.join(tmpdir, snapshot_name)
680
                libvirt_utils.extract_snapshot(disk_path, source_format,
681
                                               snapshot_name, out_path,
682
                                               image_format)
683
            finally:
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
684
                libvirt_utils.delete_snapshot(disk_path, snapshot_name)
685
                if state == power_state.RUNNING:
686
                    virt_dom.create()
687
688
            # Upload that image to the image service
689
            with libvirt_utils.file_open(out_path) as image_file:
690
                image_service.update(context,
691
                                     image_href,
692
                                     metadata,
693
                                     image_file)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
694
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
695
    @exception.wrap_exception()
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
696
    def reboot(self, instance, network_info, reboot_type='SOFT'):
697
        """Reboot a virtual machine, given an instance reference."""
698
        if reboot_type == 'SOFT':
699
            # NOTE(vish): This will attempt to do a graceful shutdown/restart.
700
            if self._soft_reboot(instance):
701
                LOG.info(_("Instance soft rebooted successfully."),
702
                         instance=instance)
703
                return
704
            else:
705
                LOG.info(_("Failed to soft reboot instance."),
706
                         instance=instance)
707
        return self._hard_reboot(instance, network_info)
708
709
    def _soft_reboot(self, instance):
710
        """Attempt to shutdown and restart the instance gracefully.
711
712
        We use shutdown and create here so we can return if the guest
713
        responded and actually rebooted. Note that this method only
714
        succeeds if the guest responds to acpi. Therefore we return
715
        success or failure so we can fall back to a hard reboot if
716
        necessary.
717
718
        :returns: True if the reboot succeeded
719
        """
720
        dom = self._lookup_by_name(instance.name)
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
721
        (state, _max_mem, _mem, _cpus, _t) = dom.info()
722
        # NOTE(vish): This check allows us to reboot an instance that
723
        #             is already shutdown.
724
        if state == power_state.RUNNING:
725
            dom.shutdown()
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
726
        # NOTE(vish): This actually could take slighty longer than the
727
        #             FLAG defines depending on how long the get_info
728
        #             call takes to return.
729
        for x in xrange(FLAGS.libvirt_wait_soft_reboot_seconds):
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
730
            (state, _max_mem, _mem, _cpus, _t) = dom.info()
731
            if state in [power_state.SHUTDOWN,
732
                         power_state.SHUTOFF,
733
                         power_state.CRASHED]:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
734
                LOG.info(_("Instance shutdown successfully."),
735
                         instance=instance)
736
                dom.create()
737
                timer = utils.LoopingCall(self._wait_for_running, instance)
738
                return timer.start(interval=0.5, now=True)
739
            greenthread.sleep(1)
740
        return False
741
742
    def _hard_reboot(self, instance, network_info, xml=None):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
743
        """Reboot a virtual machine, given an instance reference.
744
745
        This method actually destroys and re-creates the domain to ensure the
746
        reboot happens, as the guest OS cannot ignore this action.
747
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
748
        If xml is set, it uses the passed in xml in place of the xml from the
749
        existing domain.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
750
        """
751
        virt_dom = self._conn.lookupByName(instance['name'])
752
        # NOTE(itoumsn): Use XML delived from the running instance
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
753
        # instead of using to_xml(instance, network_info). This is almost
754
        # the ultimate stupid workaround.
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
755
        if not xml:
756
            xml = virt_dom.XMLDesc(0)
757
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
758
        self._destroy(instance, network_info, cleanup=False)
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
759
        self.plug_vifs(instance, network_info)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
760
        self.firewall_driver.setup_basic_filtering(instance, network_info)
761
        self.firewall_driver.prepare_instance_filter(instance, network_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
762
        self._create_new_domain(xml)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
763
        self.firewall_driver.apply_instance_filter(instance, network_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
764
765
        def _wait_for_reboot():
766
            """Called at an interval until the VM is running again."""
767
            try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
768
                state = self.get_info(instance)['state']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
769
            except exception.NotFound:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
770
                LOG.error(_("During reboot, instance disappeared."),
771
                          instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
772
                raise utils.LoopingCallDone
773
774
            if state == power_state.RUNNING:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
775
                LOG.info(_("Instance rebooted successfully."),
776
                         instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
777
                raise utils.LoopingCallDone
778
779
        timer = utils.LoopingCall(_wait_for_reboot)
780
        return timer.start(interval=0.5, now=True)
781
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
782
    @exception.wrap_exception()
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
783
    def pause(self, instance):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
784
        """Pause VM instance"""
785
        dom = self._lookup_by_name(instance.name)
786
        dom.suspend()
787
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
788
    @exception.wrap_exception()
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
789
    def unpause(self, instance):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
790
        """Unpause paused VM instance"""
791
        dom = self._lookup_by_name(instance.name)
792
        dom.resume()
793
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
794
    @exception.wrap_exception()
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
795
    def suspend(self, instance):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
796
        """Suspend the specified instance"""
797
        dom = self._lookup_by_name(instance.name)
798
        dom.managedSave(0)
799
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
800
    @exception.wrap_exception()
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
801
    def resume(self, instance):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
802
        """resume the specified instance"""
803
        dom = self._lookup_by_name(instance.name)
804
        dom.create()
805
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
806
    @exception.wrap_exception()
1.1.38 by Chuck Short
Import upstream version 2012.1~e2~20111208.11721
807
    def rescue(self, context, instance, network_info, image_meta):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
808
        """Loads a VM using rescue images.
809
810
        A rescue is normally performed when something goes wrong with the
811
        primary images and data needs to be corrected/recovered. Rescuing
812
        should not edit or over-ride the original image, only allow for
813
        data recovery.
814
815
        """
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
816
817
        virt_dom = self._conn.lookupByName(instance['name'])
818
        unrescue_xml = virt_dom.XMLDesc(0)
819
        unrescue_xml_path = os.path.join(FLAGS.instances_path,
820
                                         instance['name'],
821
                                         'unrescue.xml')
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
822
        libvirt_utils.write_to_file(unrescue_xml_path, unrescue_xml)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
823
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
824
        xml = self.to_xml(instance, network_info, image_meta, rescue=True)
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
825
        rescue_images = {
826
            'image_id': FLAGS.rescue_image_id or instance['image_ref'],
827
            'kernel_id': FLAGS.rescue_kernel_id or instance['kernel_id'],
828
            'ramdisk_id': FLAGS.rescue_ramdisk_id or instance['ramdisk_id'],
829
        }
830
        self._create_image(context, instance, xml, '.rescue', rescue_images,
831
                           network_info=network_info)
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
832
        self._hard_reboot(instance, network_info, xml=xml)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
833
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
834
    @exception.wrap_exception()
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
835
    def unrescue(self, instance, network_info):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
836
        """Reboot the VM which is being rescued back into primary images.
837
838
        Because reboot destroys and re-creates instances, unresue should
839
        simply call reboot.
840
841
        """
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
842
        unrescue_xml_path = os.path.join(FLAGS.instances_path,
843
                                         instance['name'],
844
                                         'unrescue.xml')
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
845
        xml = libvirt_utils.load_file(unrescue_xml_path)
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
846
        libvirt_utils.file_delete(unrescue_xml_path)
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
847
        self._hard_reboot(instance, network_info, xml=xml)
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
848
        rescue_files = os.path.join(FLAGS.instances_path, instance['name'],
849
                                    "*.rescue")
850
        for rescue_file in glob.iglob(rescue_files):
851
            libvirt_utils.file_delete(rescue_file)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
852
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
853
    @exception.wrap_exception()
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
854
    def poll_rebooting_instances(self, timeout):
855
        pass
856
857
    @exception.wrap_exception()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
858
    def poll_rescued_instances(self, timeout):
859
        pass
860
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
861
    @exception.wrap_exception()
862
    def poll_unconfirmed_resizes(self, resize_confirm_window):
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
863
        """Poll for unconfirmed resizes.
864
865
        Look for any unconfirmed resizes that are older than
866
        `resize_confirm_window` and automatically confirm them.
867
        """
868
        ctxt = nova_context.get_admin_context()
869
        migrations = db.migration_get_all_unconfirmed(ctxt,
870
            resize_confirm_window)
871
872
        migrations_info = dict(migration_count=len(migrations),
873
                confirm_window=FLAGS.resize_confirm_window)
874
875
        if migrations_info["migration_count"] > 0:
876
            LOG.info(_("Found %(migration_count)d unconfirmed migrations "
877
                    "older than %(confirm_window)d seconds") % migrations_info)
878
879
        for migration in migrations:
880
            LOG.info(_("Automatically confirming migration %d"), migration.id)
881
            self.compute_api.confirm_resize(ctxt, migration.instance_uuid)
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
882
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
883
    def _enable_hairpin(self, instance):
884
        interfaces = self.get_interfaces(instance['name'])
885
        for interface in interfaces:
886
            utils.execute('tee',
887
                          '/sys/class/net/%s/brport/hairpin_mode' % interface,
888
                          process_input='1',
889
                          run_as_root=True,
890
                          check_exit_code=[0, 1])
891
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
892
    # NOTE(ilyaalekseyev): Implementation like in multinics
893
    # for xenapi(tr3buchet)
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
894
    @exception.wrap_exception()
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
895
    def spawn(self, context, instance, image_meta, network_info,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
896
              block_device_info=None):
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
897
        xml = self.to_xml(instance, network_info, image_meta, False,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
898
                          block_device_info=block_device_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
899
        self.firewall_driver.setup_basic_filtering(instance, network_info)
900
        self.firewall_driver.prepare_instance_filter(instance, network_info)
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
901
        self._create_image(context, instance, xml, network_info=network_info,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
902
                           block_device_info=block_device_info)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
903
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
904
        self._create_new_domain(xml)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
905
        LOG.debug(_("Instance is running"), instance=instance)
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
906
        self._enable_hairpin(instance)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
907
        self.firewall_driver.apply_instance_filter(instance, network_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
908
909
        def _wait_for_boot():
910
            """Called at an interval until the VM is running."""
911
            try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
912
                state = self.get_info(instance)['state']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
913
            except exception.NotFound:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
914
                LOG.error(_("During reboot, instance disappeared."),
915
                          instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
916
                raise utils.LoopingCallDone
917
918
            if state == power_state.RUNNING:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
919
                LOG.info(_("Instance spawned successfully."),
920
                         instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
921
                raise utils.LoopingCallDone
922
923
        timer = utils.LoopingCall(_wait_for_boot)
924
        return timer.start(interval=0.5, now=True)
925
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
926
    def _flush_libvirt_console(self, pty):
927
        out, err = utils.execute('dd',
928
                                 'if=%s' % pty,
929
                                 'iflag=nonblock',
930
                                 run_as_root=True,
931
                                 check_exit_code=False)
932
        return out
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
933
934
    def _append_to_file(self, data, fpath):
935
        LOG.info(_('data: %(data)r, fpath: %(fpath)r') % locals())
936
        fp = open(fpath, 'a+')
937
        fp.write(data)
938
        return fpath
939
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
940
    def _inject_files(self, instance, files, partition):
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
941
        disk_path = os.path.join(FLAGS.instances_path,
942
                                 instance['name'], 'disk')
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
943
        disk.inject_files(disk_path, files, partition=partition,
944
                          use_cow=FLAGS.use_cow_images)
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
945
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
946
    @exception.wrap_exception()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
947
    def get_console_output(self, instance):
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
948
        virt_dom = self._lookup_by_name(instance['name'])
949
        xml = virt_dom.XMLDesc(0)
950
        tree = ElementTree.fromstring(xml)
951
952
        console_types = {}
953
954
        # NOTE(comstud): We want to try 'file' types first, then try 'pty'
955
        # types.  We can't use Python 2.7 syntax of:
956
        # tree.find("./devices/console[@type='file']/source")
957
        # because we need to support 2.6.
958
        console_nodes = tree.findall('./devices/console')
959
        for console_node in console_nodes:
960
            console_type = console_node.get('type')
961
            console_types.setdefault(console_type, [])
962
            console_types[console_type].append(console_node)
963
964
        # If the guest has a console logging to a file prefer to use that
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
965
        if console_types.get('file'):
966
            for file_console in console_types.get('file'):
967
                source_node = file_console.find('./source')
968
                if source_node is None:
969
                    continue
970
                path = source_node.get("path")
971
                if not path:
972
                    continue
973
                libvirt_utils.chown(path, os.getuid())
974
                return libvirt_utils.load_file(path)
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
975
976
        # Try 'pty' types
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
977
        if console_types.get('pty'):
978
            for pty_console in console_types.get('pty'):
979
                source_node = pty_console.find('./source')
980
                if source_node is None:
981
                    continue
982
                pty = source_node.get("path")
983
                if not pty:
984
                    continue
985
                break
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
986
        else:
987
            raise exception.Error(_("Guest does not have a console available"))
988
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
989
        self._chown_console_log_for_instance(instance['name'])
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
990
        data = self._flush_libvirt_console(pty)
991
        fpath = self._append_to_file(data, console_log)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
992
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
993
        return libvirt_utils.load_file(fpath)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
994
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
995
    @staticmethod
996
    def get_host_ip_addr():
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
997
        return FLAGS.my_ip
998
1.1.23 by Chuck Short
Import upstream version 2011.3~d3~20110715.1279
999
    @exception.wrap_exception()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1000
    def get_vnc_console(self, instance):
1001
        def get_vnc_port_for_instance(instance_name):
1002
            virt_dom = self._lookup_by_name(instance_name)
1003
            xml = virt_dom.XMLDesc(0)
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
1004
            # TODO(sleepsonthefloor): use etree instead of minidom
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1005
            dom = minidom.parseString(xml)
1006
1007
            for graphic in dom.getElementsByTagName('graphics'):
1008
                if graphic.getAttribute('type') == 'vnc':
1009
                    return graphic.getAttribute('port')
1010
1011
        port = get_vnc_port_for_instance(instance['name'])
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
1012
        host = FLAGS.vncserver_proxyclient_address
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1013
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
1014
        return {'host': host, 'port': port, 'internal_access_path': None}
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1015
1016
    @staticmethod
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
1017
    def _supports_direct_io(dirpath):
1018
        testfile = os.path.join(dirpath, ".directio.test")
1019
        hasDirectIO = True
1020
        try:
1021
            f = os.open(testfile, os.O_CREAT | os.O_WRONLY | os.O_DIRECT)
1022
            os.close(f)
1023
            LOG.debug(_("Path '%(path)s' supports direct I/O") %
1024
                      {'path': dirpath})
1025
        except OSError, e:
1026
            if e.errno == errno.EINVAL:
1027
                LOG.debug(_("Path '%(path)s' does not support direct I/O: "
1028
                            "'%(ex)s'") % {'path': dirpath, 'ex': str(e)})
1029
                hasDirectIO = False
1030
            else:
1031
                LOG.error(_("Error on '%(path)s' while checking direct I/O: "
1032
                            "'%(ex)s'") % {'path': dirpath, 'ex': str(e)})
1033
                raise e
1034
        except Exception, e:
1035
            LOG.error(_("Error on '%(path)s' while checking direct I/O: "
1036
                        "'%(ex)s'") % {'path': dirpath, 'ex': str(e)})
1037
            raise e
1038
        finally:
1039
            try:
1040
                os.unlink(testfile)
1041
            except:
1042
                pass
1043
1044
        return hasDirectIO
1045
1046
    @staticmethod
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1047
    def _cache_image(fn, target, fname, cow=False, size=None, *args, **kwargs):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1048
        """Wrapper for a method that creates an image that caches the image.
1049
1050
        This wrapper will save the image into a common store and create a
1051
        copy for use by the hypervisor.
1052
1053
        The underlying method should specify a kwarg of target representing
1054
        where the image will be saved.
1055
1056
        fname is used as the filename of the base image.  The filename needs
1057
        to be unique to a given image.
1058
1059
        If cow is True, it will make a CoW image instead of a copy.
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1060
1061
        If size is specified, we attempt to resize up to that size.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1062
        """
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1063
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1064
        # NOTE(mikal): Checksums aren't created here, even if the image cache
1065
        # manager is enabled, as that would slow down VM startup. If both
1066
        # cache management and checksumming are enabled, then the checksum
1067
        # will be created on the first pass of the image cache manager.
1068
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1069
        generating = 'image_id' not in kwargs
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1070
        if not os.path.exists(target):
1071
            base_dir = os.path.join(FLAGS.instances_path, '_base')
1072
            if not os.path.exists(base_dir):
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1073
                libvirt_utils.ensure_tree(base_dir)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1074
            base = os.path.join(base_dir, fname)
1075
1076
            @utils.synchronized(fname)
1077
            def call_if_not_exists(base, fn, *args, **kwargs):
1078
                if not os.path.exists(base):
1079
                    fn(target=base, *args, **kwargs)
1080
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1081
            if cow or not generating:
1082
                call_if_not_exists(base, fn, *args, **kwargs)
1083
            elif generating:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1084
                # For raw it's quicker to just generate outside the cache
1085
                call_if_not_exists(target, fn, *args, **kwargs)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1086
1.1.49 by Adam Gandelman
Import upstream version 2012.1~rc1~20120316.13416
1087
            @utils.synchronized(base)
1088
            def copy_and_extend(cow, generating, base, target, size):
1089
                if cow:
1090
                    cow_base = base
1091
                    if size:
1092
                        size_gb = size / (1024 * 1024 * 1024)
1093
                        cow_base += "_%d" % size_gb
1094
                        if not os.path.exists(cow_base):
1095
                            libvirt_utils.copy_image(base, cow_base)
1096
                            disk.extend(cow_base, size)
1097
                    libvirt_utils.create_cow_image(cow_base, target)
1098
                elif not generating:
1099
                    libvirt_utils.copy_image(base, target)
1100
                    # Resize after the copy, as it's usually much faster
1101
                    # to make sparse updates, rather than potentially
1102
                    # naively copying the whole image file.
1103
                    if size:
1104
                        disk.extend(target, size)
1105
1106
            copy_and_extend(cow, generating, base, target, size)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1107
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1108
    @staticmethod
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
1109
    def _create_local(target, local_size, unit='G',
1110
                      fs_format=None, label=None):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1111
        """Create a blank image of specified size"""
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1112
1113
        if not fs_format:
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1114
            fs_format = FLAGS.default_ephemeral_format
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1115
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1116
        libvirt_utils.create_image('raw', target,
1117
                                   '%d%c' % (local_size, unit))
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1118
        if fs_format:
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
1119
            libvirt_utils.mkfs(fs_format, target, label)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1120
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1121
    def _create_ephemeral(self, target, ephemeral_size, fs_label, os_type):
1122
        self._create_local(target, ephemeral_size)
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1123
        disk.mkfs(os_type, fs_label, target)
1124
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1125
    @staticmethod
1126
    def _create_swap(target, swap_mb):
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1127
        """Create a swap file of specified size"""
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1128
        libvirt_utils.create_image('raw', target, '%dM' % swap_mb)
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1129
        libvirt_utils.mkfs('swap', target)
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1130
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
1131
    @staticmethod
1132
    def _chown_console_log_for_instance(instance_name):
1133
        console_log = os.path.join(FLAGS.instances_path, instance_name,
1134
                                   'console.log')
1135
        if os.path.exists(console_log):
1136
            libvirt_utils.chown(console_log, os.getuid())
1137
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1138
    def _create_image(self, context, instance, libvirt_xml, suffix='',
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1139
                      disk_images=None, network_info=None,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1140
                      block_device_info=None):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1141
        if not suffix:
1142
            suffix = ''
1143
1144
        # syntactic nicety
1145
        def basepath(fname='', suffix=suffix):
1146
            return os.path.join(FLAGS.instances_path,
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1147
                                instance['name'],
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1148
                                fname + suffix)
1149
1150
        # ensure directories exist and are writable
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1151
        libvirt_utils.ensure_tree(basepath(suffix=''))
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1152
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1153
        LOG.info(_('Creating image'), instance=instance)
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1154
        libvirt_utils.write_to_file(basepath('libvirt.xml'), libvirt_xml)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1155
1156
        if FLAGS.libvirt_type == 'lxc':
1157
            container_dir = '%s/rootfs' % basepath(suffix='')
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1158
            libvirt_utils.ensure_tree(container_dir)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1159
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
1160
        # NOTE(dprince): for rescue console.log may already exist... chown it.
1161
        self._chown_console_log_for_instance(instance['name'])
67 by Chuck Short, Monty Taylor, Chuck Short, Joseph Heck
[ Monty Taylor ]
1162
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1163
        # NOTE(vish): No need add the suffix to console.log
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1164
        libvirt_utils.write_to_file(basepath('console.log', ''), '', 007)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1165
1166
        if not disk_images:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1167
            disk_images = {'image_id': instance['image_ref'],
1168
                           'kernel_id': instance['kernel_id'],
1169
                           'ramdisk_id': instance['ramdisk_id']}
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1170
1171
        if disk_images['kernel_id']:
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
1172
            fname = disk_images['kernel_id']
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1173
            self._cache_image(fn=libvirt_utils.fetch_image,
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1174
                              context=context,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1175
                              target=basepath('kernel'),
1176
                              fname=fname,
1177
                              image_id=disk_images['kernel_id'],
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1178
                              user_id=instance['user_id'],
1179
                              project_id=instance['project_id'])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1180
            if disk_images['ramdisk_id']:
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
1181
                fname = disk_images['ramdisk_id']
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1182
                self._cache_image(fn=libvirt_utils.fetch_image,
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1183
                                  context=context,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1184
                                  target=basepath('ramdisk'),
1185
                                  fname=fname,
1186
                                  image_id=disk_images['ramdisk_id'],
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1187
                                  user_id=instance['user_id'],
1188
                                  project_id=instance['project_id'])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1189
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1190
        root_fname = hashlib.sha1(str(disk_images['image_id'])).hexdigest()
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1191
        size = instance['root_gb'] * 1024 * 1024 * 1024
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1192
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1193
        inst_type_id = instance['instance_type_id']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1194
        inst_type = instance_types.get_instance_type(inst_type_id)
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1195
        if size == 0 or suffix == '.rescue':
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1196
            size = None
1197
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1198
        if not self._volume_in_mapping(self.default_root_device,
1199
                                       block_device_info):
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1200
            self._cache_image(fn=libvirt_utils.fetch_image,
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1201
                              context=context,
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1202
                              target=basepath('disk'),
1203
                              fname=root_fname,
1204
                              cow=FLAGS.use_cow_images,
1205
                              image_id=disk_images['image_id'],
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1206
                              user_id=instance['user_id'],
1207
                              project_id=instance['project_id'],
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1208
                              size=size)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1209
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1210
        ephemeral_gb = instance['ephemeral_gb']
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1211
        if ephemeral_gb and not self._volume_in_mapping(
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1212
                self.default_second_device, block_device_info):
1213
            swap_device = self.default_third_device
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1214
            fn = functools.partial(self._create_ephemeral,
1215
                                   fs_label='ephemeral0',
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1216
                                   os_type=instance.os_type)
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1217
            self._cache_image(fn=fn,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1218
                              target=basepath('disk.local'),
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1219
                              fname="ephemeral_%s_%s_%s" %
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1220
                              ("0", ephemeral_gb, instance.os_type),
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1221
                              cow=FLAGS.use_cow_images,
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1222
                              ephemeral_size=ephemeral_gb)
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1223
        else:
1224
            swap_device = self.default_second_device
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1225
1226
        for eph in driver.block_device_info_get_ephemerals(block_device_info):
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1227
            fn = functools.partial(self._create_ephemeral,
1228
                                   fs_label='ephemeral%d' % eph['num'],
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1229
                                   os_type=instance.os_type)
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1230
            self._cache_image(fn=fn,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1231
                              target=basepath(_get_eph_disk(eph)),
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1232
                              fname="ephemeral_%s_%s_%s" %
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1233
                              (eph['num'], eph['size'], instance.os_type),
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1234
                              cow=FLAGS.use_cow_images,
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1235
                              ephemeral_size=eph['size'])
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1236
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1237
        swap_mb = 0
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1238
1239
        swap = driver.block_device_info_get_swap(block_device_info)
1240
        if driver.swap_is_usable(swap):
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1241
            swap_mb = swap['swap_size']
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1242
        elif (inst_type['swap'] > 0 and
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1243
              not self._volume_in_mapping(swap_device, block_device_info)):
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1244
            swap_mb = inst_type['swap']
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1245
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1246
        if swap_mb > 0:
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1247
            self._cache_image(fn=self._create_swap,
1248
                              target=basepath('disk.swap'),
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1249
                              fname="swap_%s" % swap_mb,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1250
                              cow=FLAGS.use_cow_images,
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1251
                              swap_mb=swap_mb)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1252
1253
        # For now, we assume that if we're not using a kernel, we're using a
1254
        # partitioned disk image where the target partition is the first
1255
        # partition
1256
        target_partition = None
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1257
        if not instance['kernel_id']:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1258
            target_partition = "1"
1259
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1260
        config_drive_id = instance.get('config_drive_id')
1261
        config_drive = instance.get('config_drive')
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1262
1263
        if any((FLAGS.libvirt_type == 'lxc', config_drive, config_drive_id)):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1264
            target_partition = None
1265
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1266
        if config_drive_id:
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
1267
            fname = config_drive_id
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1268
            self._cache_image(fn=libvirt_utils.fetch_image,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1269
                              target=basepath('disk.config'),
1270
                              fname=fname,
1271
                              image_id=config_drive_id,
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1272
                              user_id=instance['user_id'],
1273
                              project_id=instance['project_id'],)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1274
        elif config_drive:
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
1275
            label = 'config'
1.1.31 by Chuck Short
Import upstream version 2011.3~rc~20110920.r1192
1276
            self._create_local(basepath('disk.config'), 64, unit='M',
1.1.47 by Chuck Short
Import upstream version 2012.1~e4
1277
                               fs_format='msdos', label=label)  # 64MB
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1278
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1279
        if instance['key_data']:
1280
            key = str(instance['key_data'])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1281
        else:
1282
            key = None
1283
        net = None
1284
1285
        nets = []
1286
        ifc_template = open(FLAGS.injected_network_template).read()
1287
        ifc_num = -1
1288
        have_injected_networks = False
1289
        for (network_ref, mapping) in network_info:
1290
            ifc_num += 1
1291
1292
            if not network_ref['injected']:
1293
                continue
1294
1295
            have_injected_networks = True
1296
            address = mapping['ips'][0]['ip']
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
1297
            netmask = mapping['ips'][0]['netmask']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1298
            address_v6 = None
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1299
            gateway_v6 = None
1300
            netmask_v6 = None
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1301
            if FLAGS.use_ipv6:
1302
                address_v6 = mapping['ip6s'][0]['ip']
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
1303
                netmask_v6 = mapping['ip6s'][0]['netmask']
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1304
                gateway_v6 = mapping['gateway_v6']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1305
            net_info = {'name': 'eth%d' % ifc_num,
1306
                   'address': address,
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
1307
                   'netmask': netmask,
1308
                   'gateway': mapping['gateway'],
1309
                   'broadcast': mapping['broadcast'],
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1310
                   'dns': ' '.join(mapping['dns']),
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1311
                   'address_v6': address_v6,
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1312
                   'gateway_v6': gateway_v6,
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
1313
                   'netmask_v6': netmask_v6}
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1314
            nets.append(net_info)
1315
1316
        if have_injected_networks:
1317
            net = str(Template(ifc_template,
1318
                               searchList=[{'interfaces': nets,
1319
                                            'use_ipv6': FLAGS.use_ipv6}]))
1320
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1321
        metadata = instance.get('metadata')
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1322
1323
        if FLAGS.libvirt_inject_password:
1324
            admin_password = instance.get('admin_pass')
1325
        else:
1326
            admin_password = None
1327
1328
        if any((key, net, metadata, admin_password)):
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1329
            if config_drive:  # Should be True or None by now.
1330
                injection_path = basepath('disk.config')
1331
                img_id = 'config-drive'
1332
            else:
1333
                injection_path = basepath('disk')
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1334
                img_id = instance.image_ref
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1335
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1336
            for injection in ('metadata', 'key', 'net', 'admin_password'):
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1337
                if locals()[injection]:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
1338
                    LOG.info(_('Injecting %(injection)s into image %(img_id)s')
1339
                             % locals(), instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1340
            try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1341
                disk.inject_data(injection_path,
1342
                                 key, net, metadata, admin_password,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1343
                                 partition=target_partition,
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1344
                                 use_cow=FLAGS.use_cow_images)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1345
1346
            except Exception as e:
1347
                # This could be a windows image, or a vmdk format disk
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1348
                LOG.warn(_('Ignoring error injecting data into image '
1349
                           '%(img_id)s (%(e)s)') % locals(),
1350
                         instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1351
1.1.32 by Chuck Short
Import upstream version 2011.3
1352
        if FLAGS.libvirt_type == 'lxc':
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1353
            self.container = disk.setup_container(basepath('disk'),
1354
                                                  container_dir=container_dir,
1355
                                                  use_cow=FLAGS.use_cow_images)
1.1.32 by Chuck Short
Import upstream version 2011.3
1356
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1357
        if FLAGS.libvirt_type == 'uml':
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1358
            libvirt_utils.chown(basepath('disk'), 'root')
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1359
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1360
        files_to_inject = instance.get('injected_files')
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1361
        if files_to_inject:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1362
            self._inject_files(instance, files_to_inject,
1363
                               partition=target_partition)
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1364
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1365
    @staticmethod
1366
    def _volume_in_mapping(mount_device, block_device_info):
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1367
        block_device_list = [block_device.strip_dev(vol['mount_device'])
1368
                             for vol in
1369
                             driver.block_device_info_get_mapping(
1370
                                 block_device_info)]
1371
        swap = driver.block_device_info_get_swap(block_device_info)
1372
        if driver.swap_is_usable(swap):
1373
            block_device_list.append(
1374
                block_device.strip_dev(swap['device_name']))
1375
        block_device_list += [block_device.strip_dev(ephemeral['device_name'])
1376
                              for ephemeral in
1377
                              driver.block_device_info_get_ephemerals(
1378
                                  block_device_info)]
1379
1380
        LOG.debug(_("block_device_list %s"), block_device_list)
1381
        return block_device.strip_dev(mount_device) in block_device_list
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1382
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1383
    def _prepare_xml_info(self, instance, network_info, image_meta, rescue,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1384
                          block_device_info=None):
1385
        block_device_mapping = driver.block_device_info_get_mapping(
1386
            block_device_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1387
1388
        nics = []
1389
        for (network, mapping) in network_info:
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1390
            nics.append(self.vif_driver.plug(instance, network, mapping))
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1391
        # FIXME(vish): stick this in db
1392
        inst_type_id = instance['instance_type_id']
1393
        inst_type = instance_types.get_instance_type(inst_type_id)
1394
1395
        if FLAGS.use_cow_images:
1396
            driver_type = 'qcow2'
1397
        else:
1398
            driver_type = 'raw'
1399
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1400
        if image_meta and image_meta.get('disk_format') == 'iso':
1401
            root_device_type = 'cdrom'
1402
        else:
1403
            root_device_type = 'disk'
1404
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
1405
        volumes = []
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1406
        for vol in block_device_mapping:
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
1407
            connection_info = vol['connection_info']
1408
            mountpoint = vol['mount_device']
1409
            xml = self.volume_driver_method('connect_volume',
1410
                                            connection_info,
1411
                                            mountpoint)
1412
            volumes.append(xml)
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1413
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1414
        ebs_root = self._volume_in_mapping(self.default_root_device,
1415
                                           block_device_info)
1416
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1417
        ephemeral_device = False
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1418
        if not (self._volume_in_mapping(self.default_second_device,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1419
                                        block_device_info) or
1420
                0 in [eph['num'] for eph in
1421
                      driver.block_device_info_get_ephemerals(
1422
                          block_device_info)]):
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1423
            if instance['ephemeral_gb'] > 0:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1424
                ephemeral_device = self.default_second_device
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1425
1426
        ephemerals = []
1427
        for eph in driver.block_device_info_get_ephemerals(block_device_info):
1428
            ephemerals.append({'device_path': _get_eph_disk(eph),
1429
                               'device': block_device.strip_dev(
1430
                                   eph['device_name'])})
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1431
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1432
        xml_info = {'type': FLAGS.libvirt_type,
1433
                    'name': instance['name'],
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1434
                    'uuid': instance['uuid'],
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
1435
                    'cachemode': self.disk_cachemode,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1436
                    'basepath': os.path.join(FLAGS.instances_path,
1437
                                             instance['name']),
1438
                    'memory_kb': inst_type['memory_mb'] * 1024,
1439
                    'vcpus': inst_type['vcpus'],
1440
                    'rescue': rescue,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1441
                    'disk_prefix': self._disk_prefix,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1442
                    'driver_type': driver_type,
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1443
                    'root_device_type': root_device_type,
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1444
                    'vif_type': FLAGS.libvirt_vif_type,
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1445
                    'nics': nics,
1446
                    'ebs_root': ebs_root,
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1447
                    'ephemeral_device': ephemeral_device,
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
1448
                    'volumes': volumes,
1.1.28 by Chuck Short
Import upstream version 2011.3~rc~20110901.1523
1449
                    'use_virtio_for_bridges':
1450
                            FLAGS.libvirt_use_virtio_for_bridges,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1451
                    'ephemerals': ephemerals}
1452
1453
        root_device_name = driver.block_device_info_get_root(block_device_info)
1454
        if root_device_name:
1455
            xml_info['root_device'] = block_device.strip_dev(root_device_name)
1456
            xml_info['root_device_name'] = root_device_name
1457
        else:
1458
            # NOTE(yamahata):
1459
            # for nova.api.ec2.cloud.CloudController.get_metadata()
1460
            xml_info['root_device'] = self.default_root_device
1461
            db.instance_update(
1462
                nova_context.get_admin_context(), instance['id'],
1463
                {'root_device_name': '/dev/' + self.default_root_device})
1464
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1465
        if ephemeral_device:
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1466
            swap_device = self.default_third_device
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1467
            db.instance_update(
1468
                nova_context.get_admin_context(), instance['id'],
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1469
                {'default_ephemeral_device':
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1470
                 '/dev/' + self.default_second_device})
1471
        else:
1472
            swap_device = self.default_second_device
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1473
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1474
        swap = driver.block_device_info_get_swap(block_device_info)
1475
        if driver.swap_is_usable(swap):
1476
            xml_info['swap_device'] = block_device.strip_dev(
1477
                swap['device_name'])
1478
        elif (inst_type['swap'] > 0 and
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1479
              not self._volume_in_mapping(swap_device,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1480
                                          block_device_info)):
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1481
            xml_info['swap_device'] = swap_device
1.1.30 by Chuck Short
Import upstream version 2011.3~rc~20110916.r1173
1482
            db.instance_update(
1483
                nova_context.get_admin_context(), instance['id'],
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
1484
                {'default_swap_device': '/dev/' + swap_device})
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1485
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1486
        if instance.get('config_drive') or instance.get('config_drive_id'):
1487
            xml_info['config_drive'] = xml_info['basepath'] + "/disk.config"
1488
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1489
        if FLAGS.vnc_enabled and FLAGS.libvirt_type not in ('lxc', 'uml'):
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
1490
            xml_info['vncserver_listen'] = FLAGS.vncserver_listen
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
1491
            xml_info['vnc_keymap'] = FLAGS.vnc_keymap
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1492
        if not rescue:
1493
            if instance['kernel_id']:
1494
                xml_info['kernel'] = xml_info['basepath'] + "/kernel"
1495
1496
            if instance['ramdisk_id']:
1497
                xml_info['ramdisk'] = xml_info['basepath'] + "/ramdisk"
1498
1499
            xml_info['disk'] = xml_info['basepath'] + "/disk"
1500
        return xml_info
1501
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1502
    def to_xml(self, instance, network_info, image_meta=None, rescue=False,
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
1503
               block_device_info=None):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1504
        # TODO(termie): cache?
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
1505
        LOG.debug(_('Starting toXML method'), instance=instance)
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1506
        xml_info = self._prepare_xml_info(instance, network_info, image_meta,
1507
                                          rescue, block_device_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1508
        xml = str(Template(self.libvirt_xml, searchList=[xml_info]))
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
1509
        LOG.debug(_('Finished toXML method'), instance=instance)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1510
        return xml
1511
1512
    def _lookup_by_name(self, instance_name):
1513
        """Retrieve libvirt domain object given an instance name.
1514
1515
        All libvirt error handling should be handled in this method and
1516
        relevant nova exceptions should be raised in response.
1517
1518
        """
1519
        try:
1520
            return self._conn.lookupByName(instance_name)
1521
        except libvirt.libvirtError as ex:
1522
            error_code = ex.get_error_code()
1523
            if error_code == libvirt.VIR_ERR_NO_DOMAIN:
1524
                raise exception.InstanceNotFound(instance_id=instance_name)
1525
1526
            msg = _("Error from libvirt while looking up %(instance_name)s: "
1527
                    "[Error Code %(error_code)s] %(ex)s") % locals()
1528
            raise exception.Error(msg)
1529
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1530
    def get_info(self, instance):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1531
        """Retrieve information from libvirt for a specific instance name.
1532
1533
        If a libvirt error is encountered during lookup, we might raise a
1534
        NotFound exception or Error exception depending on how severe the
1535
        libvirt error is.
1536
1537
        """
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1538
        virt_dom = self._lookup_by_name(instance['name'])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1539
        (state, max_mem, mem, num_cpu, cpu_time) = virt_dom.info()
1540
        return {'state': state,
1541
                'max_mem': max_mem,
1542
                'mem': mem,
1543
                'num_cpu': num_cpu,
1544
                'cpu_time': cpu_time}
1545
1546
    def _create_new_domain(self, xml, persistent=True, launch_flags=0):
1547
        # NOTE(justinsb): libvirt has two types of domain:
1548
        # * a transient domain disappears when the guest is shutdown
1549
        # or the host is rebooted.
1550
        # * a permanent domain is not automatically deleted
1551
        # NOTE(justinsb): Even for ephemeral instances, transient seems risky
1552
1553
        if persistent:
1554
            # To create a persistent domain, first define it, then launch it.
1555
            domain = self._conn.defineXML(xml)
1556
1557
            domain.createWithFlags(launch_flags)
1558
        else:
1559
            # createXML call creates a transient domain
1560
            domain = self._conn.createXML(xml, launch_flags)
1561
1562
        return domain
1563
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1564
    def get_all_block_devices(self):
1565
        """
1566
        Return all block devices in use on this node.
1567
        """
1568
        devices = []
1569
        for dom_id in self._conn.listDomainsID():
1570
            domain = self._conn.lookupByID(dom_id)
1571
            try:
1572
                doc = ElementTree.fromstring(domain.XMLDesc(0))
1573
            except Exception:
1574
                continue
1575
            ret = doc.findall('./devices/disk')
1576
            for node in ret:
1577
                if node.get('type') != 'block':
1578
                    continue
1579
                for child in node.getchildren():
1580
                    if child.tag == 'source':
1581
                        devices.append(child.get('dev'))
1582
        return devices
1583
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1584
    def get_disks(self, instance_name):
1585
        """
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1586
        Note that this function takes an instance name.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1587
1588
        Returns a list of all block devices for this domain.
1589
        """
1590
        domain = self._lookup_by_name(instance_name)
1591
        xml = domain.XMLDesc(0)
1592
        doc = None
1593
1594
        try:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1595
            doc = ElementTree.fromstring(xml)
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1596
        except Exception:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1597
            return []
1598
1599
        disks = []
1600
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1601
        ret = doc.findall('./devices/disk')
1602
1603
        for node in ret:
1604
            devdst = None
1605
1606
            for child in node.children:
1607
                if child.name == 'target':
1608
                    devdst = child.prop('dev')
1609
1610
            if devdst is None:
1611
                continue
1612
1613
            disks.append(devdst)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1614
1615
        return disks
1616
1617
    def get_interfaces(self, instance_name):
1618
        """
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1619
        Note that this function takes an instance name.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1620
1621
        Returns a list of all network interfaces for this instance.
1622
        """
1623
        domain = self._lookup_by_name(instance_name)
1624
        xml = domain.XMLDesc(0)
1625
        doc = None
1626
1627
        try:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1628
            doc = ElementTree.fromstring(xml)
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1629
        except Exception:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1630
            return []
1631
1632
        interfaces = []
1633
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1634
        ret = doc.findall('./devices/interface')
1635
1636
        for node in ret:
1637
            devdst = None
1638
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
1639
            for child in list(node):
1640
                if child.tag == 'target':
1641
                    devdst = child.attrib['dev']
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1642
1643
            if devdst is None:
1644
                continue
1645
1646
            interfaces.append(devdst)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1647
1648
        return interfaces
1649
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1650
    @staticmethod
1651
    def get_vcpu_total():
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1652
        """Get vcpu number of physical computer.
1653
1654
        :returns: the number of cpu core.
1655
1656
        """
1657
1658
        # On certain platforms, this will raise a NotImplementedError.
1659
        try:
1660
            return multiprocessing.cpu_count()
1661
        except NotImplementedError:
1662
            LOG.warn(_("Cannot get the number of cpu, because this "
1663
                       "function is not implemented for this platform. "
1664
                       "This error can be safely ignored for now."))
1665
            return 0
1666
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1667
    @staticmethod
1668
    def get_memory_mb_total():
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1669
        """Get the total memory size(MB) of physical computer.
1670
1671
        :returns: the total amount of memory(MB).
1672
1673
        """
1674
1.1.37 by Chuck Short
Import upstream version 2012.1~e2~20111202.11641
1675
        if sys.platform.upper() not in ['LINUX2', 'LINUX3']:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1676
            return 0
1677
1678
        meminfo = open('/proc/meminfo').read().split()
1679
        idx = meminfo.index('MemTotal:')
1680
        # transforming kb to mb.
1681
        return int(meminfo[idx + 1]) / 1024
1682
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1683
    @staticmethod
1684
    def get_local_gb_total():
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1685
        """Get the total hdd size(GB) of physical computer.
1686
1687
        :returns:
1688
            The total amount of HDD(GB).
1689
            Note that this value shows a partition where
1690
            NOVA-INST-DIR/instances mounts.
1691
1692
        """
1693
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1694
        stats = libvirt_utils.get_fs_info(FLAGS.instances_path)
1695
        return stats['total'] / (1024 ** 3)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1696
1697
    def get_vcpu_used(self):
1698
        """ Get vcpu usage number of physical computer.
1699
1700
        :returns: The total number of vcpu that currently used.
1701
1702
        """
1703
1704
        total = 0
1705
        for dom_id in self._conn.listDomainsID():
1706
            dom = self._conn.lookupByID(dom_id)
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1707
            vcpus = dom.vcpus()
1708
            if vcpus is None:
1709
                # dom.vcpus is not implemented for lxc, but returning 0 for
1710
                # a used count is hardly useful for something measuring usage
1711
                total += 1
1712
            else:
1713
                total += len(vcpus[1])
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1714
        return total
1715
1716
    def get_memory_mb_used(self):
1717
        """Get the free memory size(MB) of physical computer.
1718
1719
        :returns: the total usage of memory(MB).
1720
1721
        """
1722
1.1.37 by Chuck Short
Import upstream version 2012.1~e2~20111202.11641
1723
        if sys.platform.upper() not in ['LINUX2', 'LINUX3']:
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1724
            return 0
1725
1726
        m = open('/proc/meminfo').read().split()
1727
        idx1 = m.index('MemFree:')
1728
        idx2 = m.index('Buffers:')
1729
        idx3 = m.index('Cached:')
1730
        avail = (int(m[idx1 + 1]) + int(m[idx2 + 1]) + int(m[idx3 + 1])) / 1024
1731
        return  self.get_memory_mb_total() - avail
1732
1733
    def get_local_gb_used(self):
1734
        """Get the free hdd size(GB) of physical computer.
1735
1736
        :returns:
1737
           The total usage of HDD(GB).
1738
           Note that this value shows a partition where
1739
           NOVA-INST-DIR/instances mounts.
1740
1741
        """
1742
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
1743
        stats = libvirt_utils.get_fs_info(FLAGS.instances_path)
1744
        return stats['used'] / (1024 ** 3)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1745
1746
    def get_hypervisor_type(self):
1747
        """Get hypervisor type.
1748
1749
        :returns: hypervisor type (ex. qemu)
1750
1751
        """
1752
1753
        return self._conn.getType()
1754
1755
    def get_hypervisor_version(self):
1756
        """Get hypervisor version.
1757
1758
        :returns: hypervisor version (ex. 12003)
1759
1760
        """
1761
1762
        # NOTE(justinsb): getVersion moved between libvirt versions
1763
        # Trying to do be compatible with older versions is a lost cause
1764
        # But ... we can at least give the user a nice message
1765
        method = getattr(self._conn, 'getVersion', None)
1766
        if method is None:
1767
            raise exception.Error(_("libvirt version is too old"
1768
                                    " (does not support getVersion)"))
1769
            # NOTE(justinsb): If we wanted to get the version, we could:
1770
            # method = getattr(libvirt, 'getVersion', None)
1771
            # NOTE(justinsb): This would then rely on a proper version check
1772
1773
        return method()
1774
1775
    def get_cpu_info(self):
1776
        """Get cpuinfo information.
1777
1778
        Obtains cpu feature from virConnect.getCapabilities,
1779
        and returns as a json string.
1780
1781
        :return: see above description
1782
1783
        """
1784
1785
        xml = self._conn.getCapabilities()
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1786
        xml = ElementTree.fromstring(xml)
1787
        nodes = xml.findall('.//host/cpu')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1788
        if len(nodes) != 1:
1789
            reason = _("'<cpu>' must be 1, but %d\n") % len(nodes)
1790
            reason += xml.serialize()
1791
            raise exception.InvalidCPUInfo(reason=reason)
1792
1793
        cpu_info = dict()
1794
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1795
        arch_nodes = xml.findall('.//host/cpu/arch')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1796
        if arch_nodes:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1797
            cpu_info['arch'] = arch_nodes[0].text
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1798
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1799
        model_nodes = xml.findall('.//host/cpu/model')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1800
        if model_nodes:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1801
            cpu_info['model'] = model_nodes[0].text
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1802
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1803
        vendor_nodes = xml.findall('.//host/cpu/vendor')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1804
        if vendor_nodes:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1805
            cpu_info['vendor'] = vendor_nodes[0].text
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1806
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1807
        topology_nodes = xml.findall('.//host/cpu/topology')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1808
        topology = dict()
1809
        if topology_nodes:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1810
            topology_node = topology_nodes[0]
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1811
1812
            keys = ['cores', 'sockets', 'threads']
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1813
            tkeys = topology_node.keys()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1814
            if set(tkeys) != set(keys):
1815
                ks = ', '.join(keys)
1816
                reason = _("topology (%(topology)s) must have %(ks)s")
1817
                raise exception.InvalidCPUInfo(reason=reason % locals())
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1818
            for key in keys:
1819
                topology[key] = topology_node.get(key)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1820
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1821
        feature_nodes = xml.findall('.//host/cpu/feature')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1822
        features = list()
1823
        for nodes in feature_nodes:
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
1824
            features.append(nodes.get('name'))
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1825
1826
        cpu_info['topology'] = topology
1827
        cpu_info['features'] = features
1828
        return utils.dumps(cpu_info)
1829
1830
    def block_stats(self, instance_name, disk):
1831
        """
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1832
        Note that this function takes an instance name.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1833
        """
1834
        domain = self._lookup_by_name(instance_name)
1835
        return domain.blockStats(disk)
1836
1837
    def interface_stats(self, instance_name, interface):
1838
        """
1.1.25 by Chuck Short
Import upstream version 2011.3~d4~20110805.1383
1839
        Note that this function takes an instance name.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1840
        """
1841
        domain = self._lookup_by_name(instance_name)
1842
        return domain.interfaceStats(interface)
1843
1844
    def get_console_pool_info(self, console_type):
1845
        #TODO(mdragon): console proxy should be implemented for libvirt,
1846
        #               in case someone wants to use it with kvm or
1847
        #               such. For now return fake data.
1848
        return  {'address': '127.0.0.1',
1849
                 'username': 'fakeuser',
1850
                 'password': 'fakepassword'}
1851
1852
    def refresh_security_group_rules(self, security_group_id):
1853
        self.firewall_driver.refresh_security_group_rules(security_group_id)
1854
1855
    def refresh_security_group_members(self, security_group_id):
1856
        self.firewall_driver.refresh_security_group_members(security_group_id)
1857
1.1.20 by Chuck Short
Import upstream version 2011.3~d2~20110623.1209
1858
    def refresh_provider_fw_rules(self):
1859
        self.firewall_driver.refresh_provider_fw_rules()
1860
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1861
    def update_available_resource(self, ctxt, host):
1862
        """Updates compute manager resource info on ComputeNode table.
1863
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
1864
        This method is called as an periodic tasks and is used only
1865
        in live migration currently.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1866
1867
        :param ctxt: security context
1868
        :param host: hostname that compute manager is currently running
1869
1870
        """
1871
1872
        try:
1873
            service_ref = db.service_get_all_compute_by_host(ctxt, host)[0]
1874
        except exception.NotFound:
1875
            raise exception.ComputeServiceUnavailable(host=host)
1876
1877
        # Updating host information
1878
        dic = {'vcpus': self.get_vcpu_total(),
1879
               'memory_mb': self.get_memory_mb_total(),
1880
               'local_gb': self.get_local_gb_total(),
1881
               'vcpus_used': self.get_vcpu_used(),
1882
               'memory_mb_used': self.get_memory_mb_used(),
1883
               'local_gb_used': self.get_local_gb_used(),
1884
               'hypervisor_type': self.get_hypervisor_type(),
1885
               'hypervisor_version': self.get_hypervisor_version(),
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1886
               'cpu_info': self.get_cpu_info(),
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
1887
               'service_id': service_ref['id'],
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
1888
               'disk_available_least': self.get_disk_available_least()}
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1889
1890
        compute_node_ref = service_ref['compute_node']
1891
        if not compute_node_ref:
1892
            LOG.info(_('Compute_service record created for %s ') % host)
1893
            db.compute_node_create(ctxt, dic)
1894
        else:
1895
            LOG.info(_('Compute_service record updated for %s ') % host)
1896
            db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
1897
1898
    def compare_cpu(self, cpu_info):
1899
        """Checks the host cpu is compatible to a cpu given by xml.
1900
1901
        "xml" must be a part of libvirt.openReadonly().getCapabilities().
1902
        return values follows by virCPUCompareResult.
1903
        if 0 > return value, do live migration.
1904
        'http://libvirt.org/html/libvirt-libvirt.html#virCPUCompareResult'
1905
1906
        :param cpu_info: json string that shows cpu feature(see get_cpu_info())
1907
        :returns:
1908
            None. if given cpu info is not compatible to this server,
1909
            raise exception.
1910
1911
        """
1912
1913
        LOG.info(_('Instance launched has CPU info:\n%s') % cpu_info)
1914
        dic = utils.loads(cpu_info)
1915
        xml = str(Template(self.cpuinfo_xml, searchList=dic))
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
1916
        LOG.info(_('to xml...\n:%s ') % xml)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1917
1918
        u = "http://libvirt.org/html/libvirt-libvirt.html#virCPUCompareResult"
1919
        m = _("CPU doesn't have compatibility.\n\n%(ret)s\n\nRefer to %(u)s")
1920
        # unknown character exists in xml, then libvirt complains
1921
        try:
1922
            ret = self._conn.compareCPU(xml, 0)
1923
        except libvirt.libvirtError, e:
1924
            ret = e.message
1925
            LOG.error(m % locals())
1926
            raise
1927
1928
        if ret <= 0:
1929
            raise exception.InvalidCPUInfo(reason=m % locals())
1930
1931
        return
1932
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1933
    def ensure_filtering_rules_for_instance(self, instance_ref, network_info,
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1934
                                            time=None):
1935
        """Setting up filtering rules and waiting for its completion.
1936
1937
        To migrate an instance, filtering rules to hypervisors
1938
        and firewalls are inevitable on destination host.
1939
        ( Waiting only for filterling rules to hypervisor,
1940
        since filtering rules to firewall rules can be set faster).
1941
1942
        Concretely, the below method must be called.
1943
        - setup_basic_filtering (for nova-basic, etc.)
1944
        - prepare_instance_filter(for nova-instance-instance-xxx, etc.)
1945
1946
        to_xml may have to be called since it defines PROJNET, PROJMASK.
1947
        but libvirt migrates those value through migrateToURI(),
1948
        so , no need to be called.
1949
1950
        Don't use thread for this method since migration should
1951
        not be started when setting-up filtering rules operations
1952
        are not completed.
1953
1954
        :params instance_ref: nova.db.sqlalchemy.models.Instance object
1955
1956
        """
1957
1958
        if not time:
1959
            time = greenthread
1960
1961
        # If any instances never launch at destination host,
1962
        # basic-filtering must be set here.
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1963
        self.firewall_driver.setup_basic_filtering(instance_ref, network_info)
1964
        # setting up nova-instance-instance-xx mainly.
1965
        self.firewall_driver.prepare_instance_filter(instance_ref,
1966
                network_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1967
1968
        # wait for completion
1969
        timeout_count = range(FLAGS.live_migration_retry_count)
1970
        while timeout_count:
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1971
            if self.firewall_driver.instance_filter_exists(instance_ref,
1972
                                                           network_info):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1973
                break
1974
            timeout_count.pop()
1975
            if len(timeout_count) == 0:
1976
                msg = _('Timeout migrating for %s. nwfilter not found.')
1977
                raise exception.Error(msg % instance_ref.name)
1978
            time.sleep(1)
1979
1980
    def live_migration(self, ctxt, instance_ref, dest,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1981
                       post_method, recover_method, block_migration=False):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1982
        """Spawning live_migration operation for distributing high-load.
1983
1984
        :params ctxt: security context
1985
        :params instance_ref:
1986
            nova.db.sqlalchemy.models.Instance object
1987
            instance object that is migrated.
1988
        :params dest: destination host
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1989
        :params block_migration: destination host
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1990
        :params post_method:
1991
            post operation method.
1992
            expected nova.compute.manager.post_live_migration.
1993
        :params recover_method:
1994
            recovery method when any exception occurs.
1995
            expected nova.compute.manager.recover_live_migration.
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
1996
        :params block_migration: if true, do block migration.
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
1997
1998
        """
1999
2000
        greenthread.spawn(self._live_migration, ctxt, instance_ref, dest,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2001
                          post_method, recover_method, block_migration)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2002
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2003
    def _live_migration(self, ctxt, instance_ref, dest, post_method,
2004
                        recover_method, block_migration=False):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2005
        """Do live migration.
2006
2007
        :params ctxt: security context
2008
        :params instance_ref:
2009
            nova.db.sqlalchemy.models.Instance object
2010
            instance object that is migrated.
2011
        :params dest: destination host
2012
        :params post_method:
2013
            post operation method.
2014
            expected nova.compute.manager.post_live_migration.
2015
        :params recover_method:
2016
            recovery method when any exception occurs.
2017
            expected nova.compute.manager.recover_live_migration.
2018
2019
        """
2020
2021
        # Do live migration.
2022
        try:
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2023
            if block_migration:
2024
                flaglist = FLAGS.block_migration_flag.split(',')
2025
            else:
2026
                flaglist = FLAGS.live_migration_flag.split(',')
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2027
            flagvals = [getattr(libvirt, x.strip()) for x in flaglist]
2028
            logical_sum = reduce(lambda x, y: x | y, flagvals)
2029
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2030
            dom = self._conn.lookupByName(instance_ref.name)
2031
            dom.migrateToURI(FLAGS.live_migration_uri % dest,
2032
                             logical_sum,
2033
                             None,
2034
                             FLAGS.live_migration_bandwidth)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2035
2036
        except Exception:
1.1.41 by Chuck Short
Import upstream version 2012.1~e3~20120120.12170
2037
            with utils.save_and_reraise_exception():
2038
                recover_method(ctxt, instance_ref, dest, block_migration)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2039
2040
        # Waiting for completion of live_migration.
2041
        timer = utils.LoopingCall(f=None)
2042
2043
        def wait_for_live_migration():
2044
            """waiting for live migration completion"""
2045
            try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2046
                self.get_info(instance_ref)['state']
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2047
            except exception.NotFound:
2048
                timer.stop()
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2049
                post_method(ctxt, instance_ref, dest, block_migration)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2050
2051
        timer.f = wait_for_live_migration
2052
        timer.start(interval=0.5, now=True)
2053
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
2054
    def pre_live_migration(self, block_device_info):
2055
        """Preparation live migration.
2056
2057
        :params block_device_info:
2058
            It must be the result of _get_instance_volume_bdms()
2059
            at compute manager.
2060
        """
2061
2062
        # Establishing connection to volume server.
2063
        block_device_mapping = driver.block_device_info_get_mapping(
2064
            block_device_info)
2065
        for vol in block_device_mapping:
2066
            connection_info = vol['connection_info']
2067
            mountpoint = vol['mount_device']
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2068
            self.volume_driver_method('connect_volume',
2069
                                      connection_info,
2070
                                      mountpoint)
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
2071
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2072
    def pre_block_migration(self, ctxt, instance_ref, disk_info_json):
2073
        """Preparation block migration.
2074
2075
        :params ctxt: security context
2076
        :params instance_ref:
2077
            nova.db.sqlalchemy.models.Instance object
2078
            instance object that is migrated.
2079
        :params disk_info_json:
2080
            json strings specified in get_instance_disk_info
2081
2082
        """
2083
        disk_info = utils.loads(disk_info_json)
2084
2085
        # make instance directory
2086
        instance_dir = os.path.join(FLAGS.instances_path, instance_ref['name'])
2087
        if os.path.exists(instance_dir):
2088
            raise exception.DestinationDiskExists(path=instance_dir)
2089
        os.mkdir(instance_dir)
2090
2091
        for info in disk_info:
2092
            base = os.path.basename(info['path'])
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
2093
            # Get image type and create empty disk image, and
2094
            # create backing file in case of qcow2.
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2095
            instance_disk = os.path.join(instance_dir, base)
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
2096
            if not info['backing_file']:
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
2097
                libvirt_utils.create_image(info['type'], instance_disk,
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2098
                                           info['disk_size'])
1.1.33 by Chuck Short
Import upstream version 2012.1~e1~20111020.11229
2099
            else:
2100
                # Creating backing file follows same way as spawning instances.
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2101
                cache_name = os.path.basename(info['backing_file'])
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
2102
                # Remove any size tags which the cache manages
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2103
                cache_name = cache_name.split('_')[0]
2104
2105
                self._cache_image(fn=libvirt_utils.fetch_image,
2106
                    context=ctxt,
2107
                    target=instance_disk,
2108
                    fname=cache_name,
2109
                    cow=FLAGS.use_cow_images,
2110
                    image_id=instance_ref['image_ref'],
2111
                    user_id=instance_ref['user_id'],
2112
                    project_id=instance_ref['project_id'],
2113
                    size=info['disk_size'])
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2114
2115
        # if image has kernel and ramdisk, just download
2116
        # following normal way.
2117
        if instance_ref['kernel_id']:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2118
            libvirt_utils.fetch_image(ctxt,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2119
                              os.path.join(instance_dir, 'kernel'),
2120
                              instance_ref['kernel_id'],
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
2121
                              instance_ref['user_id'],
2122
                              instance_ref['project_id'])
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2123
            if instance_ref['ramdisk_id']:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2124
                libvirt_utils.fetch_image(ctxt,
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2125
                                  os.path.join(instance_dir, 'ramdisk'),
2126
                                  instance_ref['ramdisk_id'],
1.1.42 by Chuck Short
Import upstream version 2012.1~e3
2127
                                  instance_ref['user_id'],
2128
                                  instance_ref['project_id'])
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2129
2130
    def post_live_migration_at_destination(self, ctxt,
2131
                                           instance_ref,
2132
                                           network_info,
2133
                                           block_migration):
2134
        """Post operation of live migration at destination host.
2135
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2136
        :param ctxt: security context
2137
        :param instance_ref:
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2138
            nova.db.sqlalchemy.models.Instance object
2139
            instance object that is migrated.
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2140
        :param network_info: instance network infomation
2141
        :param block_migration: if true, post operation of block_migraiton.
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2142
        """
2143
        # Define migrated instance, otherwise, suspend/destroy does not work.
2144
        dom_list = self._conn.listDefinedDomains()
2145
        if instance_ref.name not in dom_list:
2146
            instance_dir = os.path.join(FLAGS.instances_path,
2147
                                        instance_ref.name)
2148
            xml_path = os.path.join(instance_dir, 'libvirt.xml')
2149
            # In case of block migration, destination does not have
2150
            # libvirt.xml
2151
            if not os.path.isfile(xml_path):
2152
                xml = self.to_xml(instance_ref, network_info=network_info)
2153
                f = open(os.path.join(instance_dir, 'libvirt.xml'), 'w+')
2154
                f.write(xml)
2155
                f.close()
2156
            # libvirt.xml should be made by to_xml(), but libvirt
2157
            # does not accept to_xml() result, since uuid is not
2158
            # included in to_xml() result.
2159
            dom = self._lookup_by_name(instance_ref.name)
2160
            self._conn.defineXML(dom.XMLDesc(0))
2161
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2162
    def get_instance_disk_info(self, instance_name):
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2163
        """Preparation block migration.
2164
2165
        :params ctxt: security context
2166
        :params instance_ref:
2167
            nova.db.sqlalchemy.models.Instance object
2168
            instance object that is migrated.
2169
        :return:
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2170
            json strings with below format::
2171
2172
                "[{'path':'disk', 'type':'raw',
2173
                  'virt_disk_size':'10737418240',
2174
                  'backing_file':'backing_file',
2175
                  'disk_size':'83886080'},...]"
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2176
2177
        """
2178
        disk_info = []
2179
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2180
        virt_dom = self._lookup_by_name(instance_name)
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2181
        xml = virt_dom.XMLDesc(0)
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
2182
        doc = ElementTree.fromstring(xml)
2183
        disk_nodes = doc.findall('.//devices/disk')
2184
        path_nodes = doc.findall('.//devices/disk/source')
2185
        driver_nodes = doc.findall('.//devices/disk/driver')
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2186
2187
        for cnt, path_node in enumerate(path_nodes):
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
2188
            disk_type = disk_nodes[cnt].get('type')
2189
            path = path_node.get('file')
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2190
2191
            if disk_type != 'file':
2192
                LOG.debug(_('skipping %(path)s since it looks like volume') %
2193
                          locals())
2194
                continue
2195
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
2196
            # get the real disk size or
2197
            # raise a localized error if image is unavailable
2198
            dk_size = int(os.path.getsize(path))
2199
1.1.35 by Chuck Short
Import upstream version 2012.1~e2~20111116.11495
2200
            disk_type = driver_nodes[cnt].get('type')
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2201
            if disk_type == "qcow2":
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2202
                out, err = utils.execute('qemu-img', 'info', path)
2203
2204
                # virtual size:
2205
                size = [i.split('(')[1].split()[0] for i in out.split('\n')
2206
                    if i.strip().find('virtual size') >= 0]
2207
                virt_size = int(size[0])
2208
2209
                # backing file:(actual path:)
2210
                backing_file = libvirt_utils.get_disk_backing_file(path)
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2211
            else:
2212
                backing_file = ""
2213
                virt_size = 0
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2214
2215
            disk_info.append({'type': disk_type,
2216
                              'path': path,
2217
                              'virt_disk_size': virt_size,
2218
                              'backing_file': backing_file,
2219
                              'disk_size': dk_size})
1.1.27 by Chuck Short
Import upstream version 2011.3~d4
2220
        return utils.dumps(disk_info)
2221
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2222
    def get_disk_available_least(self):
2223
        """Return disk available least size.
2224
2225
        The size of available disk, when block_migration command given
2226
        disk_over_commit param is FALSE.
2227
2228
        The size that deducted real nstance disk size from the total size
2229
        of the virtual disk of all instances.
2230
2231
        """
2232
        # available size of the disk
2233
        dk_sz_gb = self.get_local_gb_total() - self.get_local_gb_used()
2234
2235
        # Disk size that all instance uses : virtual_size - disk_size
2236
        instances_name = self.list_instances()
2237
        instances_sz = 0
2238
        for i_name in instances_name:
1.1.50 by Chuck Short
Import upstream version 2012.1~rc1
2239
            try:
2240
                disk_infos = utils.loads(self.get_instance_disk_info(i_name))
2241
                for info in disk_infos:
2242
                    i_vt_sz = int(info['virt_disk_size'])
2243
                    i_dk_sz = int(info['disk_size'])
2244
                    instances_sz += i_vt_sz - i_dk_sz
2245
            except OSError as e:
2246
                if e.errno == errno.ENOENT:
2247
                    LOG.error(_("Getting disk size of %(i_name)s: %(e)s") %
2248
                              locals())
2249
                else:
2250
                    raise
1.1.51 by Chuck Short
Import upstream version 2012.1~rc2
2251
            except exception.InstanceNotFound:
2252
                # Instance was deleted during the check so ignore it
2253
                pass
1.1.40 by Chuck Short
Import upstream version 2012.1~e3~20120113.12049
2254
2255
        # Disk available least size
2256
        available_least_size = dk_sz_gb * (1024 ** 3) - instances_sz
2257
        return (available_least_size / 1024 / 1024 / 1024)
2258
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
2259
    def unfilter_instance(self, instance_ref, network_info):
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2260
        """See comments of same method in firewall_driver."""
1.1.24 by Chuck Short
Import upstream version 2011.3~d3
2261
        self.firewall_driver.unfilter_instance(instance_ref,
2262
                                               network_info=network_info)
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2263
2264
    def update_host_status(self):
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
2265
        """Retrieve status info from libvirt.
2266
2267
        Query libvirt to get the state of the compute node, such
2268
        as memory and disk usage.
2269
        """
2270
        return self.host_state.update_status()
1.1.18 by Chuck Short
Import upstream version 2011.3~d1
2271
2272
    def get_host_stats(self, refresh=False):
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
2273
        """Return the current state of the host.
2274
2275
        If 'refresh' is True, run update the stats first."""
2276
        return self.host_state.get_host_stats(refresh=refresh)
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
2277
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
2278
    def host_power_action(self, host, action):
2279
        """Reboots, shuts down or powers up the host."""
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
2280
        raise NotImplementedError()
1.1.26 by Chuck Short
Import upstream version 2011.3~d4~20110812.1417
2281
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2282
    def host_maintenance_mode(self, host, mode):
2283
        """Start/Stop host maintenance window. On start, it triggers
2284
        guest VMs evacuation."""
2285
        raise NotImplementedError()
2286
1.1.22 by Chuck Short
Import upstream version 2011.3~d3~20110708.1251
2287
    def set_host_enabled(self, host, enabled):
2288
        """Sets the specified host's ability to accept new instances."""
2289
        pass
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
2290
1.1.43 by Chuck Short
Import upstream version 2012.1~e4~20120203.12454
2291
    def manage_image_cache(self, context):
2292
        """Manage the local cache of images."""
2293
        self.image_cache_manager.verify_base_images(context)
2294
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2295
    @exception.wrap_exception()
2296
    def migrate_disk_and_power_off(self, context, instance, dest,
2297
                                   instance_type, network_info):
2298
        LOG.debug(_("Instance %s: Starting migrate_disk_and_power_off"),
2299
                   instance['name'])
2300
        disk_info_text = self.get_instance_disk_info(instance['name'])
2301
        disk_info = utils.loads(disk_info_text)
2302
2303
        self._destroy(instance, network_info, cleanup=False)
2304
2305
        # copy disks to destination
2306
        # if disk type is qcow2, convert to raw then send to dest.
2307
        # rename instance dir to +_resize at first for using
2308
        # shared storage for instance dir (eg. NFS).
2309
        same_host = (dest == self.get_host_ip_addr())
2310
        inst_base = "%s/%s" % (FLAGS.instances_path, instance['name'])
2311
        inst_base_resize = inst_base + "_resize"
2312
        try:
2313
            utils.execute('mv', inst_base, inst_base_resize)
2314
            if same_host:
2315
                utils.execute('mkdir', '-p', inst_base)
2316
            else:
2317
                utils.execute('ssh', dest, 'mkdir', '-p', inst_base)
2318
            for info in disk_info:
2319
                # assume inst_base == dirname(info['path'])
2320
                to_path = "%s:%s" % (dest, info['path'])
2321
                fname = os.path.basename(info['path'])
2322
                from_path = os.path.join(inst_base_resize, fname)
2323
                if info['type'] == 'qcow2':
2324
                    tmp_path = from_path + "_rbase"
2325
                    utils.execute('qemu-img', 'convert', '-f', 'qcow2',
2326
                                  '-O', 'raw', from_path, tmp_path)
2327
                    if same_host:
2328
                        utils.execute('mv', tmp_path, info['path'])
2329
                    else:
2330
                        utils.execute('scp', tmp_path, to_path)
2331
                        utils.execute('rm', '-f', tmp_path)
2332
                else:  # raw
2333
                    if same_host:
2334
                        utils.execute('cp', from_path, info['path'])
2335
                    else:
2336
                        utils.execute('scp', from_path, to_path)
2337
        except Exception, e:
2338
            try:
2339
                if os.path.exists(inst_base_resize):
2340
                    utils.execute('rm', '-rf', inst_base)
2341
                    utils.execute('mv', inst_base_resize, inst_base)
2342
                    utils.execute('ssh', dest, 'rm', '-rf', inst_base)
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2343
            except Exception:
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2344
                pass
2345
            raise e
2346
2347
        return disk_info_text
2348
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2349
    def _wait_for_running(self, instance):
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2350
        try:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2351
            state = self.get_info(instance)['state']
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2352
        except exception.NotFound:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2353
            LOG.error(_("During wait running, instance disappeared."),
2354
                      instance=instance)
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2355
            raise utils.LoopingCallDone(False)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2356
2357
        if state == power_state.RUNNING:
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2358
            LOG.info(_("Instance running successfully."),
2359
                     instance=instance)
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2360
            raise utils.LoopingCallDone(True)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2361
2362
    @exception.wrap_exception()
2363
    def finish_migration(self, context, migration, instance, disk_info,
2364
                         network_info, image_meta, resize_instance):
2365
        LOG.debug(_("Instance %s: Starting finish_migration"),
2366
                   instance['name'])
2367
2368
        # resize disks. only "disk" and "disk.local" are necessary.
2369
        disk_info = utils.loads(disk_info)
2370
        for info in disk_info:
2371
            fname = os.path.basename(info['path'])
2372
            if fname == 'disk':
2373
                disk.extend(info['path'],
2374
                            instance['root_gb'] * 1024 * 1024 * 1024)
2375
            elif fname == 'disk.local':
2376
                disk.extend(info['path'],
2377
                            instance['ephemeral_gb'] * 1024 * 1024 * 1024)
2378
            if FLAGS.use_cow_images:
2379
                # back to qcow2 (no backing_file though) so that snapshot
2380
                # will be available
2381
                path_qcow = info['path'] + '_qcow'
2382
                utils.execute('qemu-img', 'convert', '-f', 'raw',
2383
                              '-O', 'qcow2', info['path'], path_qcow)
2384
                utils.execute('mv', path_qcow, info['path'])
2385
2386
        xml = self.to_xml(instance, network_info)
2387
2388
        self.plug_vifs(instance, network_info)
2389
        self.firewall_driver.setup_basic_filtering(instance, network_info)
2390
        self.firewall_driver.prepare_instance_filter(instance, network_info)
2391
        # assume _create_image do nothing if a target file exists.
2392
        # TODO(oda): injecting files is not necessary
2393
        self._create_image(context, instance, xml,
2394
                                    network_info=network_info,
2395
                                    block_device_info=None)
2396
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2397
        self._create_new_domain(xml)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2398
        self.firewall_driver.apply_instance_filter(instance, network_info)
2399
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2400
        timer = utils.LoopingCall(self._wait_for_running, instance)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2401
        return timer.start(interval=0.5, now=True)
2402
2403
    @exception.wrap_exception()
2404
    def finish_revert_migration(self, instance, network_info):
2405
        LOG.debug(_("Instance %s: Starting finish_revert_migration"),
2406
                   instance['name'])
2407
2408
        inst_base = "%s/%s" % (FLAGS.instances_path, instance['name'])
2409
        inst_base_resize = inst_base + "_resize"
2410
        utils.execute('mv', inst_base_resize, inst_base)
2411
2412
        xml_path = os.path.join(inst_base, 'libvirt.xml')
2413
        xml = open(xml_path).read()
2414
2415
        self.plug_vifs(instance, network_info)
2416
        self.firewall_driver.setup_basic_filtering(instance, network_info)
2417
        self.firewall_driver.prepare_instance_filter(instance, network_info)
2418
        # images already exist
1.1.48 by Chuck Short
Import upstream version 2012.1~rc1~20120309.13261
2419
        self._create_new_domain(xml)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2420
        self.firewall_driver.apply_instance_filter(instance, network_info)
2421
1.1.46 by Chuck Short
Import upstream version 2012.1~e4~20120224.12913
2422
        timer = utils.LoopingCall(self._wait_for_running, instance)
1.1.45 by Chuck Short
Import upstream version 2012.1~e4~20120217.12709
2423
        return timer.start(interval=0.5, now=True)
2424
2425
    def confirm_migration(self, migration, instance, network_info):
2426
        """Confirms a resize, destroying the source VM"""
2427
        self._cleanup_resize(instance)
2428
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
2429
2430
class HostState(object):
2431
    """Manages information about the compute node through libvirt"""
2432
    def __init__(self, read_only):
2433
        super(HostState, self).__init__()
2434
        self.read_only = read_only
2435
        self._stats = {}
2436
        self.connection = None
2437
        self.update_status()
2438
2439
    def get_host_stats(self, refresh=False):
2440
        """Return the current state of the host.
2441
2442
        If 'refresh' is True, run update the stats first."""
2443
        if refresh:
2444
            self.update_status()
2445
        return self._stats
2446
2447
    def update_status(self):
2448
        """Retrieve status info from libvirt."""
2449
        LOG.debug(_("Updating host stats"))
2450
        if self.connection is None:
2451
            self.connection = get_connection(self.read_only)
2452
        data = {}
2453
        data["vcpus"] = self.connection.get_vcpu_total()
2454
        data["vcpus_used"] = self.connection.get_vcpu_used()
2455
        data["cpu_info"] = utils.loads(self.connection.get_cpu_info())
2456
        data["disk_total"] = self.connection.get_local_gb_total()
2457
        data["disk_used"] = self.connection.get_local_gb_used()
2458
        data["disk_available"] = data["disk_total"] - data["disk_used"]
2459
        data["host_memory_total"] = self.connection.get_memory_mb_total()
1.1.44 by Chuck Short
Import upstream version 2012.1~e4~20120210.12574
2460
        data["host_memory_free"] = (data["host_memory_total"] -
2461
                                    self.connection.get_memory_mb_used())
1.1.34 by Chuck Short
Import upstream version 2012.1~e1
2462
        data["hypervisor_type"] = self.connection.get_hypervisor_type()
2463
        data["hypervisor_version"] = self.connection.get_hypervisor_version()
2464
2465
        self._stats = data
1.1.36 by Chuck Short
Import upstream version 2012.1~e2~20111125.11566
2466
2467
        return data