summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2011-12-14 16:15:52 +0900
committerIsaku Yamahata <yamahata@valinux.co.jp>2012-01-12 18:46:49 +0900
commit932f3aafd1c735a8ec9e158a94ebb983d6baeb0e (patch)
treee167a00a6cbc64d31ff5f3c7a3a5b42d2c01306d /nova/api
parent6ece432be0cfb7356636806ab3c046eff17d494b (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.py65
-rw-r--r--nova/api/ec2/inst_state.py60
-rw-r--r--nova/api/openstack/common.py3
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',
},