summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCerberus <matt.dietz@rackspace.com>2010-09-29 16:21:28 -0500
committerCerberus <matt.dietz@rackspace.com>2010-09-29 16:21:28 -0500
commit128ec65cf39e74b53903dd9788a58c8eb513abe8 (patch)
tree9c3323c87d41d5e5e631d097e4a3235d1df591d2
parent9c4319a83a6e7d61ffa6b78e9f17ea35821c5526 (diff)
downloadnova-128ec65cf39e74b53903dd9788a58c8eb513abe8.tar.gz
nova-128ec65cf39e74b53903dd9788a58c8eb513abe8.tar.xz
nova-128ec65cf39e74b53903dd9788a58c8eb513abe8.zip
Server creation up to, but not including, network configuration
-rw-r--r--nova/api/rackspace/servers.py97
-rw-r--r--nova/db/sqlalchemy/models.py1
-rw-r--r--nova/tests/api/rackspace/auth.py8
-rw-r--r--nova/tests/api/rackspace/servers.py48
-rw-r--r--nova/tests/api/rackspace/test_helper.py17
-rw-r--r--nova/wsgi.py11
6 files changed, 123 insertions, 59 deletions
diff --git a/nova/api/rackspace/servers.py b/nova/api/rackspace/servers.py
index aa955c222..cc971adc0 100644
--- a/nova/api/rackspace/servers.py
+++ b/nova/api/rackspace/servers.py
@@ -25,6 +25,7 @@ from nova import rpc
from nova import utils
from nova import wsgi
from nova.api.rackspace import _id_translator
+from nova.compute import instance_types
from nova.compute import power_state
from nova.wsgi import Serializer
import nova.image.service
@@ -39,11 +40,11 @@ def _instance_id_translator():
ids """
return _id_translator.RackspaceAPIIdTranslator( "instance", 'nova')
-def _image_id_translator():
+def _image_service():
""" Helper method for initializing the image id translator """
service = nova.image.service.ImageService.load()
- return _id_translator.RackspaceAPIIdTranslator(
- "image", service.__class__.__name__)
+ return (service, _id_translator.RackspaceAPIIdTranslator(
+ "image", service.__class__.__name__))
def _filter_params(inst_dict):
""" Extracts all updatable parameters for a server update request """
@@ -122,8 +123,11 @@ class Controller(wsgi.Controller):
def show(self, req, id):
""" Returns server details by server id """
+ inst_id_trans = _instance_id_translator()
+ inst_id = inst_id_trans.from_rs_id(id)
+
user_id = req.environ['nova.context']['user']['id']
- inst = self.db_driver.instance_get(None, id)
+ inst = self.db_driver.instance_get_by_ec2_id(None, inst_id)
if inst:
if inst.user_id == user_id:
return _entity_detail(inst)
@@ -131,8 +135,11 @@ class Controller(wsgi.Controller):
def delete(self, req, id):
""" Destroys a server """
+ inst_id_trans = _instance_id_translator()
+ inst_id = inst_id_trans.from_rs_id(id)
+
user_id = req.environ['nova.context']['user']['id']
- instance = self.db_driver.instance_get(None, id)
+ instance = self.db_driver.instance_get_by_ec2_id(None, inst_id)
if instance and instance['user_id'] == user_id:
self.db_driver.instance_destroy(None, id)
return exc.HTTPAccepted()
@@ -140,10 +147,16 @@ class Controller(wsgi.Controller):
def create(self, req):
""" Creates a new server for a given user """
- if not req.environ.has_key('inst_dict'):
+
+ env = self._deserialize(req.body, req)
+ if not env:
return exc.HTTPUnprocessableEntity()
- inst = self._build_server_instance(req)
+ #try:
+ inst = self._build_server_instance(req, env)
+ #except Exception, e:
+ # print e
+ # return exc.HTTPUnprocessableEntity()
rpc.cast(
FLAGS.compute_topic, {
@@ -153,6 +166,8 @@ class Controller(wsgi.Controller):
def update(self, req, id):
""" Updates the server name or password """
+ inst_id_trans = _instance_id_translator()
+ inst_id = inst_id_trans.from_rs_id(id)
user_id = req.environ['nova.context']['user']['id']
inst_dict = self._deserialize(req.body, req)
@@ -160,7 +175,7 @@ class Controller(wsgi.Controller):
if not inst_dict:
return exc.HTTPUnprocessableEntity()
- instance = self.db_driver.instance_get(None, id)
+ instance = self.db_driver.instance_get_by_ec2_id(None, inst_id)
if not instance or instance.user_id != user_id:
return exc.HTTPNotFound()
@@ -174,56 +189,68 @@ class Controller(wsgi.Controller):
if not req.environ.has_key('inst_dict'):
return exc.HTTPUnprocessableEntity()
- def _build_server_instance(self, req):
+ def _build_server_instance(self, req, env):
"""Build instance data structure and save it to the data store."""
ltime = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
inst = {}
inst_id_trans = _instance_id_translator()
- image_id_trans = _image_id_translator()
- env = req.environ['inst_dict']
user_id = req.environ['nova.context']['user']['id']
- inst['rs_id'] = inst_id_trans.to_rs_id()
+ instance_type, flavor = None, None
+ for k, v in instance_types.INSTANCE_TYPES.iteritems():
+ if v['flavorid'] == env['server']['flavorId']:
+ instance_type, flavor = k, v
+ break
+
+ if not flavor:
+ raise Exception, "Flavor not found"
+
image_id = env['server']['imageId']
- opaque_id = translator_instance().from_rs_id(image_id)
+ img_service, image_id_trans = _image_service()
+
+ opaque_image_id = image_id_trans.to_rs_id(image_id)
+ image = img_service.show(opaque_image_id)
- inst['name'] = env['server']['name']
- inst['image_id'] = opaque_id
- inst['instance_type'] = env['server']['flavorId']
+ if not image:
+ raise Exception, "Image not found"
+
+ inst['server_name'] = env['server']['name']
+ inst['image_id'] = opaque_image_id
inst['user_id'] = user_id
inst['launch_time'] = ltime
inst['mac_address'] = utils.generate_mac()
+ inst['project_id'] = user_id
- #TODO(dietz) These are the attributes I'm unsure of
inst['state_description'] = 'scheduling'
- inst['kernel_id'] = ''
- inst['ramdisk_id'] = ''
+ inst['kernel_id'] = image.get('kernelId', FLAGS.default_kernel)
+ inst['ramdisk_id'] = image.get('ramdiskId', FLAGS.default_ramdisk)
inst['reservation_id'] = utils.generate_uid('r')
- inst['key_data'] = ''
- inst['key_name'] = ''
- inst['security_group'] = ''
- # Flavor related attributes
- inst['instance_type'] = ''
- inst['memory_mb'] = ''
- inst['vcpus'] = ''
- inst['local_gb'] = ''
+ #TODO(dietz) this may be ill advised
+ key_pair_ref = self.db_driver.key_pair_get_all_by_user(
+ None, user_id)[0]
-
+ inst['key_data'] = key_pair_ref['public_key']
+ inst['key_name'] = key_pair_ref['name']
- #TODO(dietz): This seems necessary. How do these apply across
- #the Rackspace implementation?
- inst['project_id'] = ''
+ #TODO(dietz) stolen from ec2 api, see TODO there
+ inst['security_group'] = 'default'
- self.network_manager = utils.import_object(FLAGS.rs_network_manager)
-
- address = self.network_manager.allocate_fixed_ip( None, inst['id'])
+ # Flavor related attributes
+ inst['instance_type'] = instance_type
+ inst['memory_mb'] = flavor['memory_mb']
+ inst['vcpus'] = flavor['vcpus']
+ inst['local_gb'] = flavor['local_gb']
ref = self.db_driver.instance_create(None, inst)
- inst['id'] = ref.id
+ inst['id'] = inst_id_trans.to_rs_id(ref.ec2_id)
+
+ #self.network_manager = utils.import_object(FLAGS.rs_network_manager)
+ #
+ #address = self.network_manager.allocate_fixed_ip( None, inst['id'])
return inst
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 2a314b037..22446fc64 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -199,7 +199,6 @@ class Instance(BASE, NovaBase):
id = Column(Integer, primary_key=True)
ec2_id = Column(String(10), unique=True)
- rs_id = Column(String(255))
admin_pass = Column(String(255))
user_id = Column(String(255))
diff --git a/nova/tests/api/rackspace/auth.py b/nova/tests/api/rackspace/auth.py
index a6e10970f..56677c2f4 100644
--- a/nova/tests/api/rackspace/auth.py
+++ b/nova/tests/api/rackspace/auth.py
@@ -1,12 +1,14 @@
-import webob
-import webob.dec
+import datetime
import unittest
+
import stubout
+import webob
+import webob.dec
+
import nova.api
import nova.api.rackspace.auth
from nova import auth
from nova.tests.api.rackspace import test_helper
-import datetime
class Test(unittest.TestCase):
def setUp(self):
diff --git a/nova/tests/api/rackspace/servers.py b/nova/tests/api/rackspace/servers.py
index e08c9c6fd..d759eba3c 100644
--- a/nova/tests/api/rackspace/servers.py
+++ b/nova/tests/api/rackspace/servers.py
@@ -26,6 +26,7 @@ import nova.api.rackspace
from nova.api.rackspace import servers
import nova.db.api
from nova.db.sqlalchemy.models import Instance
+import nova.rpc
from nova.tests.api.test_helper import *
from nova.tests.api.rackspace import test_helper
@@ -52,8 +53,11 @@ class ServersTest(unittest.TestCase):
test_helper.stub_for_testing(self.stubs)
test_helper.stub_out_rate_limiting(self.stubs)
test_helper.stub_out_auth(self.stubs)
+ test_helper.stub_out_id_translator(self.stubs)
+ test_helper.stub_out_key_pair_funcs(self.stubs)
+ test_helper.stub_out_image_service(self.stubs)
self.stubs.Set(nova.db.api, 'instance_get_all', return_servers)
- self.stubs.Set(nova.db.api, 'instance_get', return_server)
+ self.stubs.Set(nova.db.api, 'instance_get_by_ec2_id', return_server)
self.stubs.Set(nova.db.api, 'instance_get_all_by_user',
return_servers)
@@ -67,9 +71,6 @@ class ServersTest(unittest.TestCase):
self.assertEqual(res_dict['server']['id'], '1')
self.assertEqual(res_dict['server']['name'], 'server1')
- def test_get_backup_schedule(self):
- pass
-
def test_get_server_list(self):
req = webob.Request.blank('/v1.0/servers')
res = req.get_response(nova.api.API())
@@ -82,19 +83,36 @@ class ServersTest(unittest.TestCase):
self.assertEqual(s.get('imageId', None), None)
i += 1
- #def test_create_instance(self):
- # test_helper.stub_out_image_translator(self.stubs)
- # body = dict(server=dict(
- # name='server_test', imageId=2, flavorId=2, metadata={},
- # personality = {}
- # ))
- # req = webob.Request.blank('/v1.0/servers')
- # req.method = 'POST'
- # req.body = json.dumps(body)
+ def test_create_instance(self):
+ def instance_create(context, inst):
+ class Foo(object):
+ ec2_id = 1
+ return Foo()
- # res = req.get_response(nova.api.API())
+ def fake_cast(*args, **kwargs):
+ pass
- # print res
+ self.stubs.Set(nova.db.api, 'instance_create', instance_create)
+ self.stubs.Set(nova.rpc, 'cast', fake_cast)
+
+ test_helper.stub_out_id_translator(self.stubs)
+ body = dict(server=dict(
+ name='server_test', imageId=2, flavorId=2, metadata={},
+ personality = {}
+ ))
+ req = webob.Request.blank('/v1.0/servers')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+
+ res = req.get_response(nova.api.API())
+
+ self.assertEqual(res.status_int, 200)
+
+ def test_update_no_body(self):
+ req = webob.Request.blank('/v1.0/servers/1')
+ req.method = 'PUT'
+ res = req.get_response(nova.api.API())
+ self.assertEqual(res.status_int, 422)
def test_update_bad_params(self):
""" Confirm that update is filtering params """
diff --git a/nova/tests/api/rackspace/test_helper.py b/nova/tests/api/rackspace/test_helper.py
index aa7fb382c..962f0ba4c 100644
--- a/nova/tests/api/rackspace/test_helper.py
+++ b/nova/tests/api/rackspace/test_helper.py
@@ -9,6 +9,7 @@ from nova import utils
from nova import flags
import nova.api.rackspace.auth
import nova.api.rackspace._id_translator
+from nova.image import service
from nova.wsgi import Router
FLAGS = flags.FLAGS
@@ -40,7 +41,21 @@ def fake_wsgi(self, req):
req.environ['inst_dict'] = json.loads(req.body)
return self.application
-def stub_out_image_translator(stubs):
+
+
+def stub_out_key_pair_funcs(stubs):
+ def key_pair(context, user_id):
+ return [dict(name='key', public_key='public_key')]
+ stubs.Set(nova.db.api, 'key_pair_get_all_by_user',
+ key_pair)
+
+def stub_out_image_service(stubs):
+ def fake_image_show(meh, id):
+ return dict(kernelId=1, ramdiskId=1)
+
+ stubs.Set(nova.image.service.LocalImageService, 'show', fake_image_show)
+
+def stub_out_id_translator(stubs):
class FakeTranslator(object):
def __init__(self, id_type, service_name):
pass
diff --git a/nova/wsgi.py b/nova/wsgi.py
index 48c4dabc2..b91d91121 100644
--- a/nova/wsgi.py
+++ b/nova/wsgi.py
@@ -281,10 +281,13 @@ class Serializer(object):
The string must be in the format of a supported MIME type.
"""
datastring = datastring.strip()
- is_xml = (datastring[0] == '<')
- if not is_xml:
- return json.loads(datastring)
- return self._from_xml(datastring)
+ try:
+ is_xml = (datastring[0] == '<')
+ if not is_xml:
+ return json.loads(datastring)
+ return self._from_xml(datastring)
+ except:
+ return None
def _from_xml(self, datastring):
xmldata = self.metadata.get('application/xml', {})