summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]nova/compute/manager.py3
-rw-r--r--nova/conductor/api.py4
-rw-r--r--nova/network/manager.py6
-rw-r--r--nova/tests/api/ec2/test_cloud.py10
-rw-r--r--nova/tests/compute/test_compute.py5
-rw-r--r--nova/tests/conductor/test_conductor.py9
-rw-r--r--nova/tests/test_db_api.py14
-rw-r--r--nova/tests/test_hypervapi.py3
-rw-r--r--nova/tests/test_imagebackend.py9
-rw-r--r--nova/tests/test_libvirt.py6
-rw-r--r--nova/tests/test_virt_drivers.py10
-rw-r--r--nova/tests/test_vmwareapi.py9
-rw-r--r--nova/tests/test_xenapi.py10
-rwxr-xr-x[-rw-r--r--]nova/virt/baremetal/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/driver.py3
-rwxr-xr-x[-rw-r--r--]nova/virt/fake.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/hyperv/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/libvirt/driver.py64
-rwxr-xr-x[-rw-r--r--]nova/virt/libvirt/imagebackend.py23
-rwxr-xr-x[-rw-r--r--]nova/virt/powervm/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/vmwareapi/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/xenapi/driver.py2
-rwxr-xr-xtools/regression_tester.py67
23 files changed, 188 insertions, 79 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 60d72e565..bb4af94a6 100644..100755
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1483,7 +1483,8 @@ class ComputeManager(manager.SchedulerDependentManager):
context=context, instance=instance)
try:
- self.driver.reboot(instance, self._legacy_nw_info(network_info),
+ self.driver.reboot(context, instance,
+ self._legacy_nw_info(network_info),
reboot_type, block_device_info)
except Exception, exc:
LOG.error(_('Cannot reboot instance: %(exc)s'), locals(),
diff --git a/nova/conductor/api.py b/nova/conductor/api.py
index 16dd666f4..a30f8dffa 100644
--- a/nova/conductor/api.py
+++ b/nova/conductor/api.py
@@ -277,7 +277,7 @@ class LocalAPI(object):
def service_update(self, context, service, values):
return self._manager.service_update(context, service, values)
- def task_log_get(self, context, task_name, begin, end, host, state):
+ def task_log_get(self, context, task_name, begin, end, host, state=None):
return self._manager.task_log_get(context, task_name, begin, end,
host, state)
@@ -583,7 +583,7 @@ class API(object):
def service_update(self, context, service, values):
return self.conductor_rpcapi.service_update(context, service, values)
- def task_log_get(self, context, task_name, begin, end, host, state):
+ def task_log_get(self, context, task_name, begin, end, host, state=None):
return self.conductor_rpcapi.task_log_get(context, task_name, begin,
end, host, state)
diff --git a/nova/network/manager.py b/nova/network/manager.py
index b182613e2..f893768e7 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -1146,10 +1146,10 @@ class NetworkManager(manager.SchedulerDependentManager):
elif fixed_range:
network = self.db.network_get_by_cidr(elevated, fixed_range)
- if require_disassociated and network.project_id is not None:
+ if require_disassociated and network['project_id'] is not None:
raise ValueError(_('Network must be disassociated from project %s'
- ' before delete') % network.project_id)
- self.db.network_delete_safe(context, network.id)
+ ' before delete') % network['project_id'])
+ self.db.network_delete_safe(context, network['id'])
@property
def _bottom_reserved_ips(self): # pylint: disable=R0201
diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py
index ec0bd3743..f8219e7a0 100644
--- a/nova/tests/api/ec2/test_cloud.py
+++ b/nova/tests/api/ec2/test_cloud.py
@@ -713,10 +713,10 @@ class CloudTestCase(test.TestCase):
# Aggregate based zones
agg = db.aggregate_create(self.context,
{'name': 'agg1'}, {'availability_zone': 'zone1'})
- db.aggregate_host_add(self.context, agg.id, 'host1_zones')
+ db.aggregate_host_add(self.context, agg['id'], 'host1_zones')
agg = db.aggregate_create(self.context,
{'name': 'agg2'}, {'availability_zone': 'zone2'})
- db.aggregate_host_add(self.context, agg.id, 'host2_zones')
+ db.aggregate_host_add(self.context, agg['id'], 'host2_zones')
result = self.cloud.describe_availability_zones(self.context)
self.assertEqual(len(result['availabilityZoneInfo']), 3)
admin_ctxt = context.get_admin_context(read_deleted="no")
@@ -738,7 +738,7 @@ class CloudTestCase(test.TestCase):
'report_count': 0})
agg = db.aggregate_create(self.context,
{'name': 'agg1'}, {'availability_zone': 'second_zone'})
- db.aggregate_host_add(self.context, agg.id, 'host2_zones')
+ db.aggregate_host_add(self.context, agg['id'], 'host2_zones')
admin_ctxt = context.get_admin_context(read_deleted="no")
result = self.cloud.describe_availability_zones(admin_ctxt,
@@ -772,13 +772,13 @@ class CloudTestCase(test.TestCase):
'topic': "compute"})
agg = db.aggregate_create(self.context,
{'name': 'agg1'}, {'availability_zone': 'zone1'})
- db.aggregate_host_add(self.context, agg.id, 'host1')
+ db.aggregate_host_add(self.context, agg['id'], 'host1')
comp2 = db.service_create(self.context, {'host': 'host2',
'topic': "compute"})
agg2 = db.aggregate_create(self.context,
{'name': 'agg2'}, {'availability_zone': 'zone2'})
- db.aggregate_host_add(self.context, agg2.id, 'host2')
+ db.aggregate_host_add(self.context, agg2['id'], 'host2')
result = self.cloud.describe_instances(self.context)
result = result['reservationSet'][0]
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 1584cde34..442832553 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -1126,8 +1126,9 @@ class ComputeTestCase(BaseTestCase):
# this is called with the wrong args, so we have to hack
# around it.
reboot_call_info = {}
- expected_call_info = {'args': (updated_instance1, expected_nw_info,
- reboot_type, fake_block_dev_info),
+ expected_call_info = {'args': (econtext, updated_instance1,
+ expected_nw_info, reboot_type,
+ fake_block_dev_info),
'kwargs': {}}
def fake_reboot(*args, **kwargs):
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
index 773b65d43..08598b756 100644
--- a/nova/tests/conductor/test_conductor.py
+++ b/nova/tests/conductor/test_conductor.py
@@ -446,6 +446,15 @@ class _BaseTestCase(object):
'end', 'host', 'state')
self.assertEqual(result, 'result')
+ def test_task_log_get_with_no_state(self):
+ self.mox.StubOutWithMock(db, 'task_log_get')
+ db.task_log_get(self.context, 'task', 'begin', 'end',
+ 'host', None).AndReturn('result')
+ self.mox.ReplayAll()
+ result = self.conductor.task_log_get(self.context, 'task', 'begin',
+ 'end', 'host')
+ self.assertEqual(result, 'result')
+
def test_task_log_begin_task(self):
self.mox.StubOutWithMock(db, 'task_log_begin_task')
db.task_log_begin_task(self.context.elevated(), 'task', 'begin',
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py
index 5581e81ac..c6bf2941e 100644
--- a/nova/tests/test_db_api.py
+++ b/nova/tests/test_db_api.py
@@ -1238,7 +1238,7 @@ class AggregateDBApiTestCase(test.TestCase):
ctxt = context.get_admin_context()
result = _create_aggregate(context=ctxt, metadata={'availability_zone':
'fake_avail_zone'})
- self.assertEqual(result.availability_zone, 'fake_avail_zone')
+ self.assertEqual(result['availability_zone'], 'fake_avail_zone')
new_values = _get_fake_aggr_values()
new_values['availability_zone'] = 'different_avail_zone'
updated = db.aggregate_update(ctxt, 1, new_values)
@@ -1256,8 +1256,8 @@ class AggregateDBApiTestCase(test.TestCase):
updated = db.aggregate_get(ctxt, result['id'])
self.assertThat(values['metadata'],
matchers.DictMatches(expected))
- self.assertNotEqual(result.availability_zone,
- updated.availability_zone)
+ self.assertNotEqual(result['availability_zone'],
+ updated['availability_zone'])
def test_aggregate_update_with_existing_metadata(self):
ctxt = context.get_admin_context()
@@ -1335,10 +1335,10 @@ class AggregateDBApiTestCase(test.TestCase):
ctxt = context.get_admin_context()
result = _create_aggregate(context=ctxt, metadata={'availability_zone':
'fake_avail_zone'})
- db.aggregate_metadata_delete(ctxt, result.id, 'availability_zone')
- expected = db.aggregate_metadata_get(ctxt, result.id)
- aggregate = db.aggregate_get(ctxt, result.id)
- self.assertEquals(aggregate.availability_zone, None)
+ db.aggregate_metadata_delete(ctxt, result['id'], 'availability_zone')
+ expected = db.aggregate_metadata_get(ctxt, result['id'])
+ aggregate = db.aggregate_get(ctxt, result['id'])
+ self.assertEquals(aggregate['availability_zone'], None)
self.assertThat({}, matchers.DictMatches(expected))
def test_aggregate_metadata_delete_raise_not_found(self):
diff --git a/nova/tests/test_hypervapi.py b/nova/tests/test_hypervapi.py
index 3b624e6d1..0c2f90a4d 100644
--- a/nova/tests/test_hypervapi.py
+++ b/nova/tests/test_hypervapi.py
@@ -486,7 +486,8 @@ class HyperVAPITestCase(test.TestCase):
constants.HYPERV_VM_STATE_REBOOT)
self._mox.ReplayAll()
- self._conn.reboot(self._instance_data, network_info, None)
+ self._conn.reboot(self._context, self._instance_data, network_info,
+ None)
self._mox.VerifyAll()
def test_destroy(self):
diff --git a/nova/tests/test_imagebackend.py b/nova/tests/test_imagebackend.py
index 495e7c947..76fd1d5b6 100644
--- a/nova/tests/test_imagebackend.py
+++ b/nova/tests/test_imagebackend.py
@@ -55,8 +55,8 @@ class _ImageTestCase(object):
def test_cache(self):
self.mox.StubOutWithMock(os.path, 'exists')
- os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_DIR).AndReturn(False)
+ os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
fn = self.mox.CreateMockAnything()
fn(target=self.TEMPLATE_PATH)
@@ -72,7 +72,9 @@ class _ImageTestCase(object):
def test_cache_image_exists(self):
self.mox.StubOutWithMock(os.path, 'exists')
+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
os.path.exists(self.PATH).AndReturn(True)
+ os.path.exists(self.TEMPLATE_PATH).AndReturn(True)
self.mox.ReplayAll()
image = self.image_class(self.INSTANCE, self.NAME)
@@ -82,8 +84,8 @@ class _ImageTestCase(object):
def test_cache_base_dir_exists(self):
self.mox.StubOutWithMock(os.path, 'exists')
- os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
+ os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
fn = self.mox.CreateMockAnything()
fn(target=self.TEMPLATE_PATH)
@@ -98,8 +100,8 @@ class _ImageTestCase(object):
def test_cache_template_exists(self):
self.mox.StubOutWithMock(os.path, 'exists')
- os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
+ os.path.exists(self.PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(True)
fn = self.mox.CreateMockAnything()
self.mox.ReplayAll()
@@ -195,7 +197,6 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
def test_create_image_with_size(self):
fn = self.prepare_mocks()
fn(target=self.TEMPLATE_PATH)
- self.mox.StubOutWithMock(os.path, 'exists')
imagebackend.libvirt_utils.create_cow_image(self.TEMPLATE_PATH,
self.PATH)
imagebackend.disk.extend(self.PATH, self.SIZE)
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 52e308b85..4b9a4eb7c 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -2330,7 +2330,7 @@ class LibvirtConnTestCase(test.TestCase):
migrate_data)
self.assertEqual(ret, None)
self.assertTrue(os.path.exists('%s/%s/' %
- (tmpdir, inst_ref.name)))
+ (tmpdir, inst_ref['name'])))
db.instance_destroy(self.context, inst_ref['uuid'])
def test_pre_block_migration_works_correctly(self):
@@ -4206,7 +4206,7 @@ class LibvirtDriverTestCase(test.TestCase):
self.counter = 0
- def fake_get_instance_disk_info(instance):
+ def fake_get_instance_disk_info(instance, xml=None):
return '[]'
def fake_destroy(instance):
@@ -4251,7 +4251,7 @@ class LibvirtDriverTestCase(test.TestCase):
'disk_size':'83886080'}]
disk_info_text = jsonutils.dumps(disk_info)
- def fake_get_instance_disk_info(instance):
+ def fake_get_instance_disk_info(instance, xml=None):
return disk_info_text
def fake_destroy(instance):
diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py
index 29c7f9959..67452bc24 100644
--- a/nova/tests/test_virt_drivers.py
+++ b/nova/tests/test_virt_drivers.py
@@ -104,6 +104,13 @@ class _FakeDriverBackendTestCase(object):
def fake_make_drive(_self, _path):
pass
+ def fake_get_instance_disk_info(_self, instance, xml=None):
+ return '[]'
+
+ self.stubs.Set(nova.virt.libvirt.driver.LibvirtDriver,
+ 'get_instance_disk_info',
+ fake_get_instance_disk_info)
+
self.stubs.Set(nova.virt.libvirt.driver.disk,
'extend', fake_extend)
@@ -227,7 +234,8 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
def test_reboot(self):
reboot_type = "SOFT"
instance_ref, network_info = self._get_running_instance()
- self.connection.reboot(instance_ref, network_info, reboot_type)
+ self.connection.reboot(self.ctxt, instance_ref, network_info,
+ reboot_type)
@catch_notimplementederror
def test_get_host_ip_addr(self):
diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py
index 34f03a555..22544fd2d 100644
--- a/nova/tests/test_vmwareapi.py
+++ b/nova/tests/test_vmwareapi.py
@@ -199,14 +199,16 @@ class VMwareAPIVMTestCase(test.TestCase):
info = self.conn.get_info({'name': 1})
self._check_vm_info(info, power_state.RUNNING)
reboot_type = "SOFT"
- self.conn.reboot(self.instance, self.network_info, reboot_type)
+ self.conn.reboot(self.context, self.instance, self.network_info,
+ reboot_type)
info = self.conn.get_info({'name': 1})
self._check_vm_info(info, power_state.RUNNING)
def test_reboot_non_existent(self):
self._create_instance_in_the_db()
self.assertRaises(exception.InstanceNotFound, self.conn.reboot,
- self.instance, self.network_info, 'SOFT')
+ self.context, self.instance, self.network_info,
+ 'SOFT')
def test_reboot_not_poweredon(self):
self._create_vm()
@@ -216,7 +218,8 @@ class VMwareAPIVMTestCase(test.TestCase):
info = self.conn.get_info({'name': 1})
self._check_vm_info(info, power_state.SUSPENDED)
self.assertRaises(exception.InstanceRebootFailure, self.conn.reboot,
- self.instance, self.network_info, 'SOFT')
+ self.context, self.instance, self.network_info,
+ 'SOFT')
def test_suspend(self):
self._create_vm()
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 9285da2b2..cc71ba31e 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -955,12 +955,12 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
def test_reboot_hard(self):
instance = self._create_instance()
conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
- conn.reboot(instance, None, "HARD")
+ conn.reboot(self.context, instance, None, "HARD")
def test_reboot_soft(self):
instance = self._create_instance()
conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
- conn.reboot(instance, None, "SOFT")
+ conn.reboot(self.context, instance, None, "SOFT")
def test_reboot_halted(self):
session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass',
@@ -968,7 +968,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
instance = self._create_instance(spawn=False)
conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
xenapi_fake.create_vm(instance['name'], 'Halted')
- conn.reboot(instance, None, "SOFT")
+ conn.reboot(self.context, instance, None, "SOFT")
vm_ref = vm_utils.lookup(session, instance['name'])
vm = xenapi_fake.get_record('VM', vm_ref)
self.assertEquals(vm['power_state'], 'Running')
@@ -977,8 +977,8 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
instance = self._create_instance(spawn=False)
conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
xenapi_fake.create_vm(instance['name'], 'Unknown')
- self.assertRaises(xenapi_fake.Failure, conn.reboot, instance,
- None, "SOFT")
+ self.assertRaises(xenapi_fake.Failure, conn.reboot, self.context,
+ instance, None, "SOFT")
def _test_maintenance_mode(self, find_host, find_aggregate):
real_call_xenapi = self.conn._session.call_xenapi
diff --git a/nova/virt/baremetal/driver.py b/nova/virt/baremetal/driver.py
index 43af951fd..9160485a6 100644..100755
--- a/nova/virt/baremetal/driver.py
+++ b/nova/virt/baremetal/driver.py
@@ -271,7 +271,7 @@ class BareMetalDriver(driver.ComputeDriver):
LOG.warning(_("Failed to update state record for "
"baremetal node %s") % instance['uuid'])
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
node = _get_baremetal_node_by_instance_uuid(instance['uuid'])
ctx = nova_context.get_admin_context()
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 747b60714..ba0dfbafe 100644..100755
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -239,7 +239,7 @@ class ComputeDriver(object):
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot the specified instance.
@@ -254,7 +254,6 @@ class ComputeDriver(object):
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
:param reboot_type: Either a HARD or SOFT reboot
"""
- # TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
def get_console_pool_info(self, console_type):
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 5a5bb7b13..30a5fc758 100644..100755
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -129,7 +129,7 @@ class FakeDriver(driver.ComputeDriver):
raise exception.InstanceNotRunning(instance_id=instance['uuid'])
update_task_state(task_state=task_states.IMAGE_UPLOADING)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
pass
diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py
index e8bf8c416..4af3b8b05 100644..100755
--- a/nova/virt/hyperv/driver.py
+++ b/nova/virt/hyperv/driver.py
@@ -52,7 +52,7 @@ class HyperVDriver(driver.ComputeDriver):
self._vmops.spawn(context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
self._vmops.reboot(instance, network_info, reboot_type)
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 666eb66f3..cf926a14c 100644..100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -957,7 +957,7 @@ class LibvirtDriver(driver.ComputeDriver):
libvirt_utils.extract_snapshot(disk_delta, 'qcow2', None,
out_path, image_format)
- def reboot(self, instance, network_info, reboot_type='SOFT',
+ def reboot(self, context, instance, network_info, reboot_type='SOFT',
block_device_info=None):
"""Reboot a virtual machine, given an instance reference."""
if reboot_type == 'SOFT':
@@ -969,7 +969,8 @@ class LibvirtDriver(driver.ComputeDriver):
else:
LOG.warn(_("Failed to soft reboot instance."),
instance=instance)
- return self._hard_reboot(instance, network_info, block_device_info)
+ return self._hard_reboot(context, instance, network_info,
+ block_device_info)
def _soft_reboot(self, instance):
"""Attempt to shutdown and restart the instance gracefully.
@@ -1015,7 +1016,8 @@ class LibvirtDriver(driver.ComputeDriver):
greenthread.sleep(1)
return False
- def _hard_reboot(self, instance, network_info, block_device_info=None):
+ def _hard_reboot(self, context, instance, network_info,
+ block_device_info=None):
"""Reboot a virtual machine, given an instance reference.
Performs a Libvirt reset (if supported) on the domain.
@@ -1035,6 +1037,13 @@ class LibvirtDriver(driver.ComputeDriver):
xml = self.to_xml(instance, network_info, disk_info,
block_device_info=block_device_info,
write_to_disk=True)
+
+ # NOTE (rmk): Re-populate any missing backing files.
+ disk_info_json = self.get_instance_disk_info(instance['name'], xml)
+ self._create_images_and_backing(context, instance, disk_info_json)
+
+ # Initialize all the necessary networking, block devices and
+ # start the instance.
self._create_domain_and_network(xml, instance, network_info,
block_device_info)
@@ -1103,7 +1112,7 @@ class LibvirtDriver(driver.ComputeDriver):
# Instance is not up and could be in an unknown state.
# Be as absolute as possible about getting it back into
# a known and running state.
- self._hard_reboot(instance, network_info, block_device_info)
+ self._hard_reboot(context, instance, network_info, block_device_info)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
@@ -2834,8 +2843,17 @@ class LibvirtDriver(driver.ComputeDriver):
greenthread.sleep(1)
def pre_block_migration(self, ctxt, instance, disk_info_json):
- """Preparation block migration.
+ """Preparation for block migration."""
+ # NOTE (rmk): When preparing for a block migration, the instance dir
+ # should not exist on the destination hypervisor.
+ instance_dir = libvirt_utils.get_instance_path(instance)
+ if os.path.exists(instance_dir):
+ raise exception.DestinationDiskExists(path=instance_dir)
+ os.mkdir(instance_dir)
+ self._create_images_and_backing(ctxt, instance, disk_info_json)
+ def _create_images_and_backing(self, ctxt, instance, disk_info_json):
+ """
:params ctxt: security context
:params instance:
nova.db.sqlalchemy.models.Instance object
@@ -2845,19 +2863,14 @@ class LibvirtDriver(driver.ComputeDriver):
"""
disk_info = jsonutils.loads(disk_info_json)
-
- # make instance directory
instance_dir = libvirt_utils.get_instance_path(instance)
- if os.path.exists(instance_dir):
- raise exception.DestinationDiskExists(path=instance_dir)
- os.mkdir(instance_dir)
for info in disk_info:
base = os.path.basename(info['path'])
# Get image type and create empty disk image, and
# create backing file in case of qcow2.
instance_disk = os.path.join(instance_dir, base)
- if not info['backing_file']:
+ if not info['backing_file'] and not os.path.exists(instance_disk):
libvirt_utils.create_image(info['type'], instance_disk,
info['disk_size'])
else:
@@ -2910,10 +2923,9 @@ class LibvirtDriver(driver.ComputeDriver):
dom = self._lookup_by_name(instance_ref["name"])
self._conn.defineXML(dom.XMLDesc(0))
- def get_instance_disk_info(self, instance_name):
+ def get_instance_disk_info(self, instance_name, xml=None):
"""Preparation block migration.
- :params ctxt: security context
:params instance_ref:
nova.db.sqlalchemy.models.Instance object
instance object that is migrated.
@@ -2926,18 +2938,22 @@ class LibvirtDriver(driver.ComputeDriver):
'disk_size':'83886080'},...]"
"""
- disk_info = []
+ # NOTE (rmk): Passing the domain XML into this function is optional.
+ # When it is not passed, we attempt to extract it from
+ # the pre-existing definition.
+ if xml is None:
+ try:
+ virt_dom = self._lookup_by_name(instance_name)
+ xml = virt_dom.XMLDesc(0)
+ except libvirt.libvirtError as ex:
+ error_code = ex.get_error_code()
+ msg = _("Error from libvirt while getting description of "
+ "%(instance_name)s: [Error Code %(error_code)s] "
+ "%(ex)s") % locals()
+ LOG.warn(msg)
+ raise exception.InstanceNotFound(instance_id=instance_name)
- virt_dom = self._lookup_by_name(instance_name)
- try:
- xml = virt_dom.XMLDesc(0)
- except libvirt.libvirtError as ex:
- error_code = ex.get_error_code()
- msg = _("Error from libvirt while getting description of "
- "%(instance_name)s: [Error Code %(error_code)s] "
- "%(ex)s") % locals()
- LOG.warn(msg)
- raise exception.InstanceNotFound(instance_id=instance_name)
+ disk_info = []
doc = etree.fromstring(xml)
disk_nodes = doc.findall('.//devices/disk')
path_nodes = doc.findall('.//devices/disk/source')
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 0815c142f..0d5e8cb66 100644..100755
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -120,12 +120,12 @@ class Image(object):
if not os.path.exists(target):
fetch_func(target=target, *args, **kwargs)
- if not os.path.exists(self.path):
- base_dir = os.path.join(CONF.instances_path, CONF.base_dir_name)
- if not os.path.exists(base_dir):
- fileutils.ensure_tree(base_dir)
- base = os.path.join(base_dir, filename)
+ base_dir = os.path.join(CONF.instances_path, CONF.base_dir_name)
+ if not os.path.exists(base_dir):
+ fileutils.ensure_tree(base_dir)
+ base = os.path.join(base_dir, filename)
+ if not os.path.exists(self.path) or not os.path.exists(base):
self.create_image(call_if_not_exists, base, size,
*args, **kwargs)
@@ -160,8 +160,9 @@ class Raw(Image):
prepare_template(target=self.path, *args, **kwargs)
else:
prepare_template(target=base, *args, **kwargs)
- with utils.remove_path_on_error(self.path):
- copy_raw_image(base, self.path, size)
+ if not os.path.exists(self.path):
+ with utils.remove_path_on_error(self.path):
+ copy_raw_image(base, self.path, size)
def snapshot(self, name):
return snapshots.RawSnapshot(self.path, name)
@@ -183,9 +184,11 @@ class Qcow2(Image):
if size:
disk.extend(target, size)
- prepare_template(target=base, *args, **kwargs)
- with utils.remove_path_on_error(self.path):
- copy_qcow2_image(base, self.path, size)
+ if not os.path.exists(base):
+ prepare_template(target=base, *args, **kwargs)
+ if not os.path.exists(self.path):
+ with utils.remove_path_on_error(self.path):
+ copy_qcow2_image(base, self.path, size)
def snapshot(self, name):
return snapshots.Qcow2Snapshot(self.path, name)
diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py
index baf9bf12d..dd0f473a6 100644..100755
--- a/nova/virt/powervm/driver.py
+++ b/nova/virt/powervm/driver.py
@@ -101,7 +101,7 @@ class PowerVMDriver(driver.ComputeDriver):
"""Destroy (shutdown and delete) the specified instance."""
self._powervm.destroy(instance['name'], destroy_disks)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot the specified instance.
diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py
index 3e9269530..19f984c7d 100644..100755
--- a/nova/virt/vmwareapi/driver.py
+++ b/nova/virt/vmwareapi/driver.py
@@ -180,7 +180,7 @@ class VMwareESXDriver(driver.ComputeDriver):
"""Create snapshot from a running VM instance."""
self._vmops.snapshot(context, instance, name, update_task_state)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, network_info)
diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py
index 46b759f43..c1a578f3b 100644..100755
--- a/nova/virt/xenapi/driver.py
+++ b/nova/virt/xenapi/driver.py
@@ -193,7 +193,7 @@ class XenAPIDriver(driver.ComputeDriver):
"""Create snapshot from a running VM instance."""
self._vmops.snapshot(context, instance, image_id, update_task_state)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, reboot_type)
diff --git a/tools/regression_tester.py b/tools/regression_tester.py
new file mode 100755
index 000000000..554260fbd
--- /dev/null
+++ b/tools/regression_tester.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+
+"""Tool for checking if patch contains a regression test.
+
+Pass in gerrit review number as parameter, tool will download branch and run
+modified tests without bug fix.
+"""
+
+import string
+import subprocess
+import sys
+
+#TODO(jogo) use proper optParser
+gerrit_number = sys.argv[1]
+
+
+def run(cmd, fail_ok=False):
+ print "running: %s" % cmd
+ try:
+ rval = subprocess.check_output(cmd, shell=True)
+ except subprocess.CalledProcessError:
+ if not fail_ok:
+ print "the above command terminated with an error"
+ sys.exit(1)
+ pass
+ return rval
+
+
+test_works = False
+
+original_branch = run("git rev-parse --abbrev-ref HEAD")
+run("git review -d %s" % gerrit_number)
+# run new tests with old code
+run("git checkout HEAD^ nova")
+run("git checkout HEAD nova/tests")
+
+# identify which tests have changed
+tests = run("git whatchanged --format=oneline -1 | grep \"nova/tests\" "
+ "| cut -f2").split()
+test_list = []
+for test in tests:
+ test_list.append(string.replace(test[0:-3], '/', '.'))
+
+# run new tests, expect them to fail
+expect_failure = run(("tox -epy27 %s 2>&1" % string.join(test_list)),
+ fail_ok=True)
+if "FAILED (id=" in expect_failure:
+ test_works = True
+
+# cleanup
+run("git checkout HEAD nova")
+new_branch = run("git status | head -1 | cut -d ' ' -f 4")
+run("git checkout %s" % original_branch)
+run("git branch -D %s" % new_branch)
+
+
+if test_works:
+ print expect_failure
+ print ""
+ print "*******************************"
+ print "SUCCESS: test covers regression"
+else:
+ print expect_failure
+ print ""
+ print "***************************************"
+ print "FAILURE: test does not cover regression"
+ sys.exit(1)