summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorBrian Waldon <brian.waldon@rackspace.com>2011-03-24 10:06:25 -0400
committerBrian Waldon <brian.waldon@rackspace.com>2011-03-24 10:06:25 -0400
commit23ca6a5e90ed5efd40ec3a33a2201a5a3a68cd30 (patch)
tree42785bbd612bc41996bf3a799bcaf64686d3d40d /nova/api
parentdb6aaa666dc1deaeead7f32fd22a4f6b2d40ed25 (diff)
parent2434138bbc73a8dbaee44c66cb7bed9f1fa40b2b (diff)
merging trunk r863
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/admin.py19
-rw-r--r--nova/api/openstack/__init__.py8
-rw-r--r--nova/api/openstack/common.py21
-rw-r--r--nova/api/openstack/images.py6
-rw-r--r--nova/api/openstack/servers.py1
-rw-r--r--nova/api/openstack/views/servers.py51
6 files changed, 71 insertions, 35 deletions
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index d9a4ef999..d8d90ad83 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -28,6 +28,7 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova import utils
+from nova.api.ec2 import ec2utils
from nova.auth import manager
@@ -60,7 +61,7 @@ def project_dict(project):
def host_dict(host, compute_service, instances, volume_service, volumes, now):
"""Convert a host model object to a result dict"""
- rv = {'hostanme': host, 'instance_count': len(instances),
+ rv = {'hostname': host, 'instance_count': len(instances),
'volume_count': len(volumes)}
if compute_service:
latest = compute_service['updated_at'] or compute_service['created_at']
@@ -92,15 +93,18 @@ def vpn_dict(project, vpn_instance):
'public_ip': project.vpn_ip,
'public_port': project.vpn_port}
if vpn_instance:
- rv['instance_id'] = vpn_instance['ec2_id']
+ rv['instance_id'] = ec2utils.id_to_ec2_id(vpn_instance['id'])
rv['created_at'] = utils.isotime(vpn_instance['created_at'])
address = vpn_instance.get('fixed_ip', None)
if address:
rv['internal_ip'] = address['address']
- if utils.vpn_ping(project.vpn_ip, project.vpn_port):
- rv['state'] = 'running'
+ if project.vpn_ip and project.vpn_port:
+ if utils.vpn_ping(project.vpn_ip, project.vpn_port):
+ rv['state'] = 'running'
+ else:
+ rv['state'] = 'down'
else:
- rv['state'] = 'down'
+ rv['state'] = 'down - invalid project vpn config'
else:
rv['state'] = 'pending'
return rv
@@ -116,7 +120,8 @@ class AdminController(object):
def describe_instance_types(self, context, **_kwargs):
"""Returns all active instance types data (vcpus, memory, etc.)"""
- return {'instanceTypeSet': [db.instance_type_get_all(context)]}
+ return {'instanceTypeSet': [instance_dict(v) for v in
+ db.instance_type_get_all(context).values()]}
def describe_user(self, _context, name, **_kwargs):
"""Returns user data, including access and secret keys."""
@@ -279,7 +284,7 @@ class AdminController(object):
", ensure it isn't running, and try "
"again in a few minutes")
instance = self._vpn_for(context, project)
- return {'instance_id': instance['ec2_id']}
+ return {'instance_id': ec2utils.id_to_ec2_id(instance['id'])}
def describe_vpns(self, context):
vpns = []
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index d028eec39..143b1d2b2 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -129,8 +129,10 @@ class APIRouter(wsgi.Router):
class APIRouterV10(APIRouter):
+ """Define routes specific to OpenStack API V1.0."""
+
def _setup_routes(self, mapper):
- APIRouter._setup_routes(self, mapper)
+ super(APIRouterV10, self)._setup_routes(mapper)
mapper.resource("server", "servers",
controller=servers.ControllerV10(),
collection={'detail': 'GET'},
@@ -138,8 +140,10 @@ class APIRouterV10(APIRouter):
class APIRouterV11(APIRouter):
+ """Define routes specific to OpenStack API V1.1."""
+
def _setup_routes(self, mapper):
- APIRouter._setup_routes(self, mapper)
+ super(APIRouterV11, self)._setup_routes(mapper)
mapper.resource("server", "servers",
controller=servers.ControllerV11(),
collection={'detail': 'GET'},
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index b224cbfb4..bff050347 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -15,10 +15,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import re
+from urlparse import urlparse
+
+import webob
+
from nova import exception
-from webob import exc
-import webob.exc
def limited(items, request, max_limit=1000):
@@ -78,7 +79,13 @@ def get_image_id_from_image_hash(image_service, context, image_hash):
def get_id_from_href(href):
- m = re.match(r'http.+/.+/(\d)+$', href)
- if not m:
- raise exc.HTTPBadRequest(_('could not parse id from href'))
- return int(m.group(1))
+ """Return the id portion of a url as an int.
+
+ Given: http://www.foo.com/bar/123?q=4
+ Returns: 123
+
+ """
+ try:
+ return int(urlparse(href).path.split('/')[-1])
+ except:
+ raise webob.exc.HTTPBadRequest(_('could not parse id from href'))
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 98f0dd96b..99c14275a 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -143,6 +143,7 @@ class Controller(wsgi.Controller):
image = self._service.show(req.environ['nova.context'], image_id)
_convert_image_id_to_hash(image)
+ self._format_image_dates(image)
return dict(image=image)
def delete(self, req, id):
@@ -164,3 +165,8 @@ class Controller(wsgi.Controller):
# Users may not modify public images, and that's all that
# we support for now.
raise faults.Fault(exc.HTTPNotFound())
+
+ def _format_image_dates(self, image):
+ for attr in ['created_at', 'updated_at', 'deleted_at']:
+ if image.get(attr) is not None:
+ image[attr] = image[attr].strftime('%Y-%m-%dT%H:%M:%SZ')
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index aeb0981ed..ff9076003 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -22,6 +22,7 @@ from xml.dom import minidom
from webob import exc
from nova import compute
+from nova import context
from nova import exception
from nova import flags
from nova import log as logging
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 6b5dc7c16..08b53177b 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -16,7 +16,10 @@
# under the License.
import hashlib
+
from nova.compute import power_state
+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
@@ -25,19 +28,18 @@ from nova import utils
class ViewBuilder(object):
- '''
- Models a server response as a python dictionary.
+ """Model a server response as a python dictionary.
+
+ Public methods: build
Abstract methods: _build_image, _build_flavor
- '''
+
+ """
def __init__(self, addresses_builder):
self.addresses_builder = addresses_builder
def build(self, inst, is_detail):
- """
- Coerces into dictionary format, mapping everything to
- Rackspace-like attributes for return
- """
+ """Return a dict that represenst a server."""
if is_detail:
server = self._build_detail(inst)
else:
@@ -45,12 +47,14 @@ class ViewBuilder(object):
self._build_extra(server, inst)
- return dict(server=server)
+ return server
def _build_simple(self, inst):
- return dict(id=inst['id'], name=inst['display_name'])
+ """Return a simple model of a server."""
+ return dict(server=dict(id=inst['id'], name=inst['display_name']))
def _build_detail(self, inst):
+ """Returns a detailed model of a server."""
power_mapping = {
None: 'build',
power_state.NOSTATE: 'build',
@@ -62,18 +66,22 @@ class ViewBuilder(object):
power_state.SHUTOFF: 'active',
power_state.CRASHED: 'error',
power_state.FAILED: 'error'}
- inst_dict = {}
- inst_dict['id'] = int(inst['id'])
- inst_dict['name'] = inst['display_name']
- inst_dict['status'] = power_mapping[inst.get('state')]
- inst_dict['addresses'] = self.addresses_builder.build(inst)
+ inst_dict = {
+ 'id': int(inst['id']),
+ 'name': inst['display_name'],
+ 'addresses': self.addresses_builder.build(inst),
+ 'status': power_mapping[inst.get('state')]}
+
+ ctxt = nova.context.get_admin_context()
+ compute_api = nova.compute.API()
+ if compute_api.has_finished_migration(ctxt, inst['id']):
+ inst_dict['status'] = 'resize-confirm'
# Return the metadata as a dictionary
metadata = {}
- if 'metadata' in dict(inst):
- for item in inst['metadata']:
- metadata[item['key']] = item['value']
+ for item in inst.get('metadata', []):
+ metadata[item['key']] = item['value']
inst_dict['metadata'] = metadata
inst_dict['hostId'] = ''
@@ -83,12 +91,14 @@ class ViewBuilder(object):
self._build_image(inst_dict, inst)
self._build_flavor(inst_dict, inst)
- return inst_dict
+ return dict(server=inst_dict)
def _build_image(self, response, inst):
+ """Return the image sub-resource of a server."""
raise NotImplementedError()
def _build_flavor(self, response, inst):
+ """Return the flavor sub-resource of a server."""
raise NotImplementedError()
def _build_extra(self, response, inst):
@@ -96,6 +106,8 @@ class ViewBuilder(object):
class ViewBuilderV10(ViewBuilder):
+ """Model an Openstack API V1.0 server response."""
+
def _build_image(self, response, inst):
if 'image_id' in dict(inst):
response['imageId'] = inst['image_id']
@@ -106,6 +118,7 @@ class ViewBuilderV10(ViewBuilder):
class ViewBuilderV11(ViewBuilder):
+ """Model an Openstack API V1.0 server response."""
def __init__(self, addresses_builder, flavor_builder, image_builder,
base_url):
ViewBuilder.__init__(self, addresses_builder)
@@ -147,7 +160,7 @@ class ViewBuilderV11(ViewBuilder):
},
]
- response["links"] = links
+ response["server"]["links"] = links
def generate_href(self, server_id):
"""Create an url that refers to a specific server id."""