Merge "Cleans up power_off and power_on semantics"

This commit is contained in:
Jenkins
2012-06-07 15:36:40 +00:00
committed by Gerrit Code Review
7 changed files with 101 additions and 86 deletions
+10 -23
View File
@@ -967,7 +967,6 @@ class API(base.Base):
if instance['host']:
self.update(context,
instance,
vm_state=vm_states.SOFT_DELETE,
task_state=task_states.POWERING_OFF,
deleted_at=utils.utcnow())
@@ -1047,15 +1046,18 @@ class API(base.Base):
@check_instance_state(vm_state=[vm_states.SOFT_DELETE])
def restore(self, context, instance):
"""Restore a previously deleted (but not reclaimed) instance."""
self.update(context,
instance,
vm_state=vm_states.ACTIVE,
task_state=None,
deleted_at=None)
if instance['host']:
self.update(context, instance, task_state=task_states.POWERING_ON)
self.update(context,
instance,
task_state=task_states.POWERING_ON,
deleted_at=None)
self.compute_rpcapi.power_on_instance(context, instance)
else:
self.update(context,
instance,
vm_state=vm_states.ACTIVE,
task_state=None,
deleted_at=None)
@wrap_check_policy
@check_instance_state(vm_state=[vm_states.SOFT_DELETE])
@@ -1074,9 +1076,7 @@ class API(base.Base):
self.update(context,
instance,
vm_state=vm_states.ACTIVE,
task_state=task_states.STOPPING,
terminated_at=utils.utcnow(),
progress=0)
self.compute_rpcapi.stop_instance(context, instance, cast=do_cast)
@@ -1085,23 +1085,10 @@ class API(base.Base):
@check_instance_state(vm_state=[vm_states.STOPPED, vm_states.SHUTOFF])
def start(self, context, instance):
"""Start an instance."""
vm_state = instance["vm_state"]
instance_uuid = instance["uuid"]
LOG.debug(_("Going to try to start instance"), instance=instance)
if vm_state == vm_states.SHUTOFF:
if instance['shutdown_terminate']:
LOG.warning(_("Instance %(instance_uuid)s is not "
"stopped. (%(vm_state)s") % locals())
return
# NOTE(yamahata): nova compute doesn't reap instances
# which initiated shutdown itself. So reap it here.
self.stop(context, instance, do_cast=False)
self.update(context,
instance,
vm_state=vm_states.STOPPED,
task_state=task_states.STARTING)
# TODO(yamahata): injected_files isn't supported right now.
+22 -29
View File
@@ -701,24 +701,10 @@ class ComputeManager(manager.SchedulerDependentManager):
self._run_instance(context, instance_uuid, **kwargs)
do_run_instance()
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@checks_instance_lock
@wrap_instance_fault
def start_instance(self, context, instance_uuid):
@utils.synchronized(instance_uuid)
def do_start_instance():
"""Starting an instance on this host."""
# TODO(yamahata): injected_files isn't supported.
# Anyway OSAPI doesn't support stop/start yet
# FIXME(vish): I've kept the files during stop instance, but
# I think start will fail due to the files still
self._run_instance(context, instance_uuid)
do_start_instance()
def _shutdown_instance(self, context, instance, action_str):
def _shutdown_instance(self, context, instance):
"""Shutdown an instance on this host."""
context = context.elevated()
LOG.audit(_('%(action_str)s instance') % {'action_str': action_str},
LOG.audit(_('%(action_str)s instance') % {'action_str': 'Terminating'},
context=context, instance=instance)
self._notify_about_instance_usage(context, instance, "shutdown.start")
@@ -765,7 +751,7 @@ class ComputeManager(manager.SchedulerDependentManager):
"""Delete an instance on this host."""
instance_uuid = instance['uuid']
self._notify_about_instance_usage(context, instance, "delete.start")
self._shutdown_instance(context, instance, 'Terminating')
self._shutdown_instance(context, instance)
self._cleanup_volumes(context, instance_uuid)
instance = self._instance_update(context,
instance_uuid,
@@ -804,21 +790,26 @@ class ComputeManager(manager.SchedulerDependentManager):
@checks_instance_lock
@wrap_instance_fault
def stop_instance(self, context, instance_uuid):
"""Stopping an instance on this host."""
@utils.synchronized(instance_uuid)
def do_stop_instance():
instance = self.db.instance_get_by_uuid(context, instance_uuid)
self._shutdown_instance(context, instance, 'Stopping')
self._instance_update(context,
instance_uuid,
vm_state=vm_states.STOPPED,
task_state=None)
do_stop_instance()
"""Stopping an instance on this host.
Alias for power_off_instance for compatibility"""
self.power_off_instance(context, instance_uuid,
final_state=vm_states.STOPPED)
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@checks_instance_lock
@wrap_instance_fault
def power_off_instance(self, context, instance_uuid):
def start_instance(self, context, instance_uuid):
"""Starting an instance on this host.
Alias for power_on_instance for compatibility"""
self.power_on_instance(context, instance_uuid)
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
@checks_instance_lock
@wrap_instance_fault
def power_off_instance(self, context, instance_uuid,
final_state=vm_states.SOFT_DELETE):
"""Power off an instance on this host."""
instance = self.db.instance_get_by_uuid(context, instance_uuid)
self._notify_about_instance_usage(context, instance, "power_off.start")
@@ -827,6 +818,7 @@ class ComputeManager(manager.SchedulerDependentManager):
self._instance_update(context,
instance_uuid,
power_state=current_power_state,
vm_state=final_state,
task_state=None)
self._notify_about_instance_usage(context, instance, "power_off.end")
@@ -842,6 +834,7 @@ class ComputeManager(manager.SchedulerDependentManager):
self._instance_update(context,
instance_uuid,
power_state=current_power_state,
vm_state=vm_states.ACTIVE,
task_state=None)
self._notify_about_instance_usage(context, instance, "power_on.end")
@@ -2579,7 +2572,7 @@ class ComputeManager(manager.SchedulerDependentManager):
"'%(name)s' which is marked as "
"DELETED but still present on host."),
locals(), instance=instance)
self._shutdown_instance(context, instance, 'Terminating')
self._shutdown_instance(context, instance)
self._cleanup_volumes(context, instance['uuid'])
else:
raise Exception(_("Unrecognized value '%(action)s'"
+5 -5
View File
@@ -1968,9 +1968,10 @@ class CloudTestCase(test.TestCase):
self.assertTrue(result)
vol = db.volume_get(self.context, vol1['id'])
self._assert_volume_detached(vol)
self._assert_volume_attached(vol, instance_uuid, '/dev/vdb')
vol = db.volume_get(self.context, vol2['id'])
self._assert_volume_detached(vol)
self._assert_volume_attached(vol, instance_uuid, '/dev/vdc')
self.cloud.start_instances(self.context, [ec2_instance_id])
vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
@@ -2039,9 +2040,8 @@ class CloudTestCase(test.TestCase):
result = self.cloud.stop_instances(self.context, [ec2_instance_id])
self.assertTrue(result)
for vol_id in (vol1['id'], vol2['id']):
vol = db.volume_get(self.context, vol_id)
self._assert_volume_detached(vol)
vol = db.volume_get(self.context, vol2['id'])
self._assert_volume_attached(vol, instance_uuid, '/dev/vdc')
self.cloud.start_instances(self.context, [ec2_instance_id])
vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
+20 -20
View File
@@ -445,7 +445,7 @@ class ComputeTestCase(BaseTestCase):
def fake_driver_power_on(self, instance):
called['power_on'] = True
self.stubs.Set(nova.virt.driver.ComputeDriver, 'power_on',
self.stubs.Set(nova.virt.fake.FakeDriver, 'power_on',
fake_driver_power_on)
instance = self._create_fake_instance()
@@ -463,7 +463,7 @@ class ComputeTestCase(BaseTestCase):
def fake_driver_power_off(self, instance):
called['power_off'] = True
self.stubs.Set(nova.virt.driver.ComputeDriver, 'power_off',
self.stubs.Set(nova.virt.fake.FakeDriver, 'power_off',
fake_driver_power_off)
instance = self._create_fake_instance()
@@ -1700,8 +1700,8 @@ class ComputeTestCase(BaseTestCase):
).AndReturn([instance])
self.mox.StubOutWithMock(self.compute, "_shutdown_instance")
self.compute._shutdown_instance(admin_context, instance,
'Terminating').AndReturn(None)
self.compute._shutdown_instance(admin_context,
instance).AndReturn(None)
self.mox.StubOutWithMock(self.compute, "_cleanup_volumes")
self.compute._cleanup_volumes(admin_context,
@@ -2256,13 +2256,8 @@ class ComputeAPITestCase(BaseTestCase):
check_state(instance_uuid, power_state.NOSTATE, vm_states.SHUTOFF,
None)
start_check_state(instance_uuid,
power_state.NOSTATE, vm_states.SHUTOFF, None)
db.instance_update(self.context, instance_uuid,
{'shutdown_terminate': False})
start_check_state(instance_uuid, power_state.NOSTATE,
vm_states.STOPPED, task_states.STARTING)
vm_states.SHUTOFF, task_states.STARTING)
db.instance_destroy(self.context, instance['id'])
@@ -2338,6 +2333,10 @@ class ComputeAPITestCase(BaseTestCase):
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
# set the state that the instance gets when soft_delete finishes
instance = db.instance_update(self.context, instance['uuid'],
{'vm_state': vm_states.SOFT_DELETE})
self.compute_api.force_delete(self.context, instance)
instance = db.instance_get_by_uuid(self.context, instance_uuid)
@@ -2402,9 +2401,8 @@ class ComputeAPITestCase(BaseTestCase):
self.compute.pause_instance(self.context, instance_uuid)
# set the state that the instance gets when pause finishes
db.instance_update(self.context, instance['uuid'],
instance = db.instance_update(self.context, instance['uuid'],
{'vm_state': vm_states.PAUSED})
instance = db.instance_get_by_uuid(self.context, instance['uuid'])
self.compute_api.unpause(self.context, instance)
@@ -2425,6 +2423,10 @@ class ComputeAPITestCase(BaseTestCase):
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
# set the state that the instance gets when soft_delete finishes
instance = db.instance_update(self.context, instance['uuid'],
{'vm_state': vm_states.SOFT_DELETE})
self.compute_api.restore(self.context, instance)
instance = db.instance_get_by_uuid(self.context, instance_uuid)
@@ -2766,10 +2768,9 @@ class ComputeAPITestCase(BaseTestCase):
{'instance_uuid': instance['uuid'],
'status': 'finished'})
# set the state that the instance gets when resize finishes
db.instance_update(self.context, instance['uuid'],
{'task_state': task_states.RESIZE_VERIFY,
'vm_state': vm_states.ACTIVE})
instance = db.instance_get_by_uuid(context, instance['uuid'])
instance = db.instance_update(self.context, instance['uuid'],
{'task_state': task_states.RESIZE_VERIFY,
'vm_state': vm_states.ACTIVE})
self.compute_api.confirm_resize(context, instance)
self.compute.terminate_instance(context, instance['uuid'])
@@ -2787,10 +2788,9 @@ class ComputeAPITestCase(BaseTestCase):
{'instance_uuid': instance['uuid'],
'status': 'finished'})
# set the state that the instance gets when resize finishes
db.instance_update(self.context, instance['uuid'],
{'task_state': task_states.RESIZE_VERIFY,
'vm_state': vm_states.ACTIVE})
instance = db.instance_get_by_uuid(context, instance['uuid'])
instance = db.instance_update(self.context, instance['uuid'],
{'task_state': task_states.RESIZE_VERIFY,
'vm_state': vm_states.ACTIVE})
self.compute_api.revert_resize(context, instance)
+16
View File
@@ -176,6 +176,22 @@ class _VirtDriverTestCase(test.TestCase):
self.ctxt, instance_ref, 'dest_host', instance_type_ref,
network_info)
@catch_notimplementederror
def test_power_off(self):
instance_ref, network_info = self._get_running_instance()
self.connection.power_off(instance_ref)
@catch_notimplementederror
def test_test_power_on_running(self):
instance_ref, network_info = self._get_running_instance()
self.connection.power_on(instance_ref)
@catch_notimplementederror
def test_test_power_on_powered_off(self):
instance_ref, network_info = self._get_running_instance()
self.connection.power_off(instance_ref)
self.connection.power_on(instance_ref)
@catch_notimplementederror
def test_pause(self):
instance_ref, network_info = self._get_running_instance()
+6
View File
@@ -139,6 +139,12 @@ class FakeDriver(driver.ComputeDriver):
def finish_revert_migration(self, instance, network_info):
pass
def power_off(self, instance):
pass
def power_on(self, instance):
pass
def pause(self, instance):
pass
+22 -9
View File
@@ -718,7 +718,7 @@ class LibvirtDriver(driver.ComputeDriver):
finally:
libvirt_utils.delete_snapshot(disk_path, snapshot_name)
if state == power_state.RUNNING:
virt_dom.create()
self._create_domain(domain=virt_dom)
# Upload that image to the image service
with libvirt_utils.file_open(out_path) as image_file:
@@ -770,7 +770,7 @@ class LibvirtDriver(driver.ComputeDriver):
power_state.CRASHED]:
LOG.info(_("Instance shutdown successfully."),
instance=instance)
dom.create()
self._create_domain(domain=dom)
timer = utils.LoopingCall(self._wait_for_running, instance)
return timer.start(interval=0.5)
greenthread.sleep(1)
@@ -808,26 +808,39 @@ class LibvirtDriver(driver.ComputeDriver):
@exception.wrap_exception()
def pause(self, instance):
"""Pause VM instance"""
dom = self._lookup_by_name(instance.name)
dom = self._lookup_by_name(instance['name'])
dom.suspend()
@exception.wrap_exception()
def unpause(self, instance):
"""Unpause paused VM instance"""
dom = self._lookup_by_name(instance.name)
dom = self._lookup_by_name(instance['name'])
dom.resume()
@exception.wrap_exception()
def power_off(self, instance):
"""Power off the specified instance"""
self._destroy(instance)
@exception.wrap_exception()
def power_on(self, instance):
"""Power on the specified instance"""
dom = self._lookup_by_name(instance['name'])
self._create_domain(domain=dom)
timer = utils.LoopingCall(self._wait_for_running, instance)
return timer.start(interval=0.5)
@exception.wrap_exception()
def suspend(self, instance):
"""Suspend the specified instance"""
dom = self._lookup_by_name(instance.name)
dom = self._lookup_by_name(instance['name'])
dom.managedSave(0)
@exception.wrap_exception()
def resume(self, instance):
"""resume the specified instance"""
dom = self._lookup_by_name(instance.name)
dom.create()
dom = self._lookup_by_name(instance['name'])
self._create_domain(domain=dom)
@exception.wrap_exception()
def resume_state_on_host_boot(self, context, instance, network_info):
@@ -2262,7 +2275,7 @@ class LibvirtDriver(driver.ComputeDriver):
post_method(ctxt, instance_ref, dest, block_migration)
timer.f = wait_for_live_migration
timer.start(interval=0.5)
return timer.start(interval=0.5)
def pre_live_migration(self, block_device_info):
"""Preparation live migration.
@@ -2514,7 +2527,7 @@ class LibvirtDriver(driver.ComputeDriver):
disk_info_text = self.get_instance_disk_info(instance['name'])
disk_info = jsonutils.loads(disk_info_text)
self._destroy(instance)
self.power_off(instance)
# copy disks to destination
# if disk type is qcow2, convert to raw then send to dest.