summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/cloud.py50
-rw-r--r--nova/api/openstack/common.py78
-rw-r--r--nova/api/openstack/servers.py22
-rw-r--r--nova/api/openstack/views/servers.py13
4 files changed, 103 insertions, 60 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 9aebf92e3..fe44191c8 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -47,6 +47,7 @@ from nova import utils
from nova import volume
from nova.api.ec2 import ec2utils
from nova.compute import instance_types
+from nova.compute import vm_states
from nova.image import s3
@@ -78,6 +79,30 @@ def _gen_key(context, user_id, key_name):
return {'private_key': private_key, 'fingerprint': fingerprint}
+# 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
+_STATE_DESCRIPTION_MAP = {
+ None: 'pending',
+ vm_states.ACTIVE: 'running',
+ vm_states.BUILDING: 'pending',
+ vm_states.REBUILDING: 'pending',
+ vm_states.DELETED: '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',
+}
+
+
+def state_description_from_vm_state(vm_state):
+ """Map the vm state to the server status string"""
+ return _STATE_DESCRIPTION_MAP.get(vm_state, vm_state)
+
+
# TODO(yamahata): hypervisor dependent default device name
_DEFAULT_ROOT_DEVICE_NAME = '/dev/sda1'
_DEFAULT_MAPPINGS = {'ami': 'sda1',
@@ -1039,11 +1064,12 @@ class CloudController(object):
def _format_attr_instance_initiated_shutdown_behavior(instance,
result):
- state_description = instance['state_description']
- state_to_value = {'stopping': 'stop',
- 'stopped': 'stop',
- 'terminating': 'terminate'}
- value = state_to_value.get(state_description)
+ 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
@@ -1198,8 +1224,8 @@ class CloudController(object):
self._format_kernel_id(instance, i, 'kernelId')
self._format_ramdisk_id(instance, i, 'ramdiskId')
i['instanceState'] = {
- 'code': instance['state'],
- 'name': instance['state_description']}
+ 'code': instance['power_state'],
+ 'name': state_description_from_vm_state(instance['vm_state'])}
fixed_addr = None
floating_addr = None
if instance['fixed_ips']:
@@ -1618,22 +1644,22 @@ class CloudController(object):
# stop the instance if necessary
restart_instance = False
if not no_reboot:
- state_description = instance['state_description']
+ vm_state = instance['vm_state']
# if the instance is in subtle state, refuse to proceed.
- if state_description not in ('running', 'stopping', 'stopped'):
+ if vm_state not in (vm_states.ACTIVE, vm_states.STOPPED):
raise exception.InstanceNotRunning(instance_id=ec2_instance_id)
- if state_description == 'running':
+ if vm_state == vm_states.ACTIVE:
restart_instance = True
self.compute_api.stop(context, instance_id=instance_id)
# wait instance for really stopped
start_time = time.time()
- while state_description != 'stopped':
+ while vm_state != vm_states.STOPPED:
time.sleep(1)
instance = self.compute_api.get(context, instance_id)
- state_description = instance['state_description']
+ vm_state = instance['vm_state']
# NOTE(yamahata): timeout and error. 1 hour for now for safety.
# Is it too short/long?
# Or is there any better way?
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index d9eb832f2..d743a66ef 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -27,7 +27,8 @@ from nova import flags
from nova import log as logging
from nova import quota
from nova.api.openstack import wsgi
-from nova.compute import power_state as compute_power_state
+from nova.compute import vm_states
+from nova.compute import task_states
LOG = logging.getLogger('nova.api.openstack.common')
@@ -38,36 +39,61 @@ XML_NS_V10 = 'http://docs.rackspacecloud.com/servers/api/v1.0'
XML_NS_V11 = 'http://docs.openstack.org/compute/api/v1.1'
-_STATUS_MAP = {
- None: 'BUILD',
- compute_power_state.NOSTATE: 'BUILD',
- compute_power_state.RUNNING: 'ACTIVE',
- compute_power_state.BLOCKED: 'ACTIVE',
- compute_power_state.SUSPENDED: 'SUSPENDED',
- compute_power_state.PAUSED: 'PAUSED',
- compute_power_state.SHUTDOWN: 'SHUTDOWN',
- compute_power_state.SHUTOFF: 'SHUTOFF',
- compute_power_state.CRASHED: 'ERROR',
- compute_power_state.FAILED: 'ERROR',
- compute_power_state.BUILDING: 'BUILD',
+_STATE_MAP = {
+ vm_states.ACTIVE: {
+ 'default': 'ACTIVE',
+ task_states.REBOOTING: 'REBOOT',
+ task_states.UPDATING_PASSWORD: 'PASSWORD',
+ task_states.RESIZE_VERIFY: 'VERIFY_RESIZE',
+ },
+ vm_states.BUILDING: {
+ 'default': 'BUILD',
+ },
+ vm_states.REBUILDING: {
+ 'default': 'REBUILD',
+ },
+ vm_states.STOPPED: {
+ 'default': 'STOPPED',
+ },
+ vm_states.MIGRATING: {
+ 'default': 'MIGRATING',
+ },
+ vm_states.RESIZING: {
+ 'default': 'RESIZE',
+ },
+ vm_states.PAUSED: {
+ 'default': 'PAUSED',
+ },
+ vm_states.SUSPENDED: {
+ 'default': 'SUSPENDED',
+ },
+ vm_states.RESCUED: {
+ 'default': 'RESCUE',
+ },
+ vm_states.ERROR: {
+ 'default': 'ERROR',
+ },
+ vm_states.DELETED: {
+ 'default': 'DELETED',
+ },
}
-def status_from_power_state(power_state):
- """Map the power state to the server status string"""
- return _STATUS_MAP[power_state]
+def status_from_state(vm_state, task_state='default'):
+ """Given vm_state and task_state, return a status string."""
+ task_map = _STATE_MAP.get(vm_state, dict(default='UNKNOWN_STATE'))
+ status = task_map.get(task_state, task_map['default'])
+ LOG.debug("Generated %(status)s from vm_state=%(vm_state)s "
+ "task_state=%(task_state)s." % locals())
+ return status
-def power_states_from_status(status):
- """Map the server status string to a list of power states"""
- power_states = []
- for power_state, status_map in _STATUS_MAP.iteritems():
- # Skip the 'None' state
- if power_state is None:
- continue
- if status.lower() == status_map.lower():
- power_states.append(power_state)
- return power_states
+def vm_state_from_status(status):
+ """Map the server status string to a vm state."""
+ for state, task_map in _STATE_MAP.iteritems():
+ status_string = task_map.get("default")
+ if status.lower() == status_string.lower():
+ return state
def get_pagination_params(request):
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 27c67e79e..e0dd9bdb1 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -95,17 +95,15 @@ class Controller(object):
search_opts['recurse_zones'] = utils.bool_from_str(
search_opts.get('recurse_zones', False))
- # If search by 'status', we need to convert it to 'state'
- # If the status is unknown, bail.
- # Leave 'state' in search_opts so compute can pass it on to
- # child zones..
+ # If search by 'status', we need to convert it to 'vm_state'
+ # to pass on to child zones.
if 'status' in search_opts:
status = search_opts['status']
- search_opts['state'] = common.power_states_from_status(status)
- if len(search_opts['state']) == 0:
+ state = common.vm_state_from_status(status)
+ if state is None:
reason = _('Invalid server status: %(status)s') % locals()
- LOG.error(reason)
raise exception.InvalidInput(reason=reason)
+ search_opts['vm_state'] = state
# By default, compute's get_all() will return deleted instances.
# If an admin hasn't specified a 'deleted' search option, we need
@@ -608,9 +606,8 @@ class ControllerV10(Controller):
try:
self.compute_api.rebuild(context, instance_id, image_id, password)
- except exception.BuildInProgress:
- msg = _("Instance %s is currently being rebuilt.") % instance_id
- LOG.debug(msg)
+ except exception.RebuildRequiresActiveInstance:
+ msg = _("Instance %s must be active to rebuild.") % instance_id
raise exc.HTTPConflict(explanation=msg)
return webob.Response(status_int=202)
@@ -750,9 +747,8 @@ class ControllerV11(Controller):
self.compute_api.rebuild(context, instance_id, image_href,
password, name=name, metadata=metadata,
files_to_inject=personalities)
- except exception.BuildInProgress:
- msg = _("Instance %s is currently being rebuilt.") % instance_id
- LOG.debug(msg)
+ except exception.RebuildRequiresActiveInstance:
+ msg = _("Instance %s must be active to rebuild.") % instance_id
raise exc.HTTPConflict(explanation=msg)
except exception.InstanceNotFound:
msg = _("Instance %s could not be found") % instance_id
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 0ec98591e..b0daeb7a8 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -21,13 +21,12 @@ import hashlib
import os
from nova import exception
-import nova.compute
-import nova.context
from nova.api.openstack import common
from nova.api.openstack.views import addresses as addresses_view
from nova.api.openstack.views import flavors as flavors_view
from nova.api.openstack.views import images as images_view
from nova import utils
+from nova.compute import vm_states
class ViewBuilder(object):
@@ -61,17 +60,13 @@ class ViewBuilder(object):
def _build_detail(self, inst):
"""Returns a detailed model of a server."""
+ vm_state = inst.get('vm_state', vm_states.BUILDING)
+ task_state = inst.get('task_state')
inst_dict = {
'id': inst['id'],
'name': inst['display_name'],
- 'status': common.status_from_power_state(inst.get('state'))}
-
- ctxt = nova.context.get_admin_context()
- compute_api = nova.compute.API()
-
- if compute_api.has_finished_migration(ctxt, inst['uuid']):
- inst_dict['status'] = 'RESIZE-CONFIRM'
+ 'status': common.status_from_state(vm_state, task_state)}
# Return the metadata as a dictionary
metadata = {}