summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorMichael Gundlach <michael.gundlach@rackspace.com>2010-09-29 09:39:24 -0400
committerMichael Gundlach <michael.gundlach@rackspace.com>2010-09-29 09:39:24 -0400
commit0f69422a47dfc837297c4853bbcea9da9b7dd809 (patch)
tree59faf12e6036251d60b84e6b91227092e9dea196 /nova/api
parent05e3e188e03624884ed019fe9cd8f216c9262f98 (diff)
parent43ce84290964b433fd9d9898772d29bffc385dd8 (diff)
downloadnova-0f69422a47dfc837297c4853bbcea9da9b7dd809.tar.gz
nova-0f69422a47dfc837297c4853bbcea9da9b7dd809.tar.xz
nova-0f69422a47dfc837297c4853bbcea9da9b7dd809.zip
Merge from trunk
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/__init__.py2
-rw-r--r--nova/api/ec2/cloud.py102
-rw-r--r--nova/api/ec2/images.py8
-rw-r--r--nova/api/rackspace/__init__.py18
-rw-r--r--nova/api/rackspace/_id_translator.py2
-rw-r--r--nova/api/rackspace/auth.py8
-rw-r--r--nova/api/rackspace/backup_schedules.py (renamed from nova/api/rackspace/base.py)26
-rw-r--r--nova/api/rackspace/flavors.py4
-rw-r--r--nova/api/rackspace/images.py9
-rw-r--r--nova/api/rackspace/servers.py203
-rw-r--r--nova/api/rackspace/sharedipgroups.py4
11 files changed, 292 insertions, 94 deletions
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index f0aa57ee4..7a958f841 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -158,12 +158,14 @@ class Authorizer(wsgi.Middleware):
'RunInstances': ['projectmanager', 'sysadmin'],
'TerminateInstances': ['projectmanager', 'sysadmin'],
'RebootInstances': ['projectmanager', 'sysadmin'],
+ 'UpdateInstance': ['projectmanager', 'sysadmin'],
'DeleteVolume': ['projectmanager', 'sysadmin'],
'DescribeImages': ['all'],
'DeregisterImage': ['projectmanager', 'sysadmin'],
'RegisterImage': ['projectmanager', 'sysadmin'],
'DescribeImageAttribute': ['all'],
'ModifyImageAttribute': ['projectmanager', 'sysadmin'],
+ 'UpdateImage': ['projectmanager', 'sysadmin'],
},
'AdminController': {
# All actions have the same permission: ['none'] (the default)
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 367511e3b..d3f54367b 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -101,9 +101,9 @@ class CloudController(object):
def _get_mpi_data(self, project_id):
result = {}
- for instance in db.instance_get_by_project(None, project_id):
+ for instance in db.instance_get_all_by_project(None, project_id):
if instance['fixed_ip']:
- line = '%s slots=%d' % (instance['fixed_ip']['str_id'],
+ line = '%s slots=%d' % (instance['fixed_ip']['address'],
INSTANCE_TYPES[instance['instance_type']]['vcpus'])
key = str(instance['key_name'])
if key in result:
@@ -143,7 +143,7 @@ class CloudController(object):
},
'hostname': hostname,
'instance-action': 'none',
- 'instance-id': instance_ref['str_id'],
+ 'instance-id': instance_ref['ec2_id'],
'instance-type': instance_ref['instance_type'],
'local-hostname': hostname,
'local-ipv4': address,
@@ -245,7 +245,7 @@ class CloudController(object):
def get_console_output(self, context, instance_id, **kwargs):
# instance_id is passed in as a list of instances
- instance_ref = db.instance_get_by_str(context, instance_id[0])
+ instance_ref = db.instance_get_by_ec2_id(context, instance_id[0])
return rpc.call('%s.%s' % (FLAGS.compute_topic,
instance_ref['host']),
{"method": "get_console_output",
@@ -256,7 +256,7 @@ class CloudController(object):
if context.user.is_admin():
volumes = db.volume_get_all(context)
else:
- volumes = db.volume_get_by_project(context, context.project.id)
+ volumes = db.volume_get_all_by_project(context, context.project.id)
volumes = [self._format_volume(context, v) for v in volumes]
@@ -264,7 +264,7 @@ class CloudController(object):
def _format_volume(self, context, volume):
v = {}
- v['volumeId'] = volume['str_id']
+ v['volumeId'] = volume['ec2_id']
v['status'] = volume['status']
v['size'] = volume['size']
v['availabilityZone'] = volume['availability_zone']
@@ -282,9 +282,12 @@ class CloudController(object):
'device': volume['mountpoint'],
'instanceId': volume['instance_id'],
'status': 'attached',
- 'volume_id': volume['str_id']}]
+ 'volume_id': volume['ec2_id']}]
else:
v['attachmentSet'] = [{}]
+
+ v['display_name'] = volume['display_name']
+ v['display_description'] = volume['display_description']
return v
def create_volume(self, context, size, **kwargs):
@@ -302,6 +305,8 @@ class CloudController(object):
vol['availability_zone'] = FLAGS.storage_availability_zone
vol['status'] = "creating"
vol['attach_status'] = "detached"
+ vol['display_name'] = kwargs.get('display_name')
+ vol['display_description'] = kwargs.get('display_description')
volume_ref = db.volume_create(context, vol)
rpc.cast(FLAGS.scheduler_topic,
@@ -314,13 +319,13 @@ class CloudController(object):
def attach_volume(self, context, volume_id, instance_id, device, **kwargs):
- volume_ref = db.volume_get_by_str(context, volume_id)
+ volume_ref = db.volume_get_by_ec2_id(context, volume_id)
# TODO(vish): abstract status checking?
if volume_ref['status'] != "available":
raise exception.ApiError("Volume status must be available")
if volume_ref['attach_status'] == "attached":
raise exception.ApiError("Volume is already attached")
- instance_ref = db.instance_get_by_str(context, instance_id)
+ instance_ref = db.instance_get_by_ec2_id(context, instance_id)
host = instance_ref['host']
rpc.cast(db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "attach_volume",
@@ -336,7 +341,7 @@ class CloudController(object):
'volumeId': volume_ref['id']}
def detach_volume(self, context, volume_id, **kwargs):
- volume_ref = db.volume_get_by_str(context, volume_id)
+ volume_ref = db.volume_get_by_ec2_id(context, volume_id)
instance_ref = db.volume_get_instance(context, volume_ref['id'])
if not instance_ref:
raise exception.ApiError("Volume isn't attached to anything!")
@@ -356,7 +361,7 @@ class CloudController(object):
db.volume_detached(context)
return {'attachTime': volume_ref['attach_time'],
'device': volume_ref['mountpoint'],
- 'instanceId': instance_ref['str_id'],
+ 'instanceId': instance_ref['ec2_id'],
'requestId': context.request_id,
'status': volume_ref['attach_status'],
'volumeId': volume_ref['id']}
@@ -368,6 +373,16 @@ class CloudController(object):
lst = [lst]
return [{label: x} for x in lst]
+ def update_volume(self, context, volume_id, **kwargs):
+ updatable_fields = ['display_name', 'display_description']
+ changes = {}
+ for field in updatable_fields:
+ if field in kwargs:
+ changes[field] = kwargs[field]
+ if changes:
+ db.volume_update(context, volume_id, kwargs)
+ return True
+
def describe_instances(self, context, **kwargs):
return self._format_describe_instances(context)
@@ -382,20 +397,20 @@ class CloudController(object):
def _format_instances(self, context, reservation_id=None):
reservations = {}
if reservation_id:
- instances = db.instance_get_by_reservation(context,
- reservation_id)
+ instances = db.instance_get_all_by_reservation(context,
+ reservation_id)
else:
if context.user.is_admin():
instances = db.instance_get_all(context)
else:
- instances = db.instance_get_by_project(context,
- context.project.id)
+ instances = db.instance_get_all_by_project(context,
+ context.project.id)
for instance in instances:
if not context.user.is_admin():
if instance['image_id'] == FLAGS.vpn_image_id:
continue
i = {}
- i['instanceId'] = instance['str_id']
+ i['instanceId'] = instance['ec2_id']
i['imageId'] = instance['image_id']
i['instanceState'] = {
'code': instance['state'],
@@ -404,10 +419,10 @@ class CloudController(object):
fixed_addr = None
floating_addr = None
if instance['fixed_ip']:
- fixed_addr = instance['fixed_ip']['str_id']
+ fixed_addr = instance['fixed_ip']['address']
if instance['fixed_ip']['floating_ips']:
fixed = instance['fixed_ip']
- floating_addr = fixed['floating_ips'][0]['str_id']
+ floating_addr = fixed['floating_ips'][0]['address']
i['privateDnsName'] = fixed_addr
i['publicDnsName'] = floating_addr
i['dnsName'] = i['publicDnsName'] or i['privateDnsName']
@@ -420,6 +435,8 @@ class CloudController(object):
i['instanceType'] = instance['instance_type']
i['launchTime'] = instance['created_at']
i['amiLaunchIndex'] = instance['launch_index']
+ i['displayName'] = instance['display_name']
+ i['displayDescription'] = instance['display_description']
if not reservations.has_key(instance['reservation_id']):
r = {}
r['reservationId'] = instance['reservation_id']
@@ -439,14 +456,14 @@ class CloudController(object):
if context.user.is_admin():
iterator = db.floating_ip_get_all(context)
else:
- iterator = db.floating_ip_get_by_project(context,
- context.project.id)
+ iterator = db.floating_ip_get_all_by_project(context,
+ context.project.id)
for floating_ip_ref in iterator:
- address = floating_ip_ref['str_id']
+ address = floating_ip_ref['address']
instance_id = None
if (floating_ip_ref['fixed_ip']
and floating_ip_ref['fixed_ip']['instance']):
- instance_id = floating_ip_ref['fixed_ip']['instance']['str_id']
+ instance_id = floating_ip_ref['fixed_ip']['instance']['ec2_id']
address_rv = {'public_ip': address,
'instance_id': instance_id}
if context.user.is_admin():
@@ -477,19 +494,20 @@ class CloudController(object):
rpc.cast(network_topic,
{"method": "deallocate_floating_ip",
"args": {"context": None,
- "floating_address": floating_ip_ref['str_id']}})
+ "floating_address": floating_ip_ref['address']}})
return {'releaseResponse': ["Address released."]}
def associate_address(self, context, instance_id, public_ip, **kwargs):
- instance_ref = db.instance_get_by_str(context, instance_id)
- fixed_ip_ref = db.fixed_ip_get_by_instance(context, instance_ref['id'])
+ instance_ref = db.instance_get_by_ec2_id(context, instance_id)
+ fixed_address = db.instance_get_fixed_address(context,
+ instance_ref['id'])
floating_ip_ref = db.floating_ip_get_by_address(context, public_ip)
network_topic = self._get_network_topic(context)
rpc.cast(network_topic,
{"method": "associate_floating_ip",
"args": {"context": None,
- "floating_address": floating_ip_ref['str_id'],
- "fixed_address": fixed_ip_ref['str_id']}})
+ "floating_address": floating_ip_ref['address'],
+ "fixed_address": fixed_address}})
return {'associateResponse': ["Address associated."]}
def disassociate_address(self, context, public_ip, **kwargs):
@@ -498,7 +516,7 @@ class CloudController(object):
rpc.cast(network_topic,
{"method": "disassociate_floating_ip",
"args": {"context": None,
- "floating_address": floating_ip_ref['str_id']}})
+ "floating_address": floating_ip_ref['address']}})
return {'disassociateResponse': ["Address disassociated."]}
def _get_network_topic(self, context):
@@ -576,6 +594,8 @@ class CloudController(object):
base_options['user_data'] = kwargs.get('user_data', '')
base_options['security_group'] = security_group
base_options['instance_type'] = instance_type
+ base_options['display_name'] = kwargs.get('display_name')
+ base_options['display_description'] = kwargs.get('display_description')
type_data = INSTANCE_TYPES[instance_type]
base_options['memory_mb'] = type_data['memory_mb']
@@ -589,7 +609,7 @@ class CloudController(object):
inst = {}
inst['mac_address'] = utils.generate_mac()
inst['launch_index'] = num
- inst['hostname'] = instance_ref['str_id']
+ inst['hostname'] = instance_ref['ec2_id']
db.instance_update(context, inst_id, inst)
address = self.network_manager.allocate_fixed_ip(context,
inst_id,
@@ -618,7 +638,7 @@ class CloudController(object):
for id_str in instance_id:
logging.debug("Going to try and terminate %s" % id_str)
try:
- instance_ref = db.instance_get_by_str(context, id_str)
+ instance_ref = db.instance_get_by_ec2_id(context, id_str)
except exception.NotFound:
logging.warning("Instance %s was not found during terminate"
% id_str)
@@ -640,7 +660,7 @@ class CloudController(object):
rpc.cast(network_topic,
{"method": "disassociate_floating_ip",
"args": {"context": None,
- "address": address}})
+ "floating_address": address}})
address = db.instance_get_fixed_address(context,
instance_ref['id'])
@@ -664,7 +684,7 @@ class CloudController(object):
def reboot_instances(self, context, instance_id, **kwargs):
"""instance_id is a list of instance ids"""
for id_str in instance_id:
- instance_ref = db.instance_get_by_str(context, id_str)
+ instance_ref = db.instance_get_by_ec2_id(context, id_str)
host = instance_ref['host']
rpc.cast(db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "reboot_instance",
@@ -672,9 +692,21 @@ class CloudController(object):
"instance_id": instance_ref['id']}})
return True
+ def update_instance(self, context, instance_id, **kwargs):
+ updatable_fields = ['display_name', 'display_description']
+ changes = {}
+ for field in updatable_fields:
+ if field in kwargs:
+ changes[field] = kwargs[field]
+ if changes:
+ db_context = {}
+ inst = db.instance_get_by_ec2_id(db_context, instance_id)
+ db.instance_update(db_context, inst['id'], kwargs)
+ return True
+
def delete_volume(self, context, volume_id, **kwargs):
# TODO: return error if not authorized
- volume_ref = db.volume_get_by_str(context, volume_id)
+ volume_ref = db.volume_get_by_ec2_id(context, volume_id)
if volume_ref['status'] != "available":
raise exception.ApiError("Volume status must be available")
now = datetime.datetime.utcnow()
@@ -727,3 +759,7 @@ class CloudController(object):
if not operation_type in ['add', 'remove']:
raise exception.ApiError('operation_type must be add or remove')
return images.modify(context, image_id, operation_type)
+
+ def update_image(self, context, image_id, **kwargs):
+ result = images.update(context, image_id, dict(kwargs))
+ return result
diff --git a/nova/api/ec2/images.py b/nova/api/ec2/images.py
index 4579cd81a..cb54cdda2 100644
--- a/nova/api/ec2/images.py
+++ b/nova/api/ec2/images.py
@@ -43,6 +43,14 @@ def modify(context, image_id, operation):
return True
+def update(context, image_id, attributes):
+ """update an image's attributes / info.json"""
+ attributes.update({"image_id": image_id})
+ conn(context).make_request(
+ method='POST',
+ bucket='_images',
+ query_args=qs(attributes))
+ return True
def register(context, image_location):
""" rpc call to register a new image based from a manifest """
diff --git a/nova/api/rackspace/__init__.py b/nova/api/rackspace/__init__.py
index 447037020..c85e90ab9 100644
--- a/nova/api/rackspace/__init__.py
+++ b/nova/api/rackspace/__init__.py
@@ -32,6 +32,7 @@ from nova import flags
from nova import utils
from nova import wsgi
from nova.api.rackspace import faults
+from nova.api.rackspace import backup_schedules
from nova.api.rackspace import flavors
from nova.api.rackspace import images
from nova.api.rackspace import ratelimiting
@@ -68,8 +69,10 @@ class AuthMiddleware(wsgi.Middleware):
if not user:
return faults.Fault(webob.exc.HTTPUnauthorized())
- context = {'user': user}
- req.environ['nova.context'] = context
+
+ if not req.environ.has_key('nova.context'):
+ req.environ['nova.context'] = {}
+ req.environ['nova.context']['user'] = user
return self.application
class RateLimitingMiddleware(wsgi.Middleware):
@@ -148,11 +151,20 @@ class APIRouter(wsgi.Router):
def __init__(self):
mapper = routes.Mapper()
- mapper.resource("server", "servers", controller=servers.Controller())
+ mapper.resource("server", "servers", controller=servers.Controller(),
+ collection={ 'detail': 'GET'},
+ member={'action':'POST'})
+
+ mapper.resource("backup_schedule", "backup_schedules",
+ controller=backup_schedules.Controller(),
+ parent_resource=dict(member_name='server',
+ collection_name = 'servers'))
+
mapper.resource("image", "images", controller=images.Controller(),
collection={'detail': 'GET'})
mapper.resource("flavor", "flavors", controller=flavors.Controller(),
collection={'detail': 'GET'})
mapper.resource("sharedipgroup", "sharedipgroups",
controller=sharedipgroups.Controller())
+
super(APIRouter, self).__init__(mapper)
diff --git a/nova/api/rackspace/_id_translator.py b/nova/api/rackspace/_id_translator.py
index aec5fb6a5..333aa8434 100644
--- a/nova/api/rackspace/_id_translator.py
+++ b/nova/api/rackspace/_id_translator.py
@@ -37,6 +37,6 @@ class RackspaceAPIIdTranslator(object):
# every int id be used.)
return int(self._store.hget(self._fwd_key, str(opaque_id)))
- def from_rs_id(self, strategy_name, rs_id):
+ def from_rs_id(self, rs_id):
"""Convert a Rackspace id to a strategy-specific one."""
return self._store.hget(self._rev_key, rs_id)
diff --git a/nova/api/rackspace/auth.py b/nova/api/rackspace/auth.py
index 519263367..c45156ebd 100644
--- a/nova/api/rackspace/auth.py
+++ b/nova/api/rackspace/auth.py
@@ -1,13 +1,15 @@
import datetime
+import hashlib
import json
import time
+
import webob.exc
import webob.dec
-import hashlib
-from nova import flags
+
from nova import auth
-from nova import manager
from nova import db
+from nova import flags
+from nova import manager
from nova import utils
from nova.api.rackspace import faults
diff --git a/nova/api/rackspace/base.py b/nova/api/rackspace/backup_schedules.py
index dd2c6543c..46da778ee 100644
--- a/nova/api/rackspace/base.py
+++ b/nova/api/rackspace/backup_schedules.py
@@ -15,16 +15,24 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova import wsgi
+import time
+from webob import exc
+from nova import wsgi
+from nova.api.rackspace import _id_translator
+import nova.image.service
class Controller(wsgi.Controller):
- """TODO(eday): Base controller for all rackspace controllers. What is this
- for? Is this just Rackspace specific? """
+ def __init__(self):
+ pass
+
+ def index(self, req, server_id):
+ return exc.HTTPNotFound()
+
+ def create(self, req, server_id):
+ """ No actual update method required, since the existing API allows
+ both create and update through a POST """
+ return exc.HTTPNotFound()
- @classmethod
- def render(cls, instance):
- if isinstance(instance, list):
- return {cls.entity_name: cls.render(instance)}
- else:
- return {"TODO": "TODO"}
+ def delete(self, req, server_id):
+ return exc.HTTPNotFound()
diff --git a/nova/api/rackspace/flavors.py b/nova/api/rackspace/flavors.py
index 6cc57be33..556a7b471 100644
--- a/nova/api/rackspace/flavors.py
+++ b/nova/api/rackspace/flavors.py
@@ -15,12 +15,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-from nova.api.rackspace import base
from nova.api.rackspace import faults
from nova.compute import instance_types
+from nova import wsgi
from webob import exc
-class Controller(base.Controller):
+class Controller(wsgi.Controller):
"""Flavor controller for the Rackspace API."""
_serialization_metadata = {
diff --git a/nova/api/rackspace/images.py b/nova/api/rackspace/images.py
index 1c50d0bec..2e2cc0c6b 100644
--- a/nova/api/rackspace/images.py
+++ b/nova/api/rackspace/images.py
@@ -15,13 +15,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-import nova.image.service
-from nova.api.rackspace import base
+from webob import exc
+
+from nova import wsgi
from nova.api.rackspace import _id_translator
+import nova.image.service
from nova.api.rackspace import faults
-from webob import exc
-class Controller(base.Controller):
+class Controller(wsgi.Controller):
_serialization_metadata = {
'application/xml': {
diff --git a/nova/api/rackspace/servers.py b/nova/api/rackspace/servers.py
index 1815f7523..4ab04bde7 100644
--- a/nova/api/rackspace/servers.py
+++ b/nova/api/rackspace/servers.py
@@ -14,67 +14,194 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+
import time
-from nova import db
+from webob import exc
+
from nova import flags
from nova import rpc
from nova import utils
-from nova.api.rackspace import base
+from nova import wsgi
+from nova.api.rackspace import _id_translator
+from nova.compute import power_state
+import nova.image.service
FLAGS = flags.FLAGS
-class Controller(base.Controller):
- entity_name = 'servers'
- def index(self, **kwargs):
- instances = []
- for inst in db.instance_get_all(None):
- instances.append(instance_details(inst))
- def show(self, **kwargs):
- instance_id = kwargs['id']
- return db.instance_get(None, instance_id)
+def translator_instance():
+ """ Helper method for initializing the image id translator """
+ service = nova.image.service.ImageService.load()
+ return _id_translator.RackspaceAPIIdTranslator(
+ "image", service.__class__.__name__)
- def delete(self, **kwargs):
- instance_id = kwargs['id']
- instance = db.instance_get(None, instance_id)
- if not instance:
- raise ServerNotFound("The requested server was not found")
- instance.destroy()
- return True
+def _filter_params(inst_dict):
+ """ Extracts all updatable parameters for a server update request """
+ keys = ['name', 'adminPass']
+ new_attrs = {}
+ for k in keys:
+ if inst_dict.has_key(k):
+ new_attrs[k] = inst_dict[k]
+ return new_attrs
+
+def _entity_list(entities):
+ """ Coerces a list of servers into proper dictionary format """
+ return dict(servers=entities)
+
+def _entity_detail(inst):
+ """ Maps everything to Rackspace-like attributes for return"""
+ power_mapping = {
+ power_state.NOSTATE: 'build',
+ power_state.RUNNING: 'active',
+ power_state.BLOCKED: 'active',
+ power_state.PAUSED: 'suspended',
+ power_state.SHUTDOWN: 'active',
+ power_state.SHUTOFF: 'active',
+ power_state.CRASHED: 'error'
+ }
+ inst_dict = {}
+
+ mapped_keys = dict(status='state', imageId='image_id',
+ flavorId='instance_type', name='server_name', id='id')
+
+ for k, v in mapped_keys.iteritems():
+ inst_dict[k] = inst[v]
+
+ inst_dict['status'] = power_mapping[inst_dict['status']]
+ inst_dict['addresses'] = dict(public=[], private=[])
+ inst_dict['metadata'] = {}
+ inst_dict['hostId'] = ''
+
+ return dict(server=inst_dict)
+
+def _entity_inst(inst):
+ """ Filters all model attributes save for id and name """
+ return dict(server=dict(id=inst['id'], name=inst['server_name']))
+
+class Controller(wsgi.Controller):
+ """ The Server API controller for the Openstack API """
+
+
+ _serialization_metadata = {
+ 'application/xml': {
+ "attributes": {
+ "server": [ "id", "imageId", "name", "flavorId", "hostId",
+ "status", "progress", "progress" ]
+ }
+ }
+ }
+
+ def __init__(self, db_driver=None):
+ if not db_driver:
+ db_driver = FLAGS.db_driver
+ self.db_driver = utils.import_object(db_driver)
+ super(Controller, self).__init__()
+
+ def index(self, req):
+ """ Returns a list of server names and ids for a given user """
+ user_id = req.environ['nova.context']['user']['id']
+ instance_list = self.db_driver.instance_get_all_by_user(None, user_id)
+ res = [_entity_inst(inst)['server'] for inst in instance_list]
+ return _entity_list(res)
+
+ def detail(self, req):
+ """ Returns a list of server details for a given user """
+ user_id = req.environ['nova.context']['user']['id']
+ res = [_entity_detail(inst)['server'] for inst in
+ self.db_driver.instance_get_all_by_user(None, user_id)]
+ return _entity_list(res)
+
+ def show(self, req, id):
+ """ Returns server details by server id """
+ user_id = req.environ['nova.context']['user']['id']
+ inst = self.db_driver.instance_get(None, id)
+ if inst:
+ if inst.user_id == user_id:
+ return _entity_detail(inst)
+ raise exc.HTTPNotFound()
+
+ def delete(self, req, id):
+ """ Destroys a server """
+ user_id = req.environ['nova.context']['user']['id']
+ instance = self.db_driver.instance_get(None, id)
+ if instance and instance['user_id'] == user_id:
+ self.db_driver.instance_destroy(None, id)
+ return exc.HTTPAccepted()
+ return exc.HTTPNotFound()
+
+ def create(self, req):
+ """ Creates a new server for a given user """
+ if not req.environ.has_key('inst_dict'):
+ return exc.HTTPUnprocessableEntity()
+
+ inst = self._build_server_instance(req)
- def create(self, **kwargs):
- inst = self.build_server_instance(kwargs['server'])
rpc.cast(
FLAGS.compute_topic, {
"method": "run_instance",
"args": {"instance_id": inst['id']}})
+ return _entity_inst(inst)
- def update(self, **kwargs):
- instance_id = kwargs['id']
- instance = db.instance_get(None, instance_id)
+ def update(self, req, id):
+ """ Updates the server name or password """
+ if not req.environ.has_key('inst_dict'):
+ return exc.HTTPUnprocessableEntity()
+
+ instance = self.db_driver.instance_get(None, id)
if not instance:
- raise ServerNotFound("The requested server was not found")
- instance.update(kwargs['server'])
- instance.save()
+ return exc.HTTPNotFound()
+
+ attrs = req.environ['nova.context'].get('model_attributes', None)
+ if attrs:
+ self.db_driver.instance_update(None, id, _filter_params(attrs))
+ return exc.HTTPNoContent()
+
+ def action(self, req, id):
+ """ multi-purpose method used to reboot, rebuild, and
+ resize a server """
+ if not req.environ.has_key('inst_dict'):
+ return exc.HTTPUnprocessableEntity()
- def build_server_instance(self, env):
+ def _build_server_instance(self, req):
"""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 = {}
- inst['name'] = env['server']['name']
- inst['image_id'] = env['server']['imageId']
+
+ env = req.environ['inst_dict']
+
+ image_id = env['server']['imageId']
+ opaque_id = translator_instance().from_rs_id(image_id)
+
+ inst['name'] = env['server']['server_name']
+ inst['image_id'] = opaque_id
inst['instance_type'] = env['server']['flavorId']
- inst['user_id'] = env['user']['id']
- inst['project_id'] = env['project']['id']
- inst['reservation_id'] = reservation
+
+ user_id = req.environ['nova.context']['user']['id']
+ inst['user_id'] = user_id
+
inst['launch_time'] = ltime
inst['mac_address'] = utils.generate_mac()
- inst_id = db.instance_create(None, inst)['id']
- address = self.network_manager.allocate_fixed_ip(None, inst_id)
- # key_data, key_name, ami_launch_index
- # TODO(todd): key data or root password
- inst.save()
+
+ inst['project_id'] = env['project']['id']
+ inst['reservation_id'] = reservation
+ reservation = utils.generate_uid('r')
+
+ 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']
+
+ ref = self.db_driver.instance_create(None, inst)
+ inst['id'] = ref.id
+
return inst
+
+
diff --git a/nova/api/rackspace/sharedipgroups.py b/nova/api/rackspace/sharedipgroups.py
index 986f11434..4d2d0ede1 100644
--- a/nova/api/rackspace/sharedipgroups.py
+++ b/nova/api/rackspace/sharedipgroups.py
@@ -15,4 +15,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-class Controller(object): pass
+from nova import wsgi
+
+class Controller(wsgi.Controller): pass