summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--Authors2
-rwxr-xr-xbin/nova-manage2
-rw-r--r--nova/api/openstack/compute/contrib/disk_config.py2
-rw-r--r--nova/api/openstack/compute/contrib/extended_status.py3
-rw-r--r--nova/compute/api.py3
-rw-r--r--nova/compute/manager.py7
-rw-r--r--nova/exception.py16
-rw-r--r--nova/scheduler/api.py2
-rw-r--r--nova/tests/test_libvirt.py274
-rw-r--r--nova/tests/test_virt_drivers.py9
-rw-r--r--nova/tests/test_xenapi.py9
-rw-r--r--nova/virt/driver.py4
-rw-r--r--nova/virt/fake.py5
-rw-r--r--nova/virt/libvirt/connection.py142
-rw-r--r--nova/virt/libvirt/utils.py3
-rw-r--r--nova/virt/vmwareapi/network_utils.py6
-rw-r--r--nova/virt/xenapi_conn.py6
18 files changed, 463 insertions, 33 deletions
diff --git a/.mailmap b/.mailmap
index 397a942ae..5807e0eeb 100644
--- a/.mailmap
+++ b/.mailmap
@@ -18,6 +18,7 @@
<corywright@gmail.com> <cory.wright@rackspace.com>
<dan@nicira.com> <danwent@dan-xs3-cs>
<dan@nicira.com> <danwent@gmail.com>
+<derekh@redhat.com> <higginsd@gmail.com>
<devin.carlen@gmail.com> <devcamcar@illian.local>
<dprince@redhat.com> <dan.prince@rackspace.com>
<edouard1.thuleau@orange.com> <thuleau@gmail.com>
diff --git a/Authors b/Authors
index 28fe3be19..e8f539653 100644
--- a/Authors
+++ b/Authors
@@ -42,7 +42,7 @@ David Pravec <David.Pravec@danix.org>
David Subiros <david.perez5@hp.com>
Dean Troyer <dtroyer@gmail.com>
Deepak Garg <deepak.garg@citrix.com>
-Derek Higgins <higginsd@gmail.com>
+Derek Higgins <derekh@redhat.com>
Devdeep Singh <devdeep.singh@citrix.com>
Devendra Modium <dmodium@isi.edu>
Devin Carlen <devin.carlen@gmail.com>
diff --git a/bin/nova-manage b/bin/nova-manage
index a271cf2ff..49ec41656 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -616,7 +616,7 @@ class ProjectCommands(object):
print e
print _("The above error may show that the certificate db has "
"not been created.\nPlease create a database by running "
- "a nova-api server on this host.")
+ "a nova-cert server on this host.")
AccountCommands = ProjectCommands
diff --git a/nova/api/openstack/compute/contrib/disk_config.py b/nova/api/openstack/compute/contrib/disk_config.py
index 46c09ffa8..5b249478a 100644
--- a/nova/api/openstack/compute/contrib/disk_config.py
+++ b/nova/api/openstack/compute/contrib/disk_config.py
@@ -106,6 +106,8 @@ class ServerDiskConfigController(wsgi.Controller):
# Filter out any servers that already have the key set
# (most likely from a remote zone)
servers = [s for s in servers if API_DISK_CONFIG not in s]
+ if not servers:
+ return
# Get DB information for servers
uuids = [server['id'] for server in servers]
diff --git a/nova/api/openstack/compute/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py
index 55e4a3aee..9447bf300 100644
--- a/nova/api/openstack/compute/contrib/extended_status.py
+++ b/nova/api/openstack/compute/contrib/extended_status.py
@@ -36,6 +36,9 @@ class ExtendedStatusController(wsgi.Controller):
self.compute_api = compute.API()
def _get_instances(self, context, instance_uuids):
+ if not instance_uuids:
+ return {}
+
filters = {'uuid': instance_uuids}
instances = self.compute_api.get_all(context, filters)
return dict((instance['uuid'], instance) for instance in instances)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 30fe911ff..514f0c133 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -1729,6 +1729,9 @@ class API(base.Base):
def get_instance_faults(self, context, instances):
"""Get all faults for a list of instance uuids."""
+ if not instances:
+ return {}
+
for instance in instances:
check_policy(context, 'get_instance_faults', instance)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 159aa8c76..3639541ff 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1152,6 +1152,7 @@ class ComputeManager(manager.SchedulerDependentManager):
migration_ref = self.db.migration_get(context, migration_id)
instance_ref = self.db.instance_get_by_uuid(context,
migration_ref.instance_uuid)
+ network_info = self._get_instance_nw_info(context, instance_ref)
self._notify_about_instance_usage(instance_ref, "resize.revert.start")
@@ -1171,7 +1172,8 @@ class ComputeManager(manager.SchedulerDependentManager):
vm_state=vm_states.ACTIVE,
task_state=None)
- self.driver.finish_revert_migration(instance_ref)
+ self.driver.finish_revert_migration(instance_ref,
+ self._legacy_nw_info(network_info))
self.db.migration_update(context, migration_id,
{'status': 'reverted'})
@@ -1239,6 +1241,7 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_type_ref = self.db.instance_type_get(context,
migration_ref.new_instance_type_id)
+ network_info = self._get_instance_nw_info(context, instance_ref)
self.db.migration_update(context,
migration_id,
{'status': 'migrating'})
@@ -1246,7 +1249,7 @@ class ComputeManager(manager.SchedulerDependentManager):
try:
disk_info = self.driver.migrate_disk_and_power_off(
context, instance_ref, migration_ref['dest_host'],
- instance_type_ref)
+ instance_type_ref, self._legacy_nw_info(network_info))
except Exception, error:
with utils.save_and_reraise_exception():
msg = _('%s. Setting instance vm_state to ERROR')
diff --git a/nova/exception.py b/nova/exception.py
index dfa20dd25..9bb39b2f4 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -76,8 +76,7 @@ class ProcessExecutionError(IOError):
class Error(Exception):
- def __init__(self, message=None):
- super(Error, self).__init__(message)
+ pass
class EC2APIError(Error):
@@ -207,9 +206,6 @@ class MelangeConnectionFailed(NovaException):
class NotAuthorized(NovaException):
message = _("Not authorized.")
- def __init__(self, *args, **kwargs):
- super(NotAuthorized, self).__init__(*args, **kwargs)
-
class AdminRequired(NotAuthorized):
message = _("User does not have admin privileges")
@@ -406,9 +402,6 @@ class InvalidEc2Id(Invalid):
class NotFound(NovaException):
message = _("Resource could not be found.")
- def __init__(self, *args, **kwargs):
- super(NotFound, self).__init__(*args, **kwargs)
-
class FlagNotSet(NotFound):
message = _("Required flag %(flag)s not set.")
@@ -911,11 +904,8 @@ class ImageTooLarge(NovaException):
message = _("Image is larger than instance type allows")
-class ZoneRequestError(Error):
- def __init__(self, message=None):
- if message is None:
- message = _("1 or more Zones could not complete the request")
- super(ZoneRequestError, self).__init__(message=message)
+class ZoneRequestError(NovaException):
+ message = _("1 or more Zones could not complete the request")
class InstanceTypeMemoryTooSmall(NovaException):
diff --git a/nova/scheduler/api.py b/nova/scheduler/api.py
index 9706a5d8e..68d4c29e7 100644
--- a/nova/scheduler/api.py
+++ b/nova/scheduler/api.py
@@ -259,7 +259,7 @@ class RedirectResult(exception.Error):
def __init__(self, results):
self.results = results
super(RedirectResult, self).__init__(
- message=_("Uncaught Zone redirection exception"))
+ _("Uncaught Zone redirection exception"))
class reroute_compute(object):
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 66a8db2b5..2eede7ed5 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -20,6 +20,7 @@ import mox
import os
import re
import shutil
+import sys
import tempfile
from xml.etree.ElementTree import fromstring as xml_to_tree
@@ -33,10 +34,12 @@ from nova import log as logging
from nova import test
from nova import utils
from nova.api.ec2 import cloud
+from nova.compute import instance_types
from nova.compute import power_state
from nova.compute import vm_states
from nova.virt import images
from nova.virt import driver
+from nova.virt import firewall as base_firewall
from nova.virt.libvirt import connection
from nova.virt.libvirt import firewall
from nova.virt.libvirt import volume
@@ -1175,7 +1178,8 @@ class LibvirtConnTestCase(test.TestCase):
conn = connection.LibvirtConnection(False)
self.stubs.Set(conn, '_lookup_by_name', fake_lookup_by_name)
- instance = {"name": "instancename", "id": "instanceid"}
+ instance = {"name": "instancename", "id": "instanceid",
+ "uuid": "875a8070-d0b9-4949-8b31-104d125c9a64"}
conn.destroy(instance, [])
@@ -1983,3 +1987,271 @@ disk size: 4.4M''', ''))
self.mox.ReplayAll()
libvirt_utils.fetch_image(context, target, image_id,
user_id, project_id)
+
+
+class LibvirtConnectionTestCase(test.TestCase):
+ """Test for nova.virt.libvirt.connection.LibvirtConnection."""
+ def setUp(self):
+ super(LibvirtConnectionTestCase, self).setUp()
+
+ self.libvirtconnection = connection.LibvirtConnection(read_only=True)
+ self.platform = sys.platform
+ self.exe_flag = False
+
+ self.temp_path = os.path.join(flags.FLAGS.instances_path,
+ 'instance-00000001/', '')
+ try:
+ os.makedirs(self.temp_path)
+ except Exception:
+ print 'testcase init error'
+ pass
+
+ def tearDown(self):
+ super(LibvirtConnectionTestCase, self).tearDown()
+ sys.platform = self.platform
+
+ try:
+ shutil.rmtree(flags.FLAGS.instances_path)
+ except Exception:
+ pass
+
+ class NullFirewallDriver(base_firewall.FirewallDriver):
+ def __init__(self, get_connection, **kwargs):
+ pass
+
+ def prepare_instance_filter(self, instance, network_info):
+ pass
+
+ def unfilter_instance(self, instance, network_info):
+ pass
+
+ def apply_instance_filter(self, instance, network_info):
+ pass
+
+ def refresh_security_group_rules(self, security_group_id):
+ pass
+
+ def refresh_security_group_members(self, security_group_id):
+ pass
+
+ def refresh_provider_fw_rules(self):
+ pass
+
+ def setup_basic_filtering(self, instance, network_info):
+ pass
+
+ def instance_filter_exists(self, instance, network_info):
+ return True
+
+ def _create_instance(self, params=None):
+ """Create a test instance"""
+ if not params:
+ params = {}
+
+ inst = {}
+ inst['image_ref'] = '1'
+ inst['reservation_id'] = 'r-fakeres'
+ inst['launch_time'] = '10'
+ inst['user_id'] = 'fake'
+ inst['project_id'] = 'fake'
+ type_id = instance_types.get_instance_type_by_name('m1.tiny')['id']
+ inst['instance_type_id'] = type_id
+ inst['ami_launch_index'] = 0
+ inst['host'] = 'host1'
+ inst['root_gb'] = 10
+ inst['ephemeral_gb'] = 20
+ inst['config_drive'] = 1
+ inst['kernel_id'] = 2
+ inst['ramdisk_id'] = 3
+ inst['config_drive_id'] = 1
+ inst['key_data'] = 'ABCDEFG'
+
+ inst.update(params)
+ return db.instance_create(context.get_admin_context(), inst)
+
+ def test_migrate_disk_and_power_off_exception(self):
+ """Test for nova.virt.libvirt.connection.LivirtConnection
+ .migrate_disk_and_power_off. """
+
+ self.counter = 0
+
+ def fake_get_instance_disk_info(instance):
+ return []
+
+ def fake_destroy(instance, network_info, cleanup=True):
+ pass
+
+ def fake_get_host_ip_addr():
+ return '10.0.0.1'
+
+ def fake_execute(*args, **kwargs):
+ self.counter += 1
+ if self.counter == 1:
+ raise Exception()
+ pass
+
+ def fake_os_path_exists(path):
+ return True
+
+ self.stubs.Set(self.libvirtconnection, 'get_instance_disk_info',
+ fake_get_instance_disk_info)
+ self.stubs.Set(self.libvirtconnection, '_destroy', fake_destroy)
+ self.stubs.Set(self.libvirtconnection, 'get_host_ip_addr',
+ fake_get_host_ip_addr)
+ self.stubs.Set(utils, 'execute', fake_execute)
+ self.stubs.Set(os.path, 'exists', fake_os_path_exists)
+
+ ins_ref = self._create_instance()
+ self.assertRaises(Exception,
+ self.libvirtconnection.migrate_disk_and_power_off,
+ None, ins_ref, [], '10.0.0.2', None, None)
+
+ def test_migrate_disk_and_power_off(self):
+ """Test for nova.virt.libvirt.connection.LivirtConnection
+ .migrate_disk_and_power_off. """
+
+ disk_info = [{'type': 'qcow2', 'path': '/test/disk',
+ 'virt_disk_size': '10737418240',
+ 'backing_file': '/base/disk',
+ 'disk_size':'83886080'},
+ {'type': 'raw', 'path': '/test/disk.local',
+ 'virt_disk_size': '10737418240',
+ 'backing_file': '/base/disk.local',
+ 'disk_size':'83886080'}]
+ disk_info_text = utils.dumps(disk_info)
+
+ def fake_get_instance_disk_info(instance):
+ return disk_info_text
+
+ def fake_destroy(instance, network_info, cleanup=True):
+ pass
+
+ def fake_get_host_ip_addr():
+ return '10.0.0.1'
+
+ def fake_execute(*args, **kwargs):
+ pass
+
+ self.stubs.Set(self.libvirtconnection, 'get_instance_disk_info',
+ fake_get_instance_disk_info)
+ self.stubs.Set(self.libvirtconnection, '_destroy', fake_destroy)
+ self.stubs.Set(self.libvirtconnection, 'get_host_ip_addr',
+ fake_get_host_ip_addr)
+ self.stubs.Set(utils, 'execute', fake_execute)
+
+ ins_ref = self._create_instance()
+ """ dest is different host case """
+ out = self.libvirtconnection.migrate_disk_and_power_off(
+ None, ins_ref, '10.0.0.2', None, None)
+ self.assertEquals(out, disk_info_text)
+
+ """ dest is same host case """
+ out = self.libvirtconnection.migrate_disk_and_power_off(
+ None, ins_ref, '10.0.0.1', None, None)
+ self.assertEquals(out, disk_info_text)
+
+ def test_wait_for_running(self):
+ """Test for nova.virt.libvirt.connection.LivirtConnection
+ ._wait_for_running. """
+
+ def fake_get_info(instance_name):
+ if instance_name == "not_found":
+ raise exception.NotFound
+ elif instance_name == "running":
+ return {'state': power_state.RUNNING}
+ else:
+ return {'state': power_state.SHUTOFF}
+
+ self.stubs.Set(self.libvirtconnection, 'get_info',
+ fake_get_info)
+
+ """ instance not found case """
+ self.assertRaises(utils.LoopingCallDone,
+ self.libvirtconnection._wait_for_running,
+ "not_found")
+
+ """ instance is running case """
+ self.assertRaises(utils.LoopingCallDone,
+ self.libvirtconnection._wait_for_running,
+ "running")
+
+ """ else case """
+ self.libvirtconnection._wait_for_running("else")
+
+ def test_finish_migration(self):
+ """Test for nova.virt.libvirt.connection.LivirtConnection
+ .finish_migration. """
+
+ disk_info = [{'type': 'qcow2', 'path': '/test/disk',
+ 'local_gb': 10, 'backing_file': '/base/disk'},
+ {'type': 'raw', 'path': '/test/disk.local',
+ 'local_gb': 10, 'backing_file': '/base/disk.local'}]
+ disk_info_text = utils.dumps(disk_info)
+
+ def fake_extend(path, size):
+ pass
+
+ def fake_to_xml(instance, network_info):
+ return ""
+
+ def fake_plug_vifs(instance, network_info):
+ pass
+
+ def fake_create_image(context, inst, libvirt_xml, suffix='',
+ disk_images=None, network_info=None,
+ block_device_info=None):
+ pass
+
+ def fake_create_new_domain(xml):
+ return None
+
+ def fake_execute(*args, **kwargs):
+ pass
+
+ self.flags(use_cow_images=True)
+ self.stubs.Set(connection.disk, 'extend', fake_extend)
+ self.stubs.Set(self.libvirtconnection, 'to_xml', fake_to_xml)
+ self.stubs.Set(self.libvirtconnection, 'plug_vifs', fake_plug_vifs)
+ self.stubs.Set(self.libvirtconnection, '_create_image',
+ fake_create_image)
+ self.stubs.Set(self.libvirtconnection, '_create_new_domain',
+ fake_create_new_domain)
+ self.stubs.Set(utils, 'execute', fake_execute)
+ fw = self.NullFirewallDriver(None)
+ self.stubs.Set(self.libvirtconnection, 'firewall_driver', fw)
+
+ ins_ref = self._create_instance()
+
+ ref = self.libvirtconnection.finish_migration(
+ context.get_admin_context(), None, ins_ref,
+ disk_info_text, None, None, None)
+ self.assertTrue(isinstance(ref, eventlet.event.Event))
+
+ def test_finish_revert_migration(self):
+ """Test for nova.virt.libvirt.connection.LivirtConnection
+ .finish_revert_migration. """
+
+ def fake_execute(*args, **kwargs):
+ pass
+
+ def fake_plug_vifs(instance, network_info):
+ pass
+
+ def fake_create_new_domain(xml):
+ return None
+
+ self.stubs.Set(self.libvirtconnection, 'plug_vifs', fake_plug_vifs)
+ self.stubs.Set(utils, 'execute', fake_execute)
+ fw = self.NullFirewallDriver(None)
+ self.stubs.Set(self.libvirtconnection, 'firewall_driver', fw)
+ self.stubs.Set(self.libvirtconnection, '_create_new_domain',
+ fake_create_new_domain)
+
+ ins_ref = self._create_instance()
+ libvirt_xml_path = os.path.join(flags.FLAGS.instances_path,
+ ins_ref['name'], 'libvirt.xml')
+ f = open(libvirt_xml_path, 'w')
+ f.close()
+
+ ref = self.libvirtconnection.finish_revert_migration(ins_ref, None)
+ self.assertTrue(isinstance(ref, eventlet.event.Event))
diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py
index cf6632bda..41c5d118e 100644
--- a/nova/tests/test_virt_drivers.py
+++ b/nova/tests/test_virt_drivers.py
@@ -175,7 +175,8 @@ class _VirtDriverTestCase(test.TestCase):
instance_ref, network_info = self._get_running_instance()
instance_type_ref = test_utils.get_test_instance_type()
self.connection.migrate_disk_and_power_off(
- self.ctxt, instance_ref, 'dest_host', instance_type_ref)
+ self.ctxt, instance_ref, 'dest_host', instance_type_ref,
+ network_info)
@catch_notimplementederror
def test_pause(self):
@@ -465,3 +466,9 @@ class LibvirtConnTestCase(_VirtDriverTestCase):
nova.virt.libvirt.connection.libvirt_utils = self.saved_libvirt
nova.virt.libvirt.firewall.libvirt = self.saved_libvirt
super(LibvirtConnTestCase, self).tearDown()
+
+ @test.skip_test("Test nothing, but this method "
+ "needed to override superclass.")
+ def test_migrate_disk_and_power_off(self):
+ # there is lack of fake stuff to execute this method. so pass.
+ pass
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index f3343519e..2b1f99f7b 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -694,7 +694,7 @@ class XenAPIVMTestCase(test.TestCase):
conn = xenapi_conn.get_connection(False)
conn._vmops = VMOpsMock()
- conn.finish_revert_migration(instance)
+ conn.finish_revert_migration(instance, None)
self.assertTrue(conn._vmops.finish_revert_migration_called)
def _create_instance(self, instance_id=1, spawn=True):
@@ -849,7 +849,7 @@ class XenAPIMigrateInstance(test.TestCase):
stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
conn = xenapi_conn.get_connection(False)
conn.migrate_disk_and_power_off(self.context, instance,
- '127.0.0.1', instance_type)
+ '127.0.0.1', instance_type, None)
def test_migrate_disk_and_power_off_passes_exceptions(self):
instance = db.instance_create(self.context, self.instance_values)
@@ -863,7 +863,8 @@ class XenAPIMigrateInstance(test.TestCase):
conn = xenapi_conn.get_connection(False)
self.assertRaises(exception.MigrationError,
conn.migrate_disk_and_power_off,
- self.context, instance, '127.0.0.1', instance_type)
+ self.context, instance,
+ '127.0.0.1', instance_type, None)
def test_revert_migrate(self):
instance = db.instance_create(self.context, self.instance_values)
@@ -910,7 +911,7 @@ class XenAPIMigrateInstance(test.TestCase):
self.assertEqual(self.called, True)
self.assertEqual(self.fake_vm_start_called, True)
- conn.finish_revert_migration(instance)
+ conn.finish_revert_migration(instance, network_info)
self.assertEqual(self.fake_finish_revert_migration_called, True)
def test_finish_migrate(self):
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index ad2e82a31..821455b45 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -258,7 +258,7 @@ class ComputeDriver(object):
raise NotImplementedError()
def migrate_disk_and_power_off(self, context, instance, dest,
- instance_type):
+ instance_type, network_info):
"""
Transfers the disk of a running instance in multiple phases, turning
off the instance before the end.
@@ -293,7 +293,7 @@ class ComputeDriver(object):
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
- def finish_revert_migration(self, instance):
+ def finish_revert_migration(self, instance, network_info):
"""Finish reverting a resize, powering back on the instance"""
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 204ffb56c..53a1ea4c9 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -144,7 +144,10 @@ class FakeConnection(driver.ComputeDriver):
pass
def migrate_disk_and_power_off(self, context, instance, dest,
- instance_type):
+ instance_type, network_info):
+ pass
+
+ def finish_revert_migration(self, instance, network_info):
pass
def poll_unconfirmed_resizes(self, resize_confirm_window):
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index efd972b4b..77b53e9fb 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -63,6 +63,7 @@ from nova import flags
import nova.image
from nova import log as logging
from nova.openstack.common import cfg
+from nova import network
from nova import utils
from nova.virt import driver
from nova.virt import images
@@ -437,6 +438,12 @@ class LibvirtConnection(driver.ComputeDriver):
'initiator': self._initiator,
}
+ def _cleanup_resize(self, instance):
+ target = os.path.join(FLAGS.instances_path,
+ instance['name'] + "_resize")
+ if os.path.exists(target):
+ shutil.rmtree(target)
+
def volume_driver_method(self, method_name, connection_info,
*args, **kwargs):
driver_type = connection_info.get('driver_volume_type')
@@ -2081,6 +2088,141 @@ class LibvirtConnection(driver.ComputeDriver):
"""Manage the local cache of images."""
self.image_cache_manager.verify_base_images(context)
+ @exception.wrap_exception()
+ def migrate_disk_and_power_off(self, context, instance, dest,
+ instance_type, network_info):
+ LOG.debug(_("Instance %s: Starting migrate_disk_and_power_off"),
+ instance['name'])
+ disk_info_text = self.get_instance_disk_info(instance['name'])
+ disk_info = utils.loads(disk_info_text)
+
+ self._destroy(instance, network_info, cleanup=False)
+
+ # copy disks to destination
+ # if disk type is qcow2, convert to raw then send to dest.
+ # rename instance dir to +_resize at first for using
+ # shared storage for instance dir (eg. NFS).
+ same_host = (dest == self.get_host_ip_addr())
+ inst_base = "%s/%s" % (FLAGS.instances_path, instance['name'])
+ inst_base_resize = inst_base + "_resize"
+ try:
+ utils.execute('mv', inst_base, inst_base_resize)
+ if same_host:
+ utils.execute('mkdir', '-p', inst_base)
+ else:
+ utils.execute('ssh', dest, 'mkdir', '-p', inst_base)
+ for info in disk_info:
+ # assume inst_base == dirname(info['path'])
+ to_path = "%s:%s" % (dest, info['path'])
+ fname = os.path.basename(info['path'])
+ from_path = os.path.join(inst_base_resize, fname)
+ if info['type'] == 'qcow2':
+ tmp_path = from_path + "_rbase"
+ utils.execute('qemu-img', 'convert', '-f', 'qcow2',
+ '-O', 'raw', from_path, tmp_path)
+ if same_host:
+ utils.execute('mv', tmp_path, info['path'])
+ else:
+ utils.execute('scp', tmp_path, to_path)
+ utils.execute('rm', '-f', tmp_path)
+ else: # raw
+ if same_host:
+ utils.execute('cp', from_path, info['path'])
+ else:
+ utils.execute('scp', from_path, to_path)
+ except Exception, e:
+ try:
+ if os.path.exists(inst_base_resize):
+ utils.execute('rm', '-rf', inst_base)
+ utils.execute('mv', inst_base_resize, inst_base)
+ utils.execute('ssh', dest, 'rm', '-rf', inst_base)
+ except:
+ pass
+ raise e
+
+ return disk_info_text
+
+ def _wait_for_running(self, instance_name):
+ try:
+ state = self.get_info(instance_name)['state']
+ except exception.NotFound:
+ msg = _("During wait running, %s disappeared.") % instance_name
+ LOG.error(msg)
+ raise utils.LoopingCallDone
+
+ if state == power_state.RUNNING:
+ msg = _("Instance %s running successfully.") % instance_name
+ LOG.info(msg)
+ raise utils.LoopingCallDone
+
+ @exception.wrap_exception()
+ def finish_migration(self, context, migration, instance, disk_info,
+ network_info, image_meta, resize_instance):
+ LOG.debug(_("Instance %s: Starting finish_migration"),
+ instance['name'])
+
+ # resize disks. only "disk" and "disk.local" are necessary.
+ disk_info = utils.loads(disk_info)
+ for info in disk_info:
+ fname = os.path.basename(info['path'])
+ if fname == 'disk':
+ disk.extend(info['path'],
+ instance['root_gb'] * 1024 * 1024 * 1024)
+ elif fname == 'disk.local':
+ disk.extend(info['path'],
+ instance['ephemeral_gb'] * 1024 * 1024 * 1024)
+ if FLAGS.use_cow_images:
+ # back to qcow2 (no backing_file though) so that snapshot
+ # will be available
+ path_qcow = info['path'] + '_qcow'
+ utils.execute('qemu-img', 'convert', '-f', 'raw',
+ '-O', 'qcow2', info['path'], path_qcow)
+ utils.execute('mv', path_qcow, info['path'])
+
+ xml = self.to_xml(instance, network_info)
+
+ self.plug_vifs(instance, network_info)
+ self.firewall_driver.setup_basic_filtering(instance, network_info)
+ self.firewall_driver.prepare_instance_filter(instance, network_info)
+ # assume _create_image do nothing if a target file exists.
+ # TODO(oda): injecting files is not necessary
+ self._create_image(context, instance, xml,
+ network_info=network_info,
+ block_device_info=None)
+
+ domain = self._create_new_domain(xml)
+
+ self.firewall_driver.apply_instance_filter(instance, network_info)
+
+ timer = utils.LoopingCall(self._wait_for_running, instance['name'])
+ return timer.start(interval=0.5, now=True)
+
+ @exception.wrap_exception()
+ def finish_revert_migration(self, instance, network_info):
+ LOG.debug(_("Instance %s: Starting finish_revert_migration"),
+ instance['name'])
+
+ inst_base = "%s/%s" % (FLAGS.instances_path, instance['name'])
+ inst_base_resize = inst_base + "_resize"
+ utils.execute('mv', inst_base_resize, inst_base)
+
+ xml_path = os.path.join(inst_base, 'libvirt.xml')
+ xml = open(xml_path).read()
+
+ self.plug_vifs(instance, network_info)
+ self.firewall_driver.setup_basic_filtering(instance, network_info)
+ self.firewall_driver.prepare_instance_filter(instance, network_info)
+ # images already exist
+ domain = self._create_new_domain(xml)
+ self.firewall_driver.apply_instance_filter(instance, network_info)
+
+ timer = utils.LoopingCall(self._wait_for_running, instance['name'])
+ return timer.start(interval=0.5, now=True)
+
+ def confirm_migration(self, migration, instance, network_info):
+ """Confirms a resize, destroying the source VM"""
+ self._cleanup_resize(instance)
+
class HostState(object):
"""Manages information about the compute node through libvirt"""
diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py
index 0b94a173f..080b58736 100644
--- a/nova/virt/libvirt/utils.py
+++ b/nova/virt/libvirt/utils.py
@@ -102,7 +102,8 @@ def get_disk_backing_file(path):
out, err = execute(FLAGS.qemu_img, 'info', path)
backing_file = [i.split('actual path:')[1].strip()[:-1]
for i in out.split('\n') if 0 <= i.find('backing file')]
- backing_file = os.path.basename(backing_file[0])
+ if backing_file:
+ backing_file = os.path.basename(backing_file[0])
return backing_file
diff --git a/nova/virt/vmwareapi/network_utils.py b/nova/virt/vmwareapi/network_utils.py
index fb1873224..8fbe02dc3 100644
--- a/nova/virt/vmwareapi/network_utils.py
+++ b/nova/virt/vmwareapi/network_utils.py
@@ -125,10 +125,10 @@ def get_vlanid_and_vswitch_for_portgroup(session, pg_name):
"get_dynamic_property", host_mor,
"HostSystem", "config.network.portgroup")
if not port_grps_on_host_ret:
- excep = ("ESX SOAP server returned an empty port group "
- "for the host system in its response")
+ excep = _("ESX SOAP server returned an empty port group "
+ "for the host system in its response")
LOG.exception(excep)
- raise exception.Error(_(excep))
+ raise exception.Error(excep)
port_grps_on_host = port_grps_on_host_ret.HostPortGroup
for p_gp in port_grps_on_host:
if p_gp.spec.name == pg_name:
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 7c419824a..1e2d11bb0 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -211,8 +211,9 @@ class XenAPIConnection(driver.ComputeDriver):
# TODO(Vek): Need to pass context in for access to auth_token
self._vmops.confirm_migration(migration, instance, network_info)
- def finish_revert_migration(self, instance):
+ def finish_revert_migration(self, instance, network_info):
"""Finish reverting a resize, powering back on the instance"""
+ # NOTE(vish): Xen currently does not use network info.
self._vmops.finish_revert_migration(instance)
def finish_migration(self, context, migration, instance, disk_info,
@@ -252,9 +253,10 @@ class XenAPIConnection(driver.ComputeDriver):
self._vmops.unpause(instance)
def migrate_disk_and_power_off(self, context, instance, dest,
- instance_type):
+ instance_type, network_info):
"""Transfers the VHD of a running instance to another host, then shuts
off the instance copies over the COW disk"""
+ # NOTE(vish): Xen currently does not use network info.
return self._vmops.migrate_disk_and_power_off(context, instance,
dest, instance_type)