diff options
| author | Michael Gundlach <michael.gundlach@rackspace.com> | 2010-08-18 13:09:34 -0400 |
|---|---|---|
| committer | Michael Gundlach <michael.gundlach@rackspace.com> | 2010-08-18 13:09:34 -0400 |
| commit | 2eb1287f8d8c88eada2a14bed06ed1613c9beed2 (patch) | |
| tree | 7ac0838f96196126d7f59acc34ed9a2db99ef17e /nova/api | |
| parent | 24a6fd40f657896fb20249392be6ed41c30ca679 (diff) | |
| parent | 4e5e72da2e3242026d757c8d5143e16f9d00cb6a (diff) | |
| download | nova-2eb1287f8d8c88eada2a14bed06ed1613c9beed2.tar.gz nova-2eb1287f8d8c88eada2a14bed06ed1613c9beed2.tar.xz nova-2eb1287f8d8c88eada2a14bed06ed1613c9beed2.zip | |
Pull in ~eday/nova/api-port
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/__init__.py | 38 | ||||
| -rw-r--r-- | nova/api/ec2/__init__.py | 42 | ||||
| -rw-r--r-- | nova/api/rackspace/__init__.py | 81 | ||||
| -rw-r--r-- | nova/api/rackspace/base.py | 39 | ||||
| -rw-r--r-- | nova/api/rackspace/controllers/__init__.py | 5 | ||||
| -rw-r--r-- | nova/api/rackspace/flavors.py | 18 | ||||
| -rw-r--r-- | nova/api/rackspace/images.py | 64 | ||||
| -rw-r--r-- | nova/api/rackspace/servers.py | 83 | ||||
| -rw-r--r-- | nova/api/rackspace/sharedipgroups.py | 18 |
9 files changed, 388 insertions, 0 deletions
diff --git a/nova/api/__init__.py b/nova/api/__init__.py new file mode 100644 index 000000000..a6bb93348 --- /dev/null +++ b/nova/api/__init__.py @@ -0,0 +1,38 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +""" +Root WSGI middleware for all API controllers. +""" + +import routes + +from nova import wsgi +from nova.api import ec2 +from nova.api import rackspace + + +class API(wsgi.Router): + """Routes top-level requests to the appropriate controller.""" + + def __init__(self): + mapper = routes.Mapper() + mapper.connect(None, "/v1.0/{path_info:.*}", + controller=rackspace.API()) + mapper.connect(None, "/ec2/{path_info:.*}", controller=ec2.API()) + super(API, self).__init__(mapper) diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py new file mode 100644 index 000000000..6eec0abf7 --- /dev/null +++ b/nova/api/ec2/__init__.py @@ -0,0 +1,42 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +""" +WSGI middleware for EC2 API controllers. +""" + +import routes +import webob.dec + +from nova import wsgi + + +class API(wsgi.Router): + """Routes EC2 requests to the appropriate controller.""" + + def __init__(self): + mapper = routes.Mapper() + mapper.connect(None, "{all:.*}", controller=self.dummy) + super(API, self).__init__(mapper) + + @staticmethod + @webob.dec.wsgify + def dummy(req): + """Temporary dummy controller.""" + msg = "dummy response -- please hook up __init__() to cloud.py instead" + return repr({'dummy': msg, + 'kwargs': repr(req.environ['wsgiorg.routing_args'][1])}) diff --git a/nova/api/rackspace/__init__.py b/nova/api/rackspace/__init__.py new file mode 100644 index 000000000..27e78f801 --- /dev/null +++ b/nova/api/rackspace/__init__.py @@ -0,0 +1,81 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +""" +WSGI middleware for Rackspace API controllers. +""" + +import json +import time + +import routes +import webob.dec +import webob.exc + +from nova import flags +from nova import wsgi +from nova.api.rackspace import flavors +from nova.api.rackspace import images +from nova.api.rackspace import servers +from nova.api.rackspace import sharedipgroups +from nova.auth import manager + + +class API(wsgi.Middleware): + """WSGI entry point for all Rackspace API requests.""" + + def __init__(self): + app = AuthMiddleware(APIRouter()) + super(API, self).__init__(app) + + +class AuthMiddleware(wsgi.Middleware): + """Authorize the rackspace API request or return an HTTP Forbidden.""" + + #TODO(gundlach): isn't this the old Nova API's auth? Should it be replaced + #with correct RS API auth? + + @webob.dec.wsgify + def __call__(self, req): + context = {} + if "HTTP_X_AUTH_TOKEN" in req.environ: + context['user'] = manager.AuthManager().get_user_from_access_key( + req.environ['HTTP_X_AUTH_TOKEN']) + if context['user']: + context['project'] = manager.AuthManager().get_project( + context['user'].name) + if "user" not in context: + return webob.exc.HTTPForbidden() + req.environ['nova.context'] = context + return self.application + + +class APIRouter(wsgi.Router): + """ + Routes requests on the Rackspace API to the appropriate controller + and method. + """ + + def __init__(self): + mapper = routes.Mapper() + mapper.resource("server", "servers", controller=servers.Controller()) + mapper.resource("image", "images", controller=images.Controller()) + mapper.resource("flavor", "flavors", controller=flavors.Controller()) + mapper.resource("sharedipgroup", "sharedipgroups", + controller=sharedipgroups.Controller()) + super(APIRouter, self).__init__(mapper) diff --git a/nova/api/rackspace/base.py b/nova/api/rackspace/base.py new file mode 100644 index 000000000..c85fd7b8e --- /dev/null +++ b/nova/api/rackspace/base.py @@ -0,0 +1,39 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +from nova import wsgi + + +class Controller(wsgi.Controller): + """TODO(eday): Base controller for all rackspace controllers. What is this + for? Is this just Rackspace specific? """ + + @classmethod + def render(cls, instance): + if isinstance(instance, list): + return {cls.entity_name: cls.render(instance)} + else: + return { "TODO": "TODO" } + + def serialize(self, data, request): + """ + Serialize the given dict to the response type requested in request. + Uses self._serialization_metadata if it exists, which is a dict mapping + MIME types to information needed to serialize to that type. + """ + _metadata = getattr(type(self), "_serialization_metadata", {}) + return Serializer(request.environ, _metadata).to_content_type(data) diff --git a/nova/api/rackspace/controllers/__init__.py b/nova/api/rackspace/controllers/__init__.py new file mode 100644 index 000000000..052b6f365 --- /dev/null +++ b/nova/api/rackspace/controllers/__init__.py @@ -0,0 +1,5 @@ +from nova.endpoint.rackspace.controllers.images import ImagesController +from nova.endpoint.rackspace.controllers.flavors import FlavorsController +from nova.endpoint.rackspace.controllers.servers import ServersController +from nova.endpoint.rackspace.controllers.sharedipgroups import \ + SharedIpGroupsController diff --git a/nova/api/rackspace/flavors.py b/nova/api/rackspace/flavors.py new file mode 100644 index 000000000..986f11434 --- /dev/null +++ b/nova/api/rackspace/flavors.py @@ -0,0 +1,18 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +class Controller(object): pass diff --git a/nova/api/rackspace/images.py b/nova/api/rackspace/images.py new file mode 100644 index 000000000..57c03894a --- /dev/null +++ b/nova/api/rackspace/images.py @@ -0,0 +1,64 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +from nova.endpoint.rackspace.controllers.base import BaseController +from nova.endpoint import images +from webob import exc + +#TODO(gundlach): Serialize return values +class Controller(BaseController): + + _serialization_metadata = { + 'application/xml': { + "attributes": { + "image": [ "id", "name", "updated", "created", "status", + "serverId", "progress" ] + } + } + } + + def index(self, req): + context = req.environ['nova.api_request_context'] + return images.list(context) + + def show(self, req, id): + context = req.environ['nova.api_request_context'] + return images.list(context, filter_list=[id]) + + def delete(self, req, id): + context = req.environ['nova.api_request_context'] + # TODO(gundlach): make sure it's an image they may delete? + return images.deregister(context, id) + + def create(self, **kwargs): + # TODO(gundlach): no idea how to hook this up. code below + # is from servers.py. + inst = self.build_server_instance(kwargs['server']) + rpc.cast( + FLAGS.compute_topic, { + "method": "run_instance", + "args": {"instance_id": inst.instance_id}}) + + def update(self, **kwargs): + # TODO (gundlach): no idea how to hook this up. code below + # is from servers.py. + instance_id = kwargs['id'] + instance = compute.InstanceDirectory().get(instance_id) + if not instance: + raise ServerNotFound("The requested server was not found") + instance.update(kwargs['server']) + instance.save() diff --git a/nova/api/rackspace/servers.py b/nova/api/rackspace/servers.py new file mode 100644 index 000000000..25d1fe9c8 --- /dev/null +++ b/nova/api/rackspace/servers.py @@ -0,0 +1,83 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +from nova import rpc +from nova.compute import model as compute +from nova.api.rackspace import base + + +class Controller(base.Controller): + entity_name = 'servers' + + def index(self, **kwargs): + instances = [] + for inst in compute.InstanceDirectory().all: + instances.append(instance_details(inst)) + + def show(self, **kwargs): + instance_id = kwargs['id'] + return compute.InstanceDirectory().get(instance_id) + + def delete(self, **kwargs): + instance_id = kwargs['id'] + instance = compute.InstanceDirectory().get(instance_id) + if not instance: + raise ServerNotFound("The requested server was not found") + instance.destroy() + return True + + def create(self, **kwargs): + inst = self.build_server_instance(kwargs['server']) + rpc.cast( + FLAGS.compute_topic, { + "method": "run_instance", + "args": {"instance_id": inst.instance_id}}) + + def update(self, **kwargs): + instance_id = kwargs['id'] + instance = compute.InstanceDirectory().get(instance_id) + if not instance: + raise ServerNotFound("The requested server was not found") + instance.update(kwargs['server']) + instance.save() + + def build_server_instance(self, env): + """Build instance data structure and save it to the data store.""" + reservation = utils.generate_uid('r') + ltime = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + inst = self.instdir.new() + inst['name'] = env['server']['name'] + inst['image_id'] = env['server']['imageId'] + inst['instance_type'] = env['server']['flavorId'] + inst['user_id'] = env['user']['id'] + inst['project_id'] = env['project']['id'] + inst['reservation_id'] = reservation + inst['launch_time'] = ltime + inst['mac_address'] = utils.generate_mac() + address = self.network.allocate_ip( + inst['user_id'], + inst['project_id'], + mac=inst['mac_address']) + inst['private_dns_name'] = str(address) + inst['bridge_name'] = network.BridgedNetwork.get_network_for_project( + inst['user_id'], + inst['project_id'], + 'default')['bridge_name'] + # key_data, key_name, ami_launch_index + # TODO(todd): key data or root password + inst.save() + return inst diff --git a/nova/api/rackspace/sharedipgroups.py b/nova/api/rackspace/sharedipgroups.py new file mode 100644 index 000000000..986f11434 --- /dev/null +++ b/nova/api/rackspace/sharedipgroups.py @@ -0,0 +1,18 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# 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. + +class Controller(object): pass |
