diff options
| author | Brian Waldon <brian.waldon@rackspace.com> | 2011-03-24 10:06:25 -0400 |
|---|---|---|
| committer | Brian Waldon <brian.waldon@rackspace.com> | 2011-03-24 10:06:25 -0400 |
| commit | 23ca6a5e90ed5efd40ec3a33a2201a5a3a68cd30 (patch) | |
| tree | 42785bbd612bc41996bf3a799bcaf64686d3d40d /nova/api | |
| parent | db6aaa666dc1deaeead7f32fd22a4f6b2d40ed25 (diff) | |
| parent | 2434138bbc73a8dbaee44c66cb7bed9f1fa40b2b (diff) | |
merging trunk r863
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/admin.py | 19 | ||||
| -rw-r--r-- | nova/api/openstack/__init__.py | 8 | ||||
| -rw-r--r-- | nova/api/openstack/common.py | 21 | ||||
| -rw-r--r-- | nova/api/openstack/images.py | 6 | ||||
| -rw-r--r-- | nova/api/openstack/servers.py | 1 | ||||
| -rw-r--r-- | nova/api/openstack/views/servers.py | 51 |
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.""" |
