Merge lp:~sandy-walsh/nova/api-parity into lp:~hudson-openstack/nova/trunk

Proposed by Sandy Walsh
Status: Merged
Approved by: Matt Dietz
Approved revision: 533
Merged at revision: 545
Proposed branch: lp:~sandy-walsh/nova/api-parity
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 469 lines (+125/-20)
15 files modified
krm_mapping.json.sample (+3/-0)
nova/api/openstack/__init__.py (+8/-3)
nova/api/openstack/backup_schedules.py (+4/-2)
nova/api/openstack/common.py (+24/-0)
nova/api/openstack/images.py (+18/-1)
nova/api/openstack/servers.py (+27/-2)
nova/api/openstack/shared_ip_groups.py (+6/-4)
nova/auth/manager.py (+9/-5)
nova/auth/novarc.template (+4/-0)
nova/compute/api.py (+4/-1)
nova/flags.py (+2/-0)
nova/tests/api/openstack/test_images.py (+2/-0)
nova/tests/api/openstack/test_servers.py (+10/-0)
nova/tests/api/openstack/test_shared_ip_groups.py (+1/-1)
nova/virt/xenapi/vm_utils.py (+3/-1)
To merge this branch: bzr merge lp:~sandy-walsh/nova/api-parity
Reviewer Review Type Date Requested Status
Cory Wright (community) Approve
Matt Dietz (community) Approve
Trey Morris (community) Approve
Eric Day (community) Needs Information
Review via email: mp+45371@code.launchpad.net

Description of the change

Read Full Spec for implementation details and notes on how to boot an instance using OS API.
http://etherpad.openstack.org/B2RK0q1CYj

Look at these notes for known issues:
http://etherpad.openstack.org/BXOU0TTj9M

To post a comment you must log in.
Revision history for this message
Cory Wright (corywright) wrote :

Looks like you have a few conflicts in this commit.

review: Needs Fixing
Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

Conflicts resolved, tests run. Thx dubs!

Revision history for this message
Trey Morris (tr3buchet) wrote :

I like it! exporting the cloudservers environment variables was a great idea.

question about lines 190-191, I thought the current api didn't have a paused state, wouldn't returning paused cause trouble? Pause isn't implemented in the current api so i chose to set it to "error" because if an instance somehow got "paused" something weird would have happened.

review: Approve
Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

Trey I went back and forth over that decision for a while. It just looked so weird seeing "error" when it was paused. I figured since other clients are unable to issue a "pause" command, they should never see it.

But I see your point and can live with it either way.

Revision history for this message
Eric Day (eday) wrote :

367/368: is this needed now that instance is returned as a dict?

Should sharedipgroups.py be renamed to shared_ip_groups.py for consistency?

I don't like the 'grab all and find w/ hash' on image ID as I mentioned in IRC, but hopefully this will get better with Glance. :)

review: Needs Information
Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

good point ... I will rename.

I've got a tweet out looking for a two-way function. Good idea.

Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

Renamed, remerged with trunk and fixed a bug in the display_name patch test.

Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

Hmm, this branch is busted now after the trunk merge until the instance_id thing is straightened out.

Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

Branch working again.

Eric, as your question about "not in", I'm not getting a dict back, but a sqlalchemy object (verified).

Revision history for this message
Trey Morris (tr3buchet) wrote :

I like your point of view on pause/error sandy. Let's definitely go with pause.

review: Approve
Revision history for this message
Matt Dietz (cerberus) wrote :

284-285: We should be consistent with the /controller/detail calls. If you look at openstack/__init__.py detail is a sub-resource of server, with an implemented verb in the controller itself.

review: Needs Fixing
lp:~sandy-walsh/nova/api-parity updated
531. By Sandy Walsh

another merge with trunk to remedy instance_id issues

532. By Sandy Walsh

Changed shared_ip_group detail routing

533. By Sandy Walsh

Changed shared_ip_group detail routing

Revision history for this message
Sandy Walsh (sandy-walsh) wrote :

> 284-285: We should be consistent with the /controller/detail calls. If you
> look at openstack/__init__.py detail is a sub-resource of server, with an
> implemented verb in the controller itself.

All done sir. Good suggestion!

Revision history for this message
Matt Dietz (cerberus) wrote :

\o/

review: Approve
Revision history for this message
Cory Wright (corywright) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'krm_mapping.json.sample'
--- krm_mapping.json.sample 1970-01-01 00:00:00 +0000
+++ krm_mapping.json.sample 2011-01-11 19:42:14 +0000
@@ -0,0 +1,3 @@
1{
2 "machine" : ["kernel", "ramdisk"]
3}
04
=== modified file 'nova/api/openstack/__init__.py'
--- nova/api/openstack/__init__.py 2011-01-10 17:37:06 +0000
+++ nova/api/openstack/__init__.py 2011-01-11 19:42:14 +0000
@@ -35,7 +35,7 @@
35from nova.api.openstack import flavors35from nova.api.openstack import flavors
36from nova.api.openstack import images36from nova.api.openstack import images
37from nova.api.openstack import servers37from nova.api.openstack import servers
38from nova.api.openstack import sharedipgroups38from nova.api.openstack import shared_ip_groups
3939
4040
41LOG = logging.getLogger('nova.api.openstack')41LOG = logging.getLogger('nova.api.openstack')
@@ -48,6 +48,10 @@
48 'nova.api.openstack.ratelimiting.RateLimitingMiddleware',48 'nova.api.openstack.ratelimiting.RateLimitingMiddleware',
49 'Default ratelimiting implementation for the Openstack API')49 'Default ratelimiting implementation for the Openstack API')
5050
51flags.DEFINE_string('os_krm_mapping_file',
52 'krm_mapping.json',
53 'Location of OpenStack Flavor/OS:EC2 Kernel/Ramdisk/Machine JSON file.')
54
51flags.DEFINE_bool('allow_admin_api',55flags.DEFINE_bool('allow_admin_api',
52 False,56 False,
53 'When True, this API service will accept admin operations.')57 'When True, this API service will accept admin operations.')
@@ -110,8 +114,9 @@
110 collection={'detail': 'GET'})114 collection={'detail': 'GET'})
111 mapper.resource("flavor", "flavors", controller=flavors.Controller(),115 mapper.resource("flavor", "flavors", controller=flavors.Controller(),
112 collection={'detail': 'GET'})116 collection={'detail': 'GET'})
113 mapper.resource("sharedipgroup", "sharedipgroups",117 mapper.resource("shared_ip_group", "shared_ip_groups",
114 controller=sharedipgroups.Controller())118 collection={'detail': 'GET'},
119 controller=shared_ip_groups.Controller())
115120
116 super(APIRouter, self).__init__(mapper)121 super(APIRouter, self).__init__(mapper)
117122
118123
=== modified file 'nova/api/openstack/backup_schedules.py'
--- nova/api/openstack/backup_schedules.py 2010-12-28 21:48:48 +0000
+++ nova/api/openstack/backup_schedules.py 2011-01-11 19:42:14 +0000
@@ -15,7 +15,9 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18import logging
18import time19import time
20
19from webob import exc21from webob import exc
2022
21from nova import wsgi23from nova import wsgi
@@ -46,8 +48,8 @@
46 def create(self, req, server_id):48 def create(self, req, server_id):
47 """ No actual update method required, since the existing API allows49 """ No actual update method required, since the existing API allows
48 both create and update through a POST """50 both create and update through a POST """
49 return faults.Fault(exc.HTTPNotFound())51 return faults.Fault(exc.HTTPNotImplemented())
5052
51 def delete(self, req, server_id, id):53 def delete(self, req, server_id, id):
52 """ Deletes an existing backup schedule """54 """ Deletes an existing backup schedule """
53 return faults.Fault(exc.HTTPNotFound())55 return faults.Fault(exc.HTTPNotImplemented())
5456
=== modified file 'nova/api/openstack/common.py'
--- nova/api/openstack/common.py 2010-12-23 19:17:53 +0000
+++ nova/api/openstack/common.py 2011-01-11 19:42:14 +0000
@@ -15,6 +15,8 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18from nova import exception
19
1820
19def limited(items, req):21def limited(items, req):
20 """Return a slice of items according to requested offset and limit.22 """Return a slice of items according to requested offset and limit.
@@ -34,3 +36,25 @@
34 limit = min(1000, limit)36 limit = min(1000, limit)
35 range_end = offset + limit37 range_end = offset + limit
36 return items[offset:range_end]38 return items[offset:range_end]
39
40
41def get_image_id_from_image_hash(image_service, context, image_hash):
42 """Given an Image ID Hash, return an objectstore Image ID.
43
44 image_service - reference to objectstore compatible image service.
45 context - security context for image service requests.
46 image_hash - hash of the image ID.
47 """
48
49 # FIX(sandy): This is terribly inefficient. It pulls all images
50 # from objectstore in order to find the match. ObjectStore
51 # should have a numeric counterpart to the string ID.
52 try:
53 items = image_service.detail(context)
54 except NotImplementedError:
55 items = image_service.index(context)
56 for image in items:
57 image_id = image['imageId']
58 if abs(hash(image_id)) == int(image_hash):
59 return image_id
60 raise exception.NotFound(image_hash)
3761
=== modified file 'nova/api/openstack/images.py'
--- nova/api/openstack/images.py 2010-12-31 03:55:00 +0000
+++ nova/api/openstack/images.py 2011-01-11 19:42:14 +0000
@@ -15,6 +15,8 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18import logging
19
18from webob import exc20from webob import exc
1921
20from nova import compute22from nova import compute
@@ -26,6 +28,7 @@
26from nova.api.openstack import faults28from nova.api.openstack import faults
27import nova.image.service29import nova.image.service
2830
31
29FLAGS = flags.FLAGS32FLAGS = flags.FLAGS
3033
3134
@@ -88,6 +91,12 @@
88 return dict((k, v) for k, v in item.iteritems() if k in keys)91 return dict((k, v) for k, v in item.iteritems() if k in keys)
8992
9093
94def _convert_image_id_to_hash(image):
95 image_id = abs(hash(image['imageId']))
96 image['imageId'] = image_id
97 image['id'] = image_id
98
99
91class Controller(wsgi.Controller):100class Controller(wsgi.Controller):
92101
93 _serialization_metadata = {102 _serialization_metadata = {
@@ -112,6 +121,9 @@
112 items = self._service.detail(req.environ['nova.context'])121 items = self._service.detail(req.environ['nova.context'])
113 except NotImplementedError:122 except NotImplementedError:
114 items = self._service.index(req.environ['nova.context'])123 items = self._service.index(req.environ['nova.context'])
124 for image in items:
125 _convert_image_id_to_hash(image)
126
115 items = common.limited(items, req)127 items = common.limited(items, req)
116 items = [_translate_keys(item) for item in items]128 items = [_translate_keys(item) for item in items]
117 items = [_translate_status(item) for item in items]129 items = [_translate_status(item) for item in items]
@@ -119,7 +131,12 @@
119131
120 def show(self, req, id):132 def show(self, req, id):
121 """Return data about the given image id"""133 """Return data about the given image id"""
122 return dict(image=self._service.show(req.environ['nova.context'], id))134 image_id = common.get_image_id_from_image_hash(self._service,
135 req.environ['nova.context'], id)
136
137 image = self._service.show(req.environ['nova.context'], image_id)
138 _convert_image_id_to_hash(image)
139 return dict(image=image)
123140
124 def delete(self, req, id):141 def delete(self, req, id):
125 # Only public images are supported for now.142 # Only public images are supported for now.
126143
=== modified file 'nova/api/openstack/servers.py'
--- nova/api/openstack/servers.py 2011-01-07 14:46:17 +0000
+++ nova/api/openstack/servers.py 2011-01-11 19:42:14 +0000
@@ -15,14 +15,17 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18import json
18import traceback19import traceback
1920
20from webob import exc21from webob import exc
2122
22from nova import compute23from nova import compute
23from nova import exception24from nova import exception
25from nova import flags
24from nova import log as logging26from nova import log as logging
25from nova import wsgi27from nova import wsgi
28from nova import utils
26from nova.api.openstack import common29from nova.api.openstack import common
27from nova.api.openstack import faults30from nova.api.openstack import faults
28from nova.auth import manager as auth_manager31from nova.auth import manager as auth_manager
@@ -35,6 +38,9 @@
35LOG.setLevel(logging.DEBUG)38LOG.setLevel(logging.DEBUG)
3639
3740
41FLAGS = flags.FLAGS
42
43
38def _translate_detail_keys(inst):44def _translate_detail_keys(inst):
39 """ Coerces into dictionary format, mapping everything to Rackspace-like45 """ Coerces into dictionary format, mapping everything to Rackspace-like
40 attributes for return"""46 attributes for return"""
@@ -44,7 +50,7 @@
44 power_state.RUNNING: 'active',50 power_state.RUNNING: 'active',
45 power_state.BLOCKED: 'active',51 power_state.BLOCKED: 'active',
46 power_state.SUSPENDED: 'suspended',52 power_state.SUSPENDED: 'suspended',
47 power_state.PAUSED: 'error',53 power_state.PAUSED: 'paused',
48 power_state.SHUTDOWN: 'active',54 power_state.SHUTDOWN: 'active',
49 power_state.SHUTOFF: 'active',55 power_state.SHUTOFF: 'active',
50 power_state.CRASHED: 'error'}56 power_state.CRASHED: 'error'}
@@ -81,6 +87,7 @@
8187
82 def __init__(self):88 def __init__(self):
83 self.compute_api = compute.API()89 self.compute_api = compute.API()
90 self._image_service = utils.import_object(FLAGS.image_service)
84 super(Controller, self).__init__()91 super(Controller, self).__init__()
8592
86 def index(self, req):93 def index(self, req):
@@ -117,6 +124,18 @@
117 return faults.Fault(exc.HTTPNotFound())124 return faults.Fault(exc.HTTPNotFound())
118 return exc.HTTPAccepted()125 return exc.HTTPAccepted()
119126
127 def _get_kernel_ramdisk_from_image(self, image_id):
128 mapping_filename = FLAGS.os_krm_mapping_file
129
130 with open(mapping_filename) as f:
131 mapping = json.load(f)
132 if image_id in mapping:
133 return mapping[image_id]
134
135 raise exception.NotFound(
136 _("No entry for image '%s' in mapping file '%s'") %
137 (image_id, mapping_filename))
138
120 def create(self, req):139 def create(self, req):
121 """ Creates a new server for a given user """140 """ Creates a new server for a given user """
122 env = self._deserialize(req.body, req)141 env = self._deserialize(req.body, req)
@@ -125,10 +144,15 @@
125144
126 key_pair = auth_manager.AuthManager.get_key_pairs(145 key_pair = auth_manager.AuthManager.get_key_pairs(
127 req.environ['nova.context'])[0]146 req.environ['nova.context'])[0]
147 image_id = common.get_image_id_from_image_hash(self._image_service,
148 req.environ['nova.context'], env['server']['imageId'])
149 kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(image_id)
128 instances = self.compute_api.create(150 instances = self.compute_api.create(
129 req.environ['nova.context'],151 req.environ['nova.context'],
130 instance_types.get_by_flavor_id(env['server']['flavorId']),152 instance_types.get_by_flavor_id(env['server']['flavorId']),
131 env['server']['imageId'],153 image_id,
154 kernel_id=kernel_id,
155 ramdisk_id=ramdisk_id,
132 display_name=env['server']['name'],156 display_name=env['server']['name'],
133 display_description=env['server']['name'],157 display_description=env['server']['name'],
134 key_name=key_pair['name'],158 key_name=key_pair['name'],
@@ -158,6 +182,7 @@
158 """ Multi-purpose method used to reboot, rebuild, and182 """ Multi-purpose method used to reboot, rebuild, and
159 resize a server """183 resize a server """
160 input_dict = self._deserialize(req.body, req)184 input_dict = self._deserialize(req.body, req)
185 #TODO(sandy): rebuild/resize not supported.
161 try:186 try:
162 reboot_type = input_dict['reboot']['type']187 reboot_type = input_dict['reboot']['type']
163 except Exception:188 except Exception:
164189
=== renamed file 'nova/api/openstack/sharedipgroups.py' => 'nova/api/openstack/shared_ip_groups.py'
--- nova/api/openstack/sharedipgroups.py 2010-12-28 21:48:48 +0000
+++ nova/api/openstack/shared_ip_groups.py 2011-01-11 19:42:14 +0000
@@ -15,6 +15,8 @@
15# License for the specific language governing permissions and limitations15# License for the specific language governing permissions and limitations
16# under the License.16# under the License.
1717
18import logging
19
18from webob import exc20from webob import exc
1921
20from nova import wsgi22from nova import wsgi
@@ -29,7 +31,7 @@
29def _translate_detail_keys(inst):31def _translate_detail_keys(inst):
30 """ Coerces a shared IP group instance into proper dictionary format with32 """ Coerces a shared IP group instance into proper dictionary format with
31 correctly mapped attributes """33 correctly mapped attributes """
32 return dict(sharedIpGroup=inst)34 return dict(sharedIpGroups=inst)
3335
3436
35class Controller(wsgi.Controller):37class Controller(wsgi.Controller):
@@ -54,12 +56,12 @@
5456
55 def delete(self, req, id):57 def delete(self, req, id):
56 """ Deletes a Shared IP Group """58 """ Deletes a Shared IP Group """
57 raise faults.Fault(exc.HTTPNotFound())59 raise faults.Fault(exc.HTTPNotImplemented())
5860
59 def detail(self, req, id):61 def detail(self, req):
60 """ Returns a complete list of Shared IP Groups """62 """ Returns a complete list of Shared IP Groups """
61 return _translate_detail_keys({})63 return _translate_detail_keys({})
6264
63 def create(self, req):65 def create(self, req):
64 """ Creates a new Shared IP group """66 """ Creates a new Shared IP group """
65 raise faults.Fault(exc.HTTPNotFound())67 raise faults.Fault(exc.HTTPNotImplemented())
6668
=== modified file 'nova/auth/manager.py'
--- nova/auth/manager.py 2011-01-04 05:26:41 +0000
+++ nova/auth/manager.py 2011-01-11 19:42:14 +0000
@@ -684,8 +684,7 @@
684 else:684 else:
685 regions = {'nova': FLAGS.cc_host}685 regions = {'nova': FLAGS.cc_host}
686 for region, host in regions.iteritems():686 for region, host in regions.iteritems():
687 rc = self.__generate_rc(user.access,687 rc = self.__generate_rc(user,
688 user.secret,
689 pid,688 pid,
690 use_dmz,689 use_dmz,
691 host)690 host)
@@ -725,7 +724,7 @@
725 return self.__generate_rc(user.access, user.secret, pid, use_dmz)724 return self.__generate_rc(user.access, user.secret, pid, use_dmz)
726725
727 @staticmethod726 @staticmethod
728 def __generate_rc(access, secret, pid, use_dmz=True, host=None):727 def __generate_rc(user, pid, use_dmz=True, host=None):
729 """Generate rc file for user"""728 """Generate rc file for user"""
730 if use_dmz:729 if use_dmz:
731 cc_host = FLAGS.cc_dmz730 cc_host = FLAGS.cc_dmz
@@ -738,14 +737,19 @@
738 s3_host = host737 s3_host = host
739 cc_host = host738 cc_host = host
740 rc = open(FLAGS.credentials_template).read()739 rc = open(FLAGS.credentials_template).read()
741 rc = rc % {'access': access,740 rc = rc % {'access': user.access,
742 'project': pid,741 'project': pid,
743 'secret': secret,742 'secret': user.secret,
744 'ec2': '%s://%s:%s%s' % (FLAGS.ec2_prefix,743 'ec2': '%s://%s:%s%s' % (FLAGS.ec2_prefix,
745 cc_host,744 cc_host,
746 FLAGS.cc_port,745 FLAGS.cc_port,
747 FLAGS.ec2_suffix),746 FLAGS.ec2_suffix),
748 's3': 'http://%s:%s' % (s3_host, FLAGS.s3_port),747 's3': 'http://%s:%s' % (s3_host, FLAGS.s3_port),
748 'os': '%s://%s:%s%s' % (FLAGS.os_prefix,
749 cc_host,
750 FLAGS.cc_port,
751 FLAGS.os_suffix),
752 'user': user.name,
749 'nova': FLAGS.ca_file,753 'nova': FLAGS.ca_file,
750 'cert': FLAGS.credential_cert_file,754 'cert': FLAGS.credential_cert_file,
751 'key': FLAGS.credential_key_file}755 'key': FLAGS.credential_key_file}
752756
=== modified file 'nova/auth/novarc.template'
--- nova/auth/novarc.template 2010-07-15 15:52:11 +0000
+++ nova/auth/novarc.template 2011-01-11 19:42:14 +0000
@@ -10,3 +10,7 @@
10export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set10export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set
11alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}"11alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}"
12alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}"12alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}"
13export CLOUD_SERVERS_API_KEY="%(access)s"
14export CLOUD_SERVERS_USERNAME="%(user)s"
15export CLOUD_SERVERS_URL="%(os)s"
16
1317
=== modified file 'nova/compute/api.py'
--- nova/compute/api.py 2011-01-08 14:35:50 +0000
+++ nova/compute/api.py 2011-01-11 19:42:14 +0000
@@ -108,6 +108,8 @@
108 ramdisk_id = None108 ramdisk_id = None
109 LOG.debug(_("Creating a raw instance"))109 LOG.debug(_("Creating a raw instance"))
110 # Make sure we have access to kernel and ramdisk (if not raw)110 # Make sure we have access to kernel and ramdisk (if not raw)
111 logging.debug("Using Kernel=%s, Ramdisk=%s" %
112 (kernel_id, ramdisk_id))
111 if kernel_id:113 if kernel_id:
112 self.image_service.show(context, kernel_id)114 self.image_service.show(context, kernel_id)
113 if ramdisk_id:115 if ramdisk_id:
@@ -171,7 +173,8 @@
171173
172 # Set sane defaults if not specified174 # Set sane defaults if not specified
173 updates = dict(hostname=generate_hostname(instance_id))175 updates = dict(hostname=generate_hostname(instance_id))
174 if 'display_name' not in instance:176 if (not hasattr(instance, 'display_name')) or \
177 instance.display_name == None:
175 updates['display_name'] = "Server %s" % instance_id178 updates['display_name'] = "Server %s" % instance_id
176179
177 instance = self.update(context, instance_id, **updates)180 instance = self.update(context, instance_id, **updates)
178181
=== modified file 'nova/flags.py'
--- nova/flags.py 2011-01-11 12:24:58 +0000
+++ nova/flags.py 2011-01-11 19:42:14 +0000
@@ -248,10 +248,12 @@
248DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')248DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts')
249DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')249DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to')
250DEFINE_string('ec2_prefix', 'http', 'prefix for ec2')250DEFINE_string('ec2_prefix', 'http', 'prefix for ec2')
251DEFINE_string('os_prefix', 'http', 'prefix for openstack')
251DEFINE_string('cc_host', '$my_ip', 'ip of api server')252DEFINE_string('cc_host', '$my_ip', 'ip of api server')
252DEFINE_string('cc_dmz', '$my_ip', 'internal ip of api server')253DEFINE_string('cc_dmz', '$my_ip', 'internal ip of api server')
253DEFINE_integer('cc_port', 8773, 'cloud controller port')254DEFINE_integer('cc_port', 8773, 'cloud controller port')
254DEFINE_string('ec2_suffix', '/services/Cloud', 'suffix for ec2')255DEFINE_string('ec2_suffix', '/services/Cloud', 'suffix for ec2')
256DEFINE_string('os_suffix', '/v1.0/', 'suffix for openstack')
255257
256DEFINE_string('default_project', 'openstack', 'default project for openstack')258DEFINE_string('default_project', 'openstack', 'default project for openstack')
257DEFINE_string('default_image', 'ami-11111',259DEFINE_string('default_image', 'ami-11111',
258260
=== modified file 'nova/tests/api/openstack/test_images.py'
--- nova/tests/api/openstack/test_images.py 2011-01-04 05:23:35 +0000
+++ nova/tests/api/openstack/test_images.py 2011-01-11 19:42:14 +0000
@@ -172,6 +172,7 @@
172172
173 IMAGE_FIXTURES = [173 IMAGE_FIXTURES = [
174 {'id': '23g2ogk23k4hhkk4k42l',174 {'id': '23g2ogk23k4hhkk4k42l',
175 'imageId': '23g2ogk23k4hhkk4k42l',
175 'name': 'public image #1',176 'name': 'public image #1',
176 'created_at': str(datetime.datetime.utcnow()),177 'created_at': str(datetime.datetime.utcnow()),
177 'updated_at': str(datetime.datetime.utcnow()),178 'updated_at': str(datetime.datetime.utcnow()),
@@ -181,6 +182,7 @@
181 'status': 'available',182 'status': 'available',
182 'image_type': 'kernel'},183 'image_type': 'kernel'},
183 {'id': 'slkduhfas73kkaskgdas',184 {'id': 'slkduhfas73kkaskgdas',
185 'imageId': 'slkduhfas73kkaskgdas',
184 'name': 'public image #2',186 'name': 'public image #2',
185 'created_at': str(datetime.datetime.utcnow()),187 'created_at': str(datetime.datetime.utcnow()),
186 'updated_at': str(datetime.datetime.utcnow()),188 'updated_at': str(datetime.datetime.utcnow()),
187189
=== modified file 'nova/tests/api/openstack/test_servers.py'
--- nova/tests/api/openstack/test_servers.py 2011-01-06 22:35:48 +0000
+++ nova/tests/api/openstack/test_servers.py 2011-01-11 19:42:14 +0000
@@ -133,6 +133,12 @@
133 def queue_get_for(context, *args):133 def queue_get_for(context, *args):
134 return 'network_topic'134 return 'network_topic'
135135
136 def kernel_ramdisk_mapping(*args, **kwargs):
137 return (1, 1)
138
139 def image_id_from_hash(*args, **kwargs):
140 return 2
141
136 self.stubs.Set(nova.db.api, 'project_get_network', project_get_network)142 self.stubs.Set(nova.db.api, 'project_get_network', project_get_network)
137 self.stubs.Set(nova.db.api, 'instance_create', instance_create)143 self.stubs.Set(nova.db.api, 'instance_create', instance_create)
138 self.stubs.Set(nova.rpc, 'cast', fake_method)144 self.stubs.Set(nova.rpc, 'cast', fake_method)
@@ -142,6 +148,10 @@
142 self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for)148 self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for)
143 self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip',149 self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip',
144 fake_method)150 fake_method)
151 self.stubs.Set(nova.api.openstack.servers.Controller,
152 "_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping)
153 self.stubs.Set(nova.api.openstack.common,
154 "get_image_id_from_image_hash", image_id_from_hash)
145155
146 body = dict(server=dict(156 body = dict(server=dict(
147 name='server_test', imageId=2, flavorId=2, metadata={},157 name='server_test', imageId=2, flavorId=2, metadata={},
148158
=== renamed file 'nova/tests/api/openstack/test_sharedipgroups.py' => 'nova/tests/api/openstack/test_shared_ip_groups.py'
--- nova/tests/api/openstack/test_sharedipgroups.py 2010-10-08 20:39:00 +0000
+++ nova/tests/api/openstack/test_shared_ip_groups.py 2011-01-11 19:42:14 +0000
@@ -19,7 +19,7 @@
1919
20import stubout20import stubout
2121
22from nova.api.openstack import sharedipgroups22from nova.api.openstack import shared_ip_groups
2323
2424
25class SharedIpGroupsTest(unittest.TestCase):25class SharedIpGroupsTest(unittest.TestCase):
2626
=== modified file 'nova/virt/xenapi/vm_utils.py'
--- nova/virt/xenapi/vm_utils.py 2011-01-04 05:23:35 +0000
+++ nova/virt/xenapi/vm_utils.py 2011-01-11 19:42:14 +0000
@@ -357,7 +357,9 @@
357 if i >= 3 and i <= 11:357 if i >= 3 and i <= 11:
358 ref = node.childNodes358 ref = node.childNodes
359 # Name and Value359 # Name and Value
360 diags[ref[0].firstChild.data] = ref[6].firstChild.data360 if len(ref) > 6:
361 diags[ref[0].firstChild.data] = \
362 ref[6].firstChild.data
361 return diags363 return diags
362 except cls.XenAPI.Failure as e:364 except cls.XenAPI.Failure as e:
363 return {"Unable to retrieve diagnostics": e}365 return {"Unable to retrieve diagnostics": e}