diff options
| author | Isaku Yamahata <yamahata@valinux.co.jp> | 2011-12-14 16:15:52 +0900 |
|---|---|---|
| committer | Isaku Yamahata <yamahata@valinux.co.jp> | 2012-01-12 18:46:49 +0900 |
| commit | 932f3aafd1c735a8ec9e158a94ebb983d6baeb0e (patch) | |
| tree | e167a00a6cbc64d31ff5f3c7a3a5b42d2c01306d /nova/api | |
| parent | 6ece432be0cfb7356636806ab3c046eff17d494b (diff) | |
Unbreak start instance and fixes bug 905270
This patch fixes the bug 905270
https://bugs.launchpad.net/nova/+bug/905270
According to EC2 documentation, EBS-instances that initiated shutdown
result in stopped state. And then it can be started again. (On the
other hand non-EBS instance result in terminted when instance
initiated shutdown)
However, the current nova case, the shutdowned instance always results
in terminated status. As related issues are
- describe-instance-attribute instance_initiated_shutdown_behavior doesn't
work correctly
- instance attribute disable_api_termination isn't supported
- stop instance was broken by the change set of the following.
It needs unbreak.
> commit eb03d47fecd3bfc24243da29ee01679b334a08fe
> Author: Vishvananda Ishaya <vishvananda@gmail.com>
> Date: Fri Sep 23 09:22:32 2011 -0700
>
> Remove AoE, Clean up volume code
>
> * Removes Ata Over Ethernet
> * Adds drivers to libvirt for volumes
> * Adds initialize_connection and terminate_connection to volume api
> * Passes connection info back through volume api
>
> Change-Id: I1b1626f40bebe8466ab410fb174683293c7c474f
This patch
- unbreak start instance
- implement instance_initiated_shutdown_behavior and make it EC2 compatible
- implement disable_api_termination
---
Changes 5 -> 6:
- fixes to catch up 26b7b9457a5899ecca93fd67d3879efcad4e4968
Changes 4 -> 5:
- HACKING compilance
Changes 3 -> 4:
- rebased to 4c5586a28fd7a085369c49f6039876ffdc86b526
sqlalchemy migrate version
Changes 2 -> 3:
- rename long name to shorter one
s/instance_initiated_shutdown_behavior/shutdown_terminate/g
s/disable_api_termination/disable_terminate/g
as suggested Kevin L. Mitchell
- improved nova.api.ec2.cloud._state_description
- pep8
- broken out patches are available for easy review at
git://github.com/yamahata/nova.git lp905270-2
Changes 1 -> 2:
- fixed an unit test failure pointed out by Mark.
(I think ebtabls failure strongly suggests installation problem)
- introduce vm_states.SHUTOFF and put instance state which is in
power_state.{NOSTATE, SHUTOFF} into vm_states.SHUTOFF.
- simplified logic a bit by vm_states.SHUTOFF as suggested by Vish.
- instance_initiated_shutdown_behavior:String(255)
=>
instance_initiated_shutdown_terminate:Boolean()
as suggested by Vish.
- Added Johannes Erdfelt to reviews as they written the vm_states state
machine checker.
I'd have liked to add David Subiros either, but he doesn't seem to be a
registered user of the gerrit.
Change-Id: Ibeb94f65137feadad2c343913b39195e3f96a35e
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/cloud.py | 65 | ||||
| -rw-r--r-- | nova/api/ec2/inst_state.py | 60 | ||||
| -rw-r--r-- | nova/api/openstack/common.py | 3 |
3 files changed, 99 insertions, 29 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 01cf61860..9fcaf30d7 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -32,8 +32,10 @@ import urllib from nova.api.ec2 import ec2utils from nova.compute import instance_types +from nova.api.ec2 import inst_state from nova import block_device from nova import compute +from nova.compute import power_state from nova.compute import vm_states from nova import crypto from nova import db @@ -79,26 +81,35 @@ def _gen_key(context, user_id, key_name): # EC2 API can return the following values as documented in the EC2 API # http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ # ApiReference-ItemType-InstanceStateType.html -# pending | running | shutting-down | terminated | stopping | stopped +# pending 0 | running 16 | shutting-down 32 | terminated 48 | stopping 64 | +# stopped 80 _STATE_DESCRIPTION_MAP = { - None: 'pending', - vm_states.ACTIVE: 'running', - vm_states.BUILDING: 'pending', - vm_states.REBUILDING: 'pending', - vm_states.DELETED: 'terminated', - vm_states.SOFT_DELETE: 'terminated', - vm_states.STOPPED: 'stopped', - vm_states.MIGRATING: 'migrate', - vm_states.RESIZING: 'resize', - vm_states.PAUSED: 'pause', - vm_states.SUSPENDED: 'suspend', - vm_states.RESCUED: 'rescue', + None: inst_state.PENDING, + vm_states.ACTIVE: inst_state.RUNNING, + vm_states.BUILDING: inst_state.PENDING, + vm_states.REBUILDING: inst_state.PENDING, + vm_states.DELETED: inst_state.TERMINATED, + vm_states.SOFT_DELETE: inst_state.TERMINATED, + vm_states.STOPPED: inst_state.STOPPED, + vm_states.SHUTOFF: inst_state.SHUTOFF, + vm_states.MIGRATING: inst_state.MIGRATE, + vm_states.RESIZING: inst_state.RESIZE, + vm_states.PAUSED: inst_state.PAUSE, + vm_states.SUSPENDED: inst_state.SUSPEND, + vm_states.RESCUED: inst_state.RESCUE, } -def state_description_from_vm_state(vm_state): +def _state_description(vm_state, shutdown_terminate): """Map the vm state to the server status string""" - return _STATE_DESCRIPTION_MAP.get(vm_state, vm_state) + if (vm_state == vm_states.SHUTOFF and + not shutdown_terminate): + name = inst_state.STOPPED + else: + name = _STATE_DESCRIPTION_MAP.get(vm_state, vm_state) + + return {'code': inst_state.name_to_code(name), + 'name': name} def _parse_block_device_mapping(bdm): @@ -987,21 +998,17 @@ class CloudController(object): tmp['rootDeviceName'], result) def _format_attr_disable_api_termination(instance, result): - _unsupported_attribute(instance, result) + result['disableApiTermination'] = instance['disable_terminate'] def _format_attr_group_set(instance, result): CloudController._format_group_set(instance, result) def _format_attr_instance_initiated_shutdown_behavior(instance, result): - vm_state = instance['vm_state'] - state_to_value = { - vm_states.STOPPED: 'stopped', - vm_states.DELETED: 'terminated', - } - value = state_to_value.get(vm_state) - if value: - result['instanceInitiatedShutdownBehavior'] = value + if instance['shutdown_terminate']: + result['instanceInitiatedShutdownBehavior'] = 'terminate' + else: + result['instanceInitiatedShutdownBehavior'] = 'stop' def _format_attr_instance_type(instance, result): self._format_instance_type(instance, result) @@ -1157,9 +1164,8 @@ class CloudController(object): i['imageId'] = ec2utils.image_ec2_id(image_id) self._format_kernel_id(context, instance, i, 'kernelId') self._format_ramdisk_id(context, instance, i, 'ramdiskId') - i['instanceState'] = { - 'code': instance['power_state'], - 'name': state_description_from_vm_state(instance['vm_state'])} + i['instanceState'] = _state_description( + instance['vm_state'], instance['shutdown_terminate']) fixed_ip = None floating_ip = None @@ -1575,10 +1581,11 @@ class CloudController(object): vm_state = instance['vm_state'] # if the instance is in subtle state, refuse to proceed. - if vm_state not in (vm_states.ACTIVE, vm_states.STOPPED): + if vm_state not in (vm_states.ACTIVE, vm_states.SHUTOFF, + vm_states.STOPPED): raise exception.InstanceNotRunning(instance_id=ec2_instance_id) - if vm_state == vm_states.ACTIVE: + if vm_state in (vm_states.ACTIVE, vm_states.SHUTOFF): restart_instance = True self.compute_api.stop(context, instance_id=instance_id) diff --git a/nova/api/ec2/inst_state.py b/nova/api/ec2/inst_state.py new file mode 100644 index 000000000..68d18c8ad --- /dev/null +++ b/nova/api/ec2/inst_state.py @@ -0,0 +1,60 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Isaku Yamahata <yamahata at valinux co jp> +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +PENDING_CODE = 0 +RUNNING_CODE = 16 +SHUTTING_DOWN_CODE = 32 +TERMINATED_CODE = 48 +STOPPING_CODE = 64 +STOPPED_CODE = 80 + +PENDING = 'pending' +RUNNING = 'running' +SHUTTING_DOWN = 'shutting-down' +TERMINATED = 'terminated' +STOPPING = 'stopping' +STOPPED = 'stopped' + +# non-ec2 value +SHUTOFF = 'shutoff' +MIGRATE = 'migrate' +RESIZE = 'resize' +PAUSE = 'pause' +SUSPEND = 'suspend' +RESCUE = 'rescue' + +# EC2 API instance status code +_NAME_TO_CODE = { + PENDING: PENDING_CODE, + RUNNING: RUNNING_CODE, + SHUTTING_DOWN: SHUTTING_DOWN_CODE, + TERMINATED: TERMINATED_CODE, + STOPPING: STOPPING_CODE, + STOPPED: STOPPED_CODE, + + # approximation + SHUTOFF: TERMINATED_CODE, + MIGRATE: RUNNING_CODE, + RESIZE: RUNNING_CODE, + PAUSE: STOPPED_CODE, + SUSPEND: STOPPED_CODE, + RESCUE: RUNNING_CODE, +} + + +def name_to_code(name): + return _NAME_TO_CODE.get(name, PENDING_CODE) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index e96c42ac9..42acb4c56 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -57,6 +57,9 @@ _STATE_MAP = { vm_states.STOPPED: { 'default': 'STOPPED', }, + vm_states.SHUTOFF: { + 'default': 'SHUTOFF', + }, vm_states.MIGRATING: { 'default': 'MIGRATING', }, |
