Sync trunk

This commit is contained in:
Donal Lafferty
2011-08-07 21:42:46 +01:00
6 changed files with 233 additions and 9 deletions

View File

@@ -592,6 +592,31 @@ class FixedIpCommands(object):
fixed_ip['address'], fixed_ip['address'],
mac_address, hostname, host) mac_address, hostname, host)
@args('--address', dest="address", metavar='<ip address>',
help='IP address')
def reserve(self, address):
"""Mark fixed ip as reserved
arguments: address"""
self._set_reserved(address, True)
@args('--address', dest="address", metavar='<ip address>',
help='IP address')
def unreserve(self, address):
"""Mark fixed ip as free to use
arguments: address"""
self._set_reserved(address, False)
def _set_reserved(self, address, reserved):
ctxt = context.get_admin_context()
try:
fixed_ip = db.fixed_ip_get_by_address(ctxt, address)
db.fixed_ip_update(ctxt, fixed_ip['address'],
{'reserved': reserved})
except exception.NotFound as ex:
print "error: %s" % ex
sys.exit(2)
class FloatingIpCommands(object): class FloatingIpCommands(object):
"""Class for managing floating ip.""" """Class for managing floating ip."""
@@ -1235,11 +1260,12 @@ class ImageCommands(object):
is_public, architecture) is_public, architecture)
def _lookup(self, old_image_id): def _lookup(self, old_image_id):
elevated = context.get_admin_context()
try: try:
internal_id = ec2utils.ec2_id_to_id(old_image_id) internal_id = ec2utils.ec2_id_to_id(old_image_id)
image = self.image_service.show(context, internal_id) image = self.image_service.show(elevated, internal_id)
except (exception.InvalidEc2Id, exception.ImageNotFound): except (exception.InvalidEc2Id, exception.ImageNotFound):
image = self.image_service.show_by_name(context, old_image_id) image = self.image_service.show_by_name(elevated, old_image_id)
return image['id'] return image['id']
def _old_to_new(self, old): def _old_to_new(self, old):

View File

@@ -58,12 +58,13 @@ class ZoneAwareScheduler(driver.Scheduler):
"""Create the requested resource in this Zone.""" """Create the requested resource in this Zone."""
host = build_plan_item['hostname'] host = build_plan_item['hostname']
base_options = request_spec['instance_properties'] base_options = request_spec['instance_properties']
image = request_spec['image']
# TODO(sandy): I guess someone needs to add block_device_mapping # TODO(sandy): I guess someone needs to add block_device_mapping
# support at some point? Also, OS API has no concept of security # support at some point? Also, OS API has no concept of security
# groups. # groups.
instance = compute_api.API().create_db_entry_for_new_instance(context, instance = compute_api.API().create_db_entry_for_new_instance(context,
base_options, None, []) image, base_options, None, [])
instance_id = instance['id'] instance_id = instance['id']
kwargs['instance_id'] = instance_id kwargs['instance_id'] = instance_id

View File

@@ -21,7 +21,9 @@ import json
import nova.db import nova.db
from nova import exception from nova import exception
from nova import rpc
from nova import test from nova import test
from nova.compute import api as compute_api
from nova.scheduler import driver from nova.scheduler import driver
from nova.scheduler import zone_aware_scheduler from nova.scheduler import zone_aware_scheduler
from nova.scheduler import zone_manager from nova.scheduler import zone_manager
@@ -114,7 +116,7 @@ def fake_provision_resource_from_blob(context, item, instance_id,
def fake_decrypt_blob_returns_local_info(blob): def fake_decrypt_blob_returns_local_info(blob):
return {'foo': True} # values aren't important. return {'hostname': 'foooooo'} # values aren't important.
def fake_decrypt_blob_returns_child_info(blob): def fake_decrypt_blob_returns_child_info(blob):
@@ -283,14 +285,29 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
global was_called global was_called
sched = FakeZoneAwareScheduler() sched = FakeZoneAwareScheduler()
was_called = False was_called = False
def fake_create_db_entry_for_new_instance(self, context,
image, base_options, security_group,
block_device_mapping, num=1):
global was_called
was_called = True
# return fake instances
return {'id': 1, 'uuid': 'f874093c-7b17-49c0-89c3-22a5348497f9'}
def fake_rpc_cast(*args, **kwargs):
pass
self.stubs.Set(sched, '_decrypt_blob', self.stubs.Set(sched, '_decrypt_blob',
fake_decrypt_blob_returns_local_info) fake_decrypt_blob_returns_local_info)
self.stubs.Set(sched, '_provision_resource_locally', self.stubs.Set(compute_api.API,
fake_provision_resource_locally) 'create_db_entry_for_new_instance',
fake_create_db_entry_for_new_instance)
self.stubs.Set(rpc, 'cast', fake_rpc_cast)
request_spec = {'blob': "Non-None blob data"} build_plan_item = {'blob': "Non-None blob data"}
request_spec = {'image': {}, 'instance_properties': {}}
sched._provision_resource_from_blob(None, request_spec, 1, sched._provision_resource_from_blob(None, build_plan_item, 1,
request_spec, {}) request_spec, {})
self.assertTrue(was_called) self.assertTrue(was_called)

134
nova/tests/test_image.py Normal file
View File

@@ -0,0 +1,134 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack LLC
# Author: Soren Hansen
#
# 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.
import datetime
from nova import context
from nova import exception
from nova import test
import nova.image
class _ImageTestCase(test.TestCase):
def setUp(self):
super(_ImageTestCase, self).setUp()
self.context = context.get_admin_context()
def test_index(self):
res = self.image_service.index(self.context)
for image in res:
self.assertEquals(set(image.keys()), set(['id', 'name']))
def test_detail(self):
res = self.image_service.detail(self.context)
for image in res:
keys = set(image.keys())
self.assertEquals(keys, set(['id', 'name', 'created_at',
'updated_at', 'deleted_at', 'deleted',
'status', 'is_public', 'properties']))
self.assertTrue(isinstance(image['created_at'], datetime.datetime))
self.assertTrue(isinstance(image['updated_at'], datetime.datetime))
if not (isinstance(image['deleted_at'], datetime.datetime) or
image['deleted_at'] is None):
self.fail('image\'s "deleted_at" attribute was neither a '
'datetime object nor None')
def check_is_bool(image, key):
val = image.get('deleted')
if not isinstance(val, bool):
self.fail('image\'s "%s" attribute wasn\'t '
'a bool: %r' % (key, val))
check_is_bool(image, 'deleted')
check_is_bool(image, 'is_public')
def test_index_and_detail_have_same_results(self):
index = self.image_service.index(self.context)
detail = self.image_service.detail(self.context)
index_set = set([(i['id'], i['name']) for i in index])
detail_set = set([(i['id'], i['name']) for i in detail])
self.assertEqual(index_set, detail_set)
def test_show_raises_imagenotfound_for_invalid_id(self):
self.assertRaises(exception.ImageNotFound,
self.image_service.show,
self.context,
'this image does not exist')
def test_show_by_name(self):
self.assertRaises(exception.ImageNotFound,
self.image_service.show_by_name,
self.context,
'this image does not exist')
def test_create_adds_id(self):
index = self.image_service.index(self.context)
image_count = len(index)
self.image_service.create(self.context, {})
index = self.image_service.index(self.context)
self.assertEquals(len(index), image_count + 1)
self.assertTrue(index[0]['id'])
def test_create_keeps_id(self):
self.image_service.create(self.context, {'id': '34'})
self.image_service.show(self.context, '34')
def test_create_rejects_duplicate_ids(self):
self.image_service.create(self.context, {'id': '34'})
self.assertRaises(exception.Duplicate,
self.image_service.create,
self.context,
{'id': '34'})
# Make sure there's still one left
self.image_service.show(self.context, '34')
def test_update(self):
self.image_service.create(self.context,
{'id': '34', 'foo': 'bar'})
self.image_service.update(self.context, '34',
{'id': '34', 'foo': 'baz'})
img = self.image_service.show(self.context, '34')
self.assertEquals(img['foo'], 'baz')
def test_delete(self):
self.image_service.create(self.context, {'id': '34', 'foo': 'bar'})
self.image_service.delete(self.context, '34')
self.assertRaises(exception.NotFound,
self.image_service.show,
self.context,
'34')
def test_delete_all(self):
self.image_service.create(self.context, {'id': '32', 'foo': 'bar'})
self.image_service.create(self.context, {'id': '33', 'foo': 'bar'})
self.image_service.create(self.context, {'id': '34', 'foo': 'bar'})
self.image_service.delete_all()
index = self.image_service.index(self.context)
self.assertEquals(len(index), 0)
class FakeImageTestCase(_ImageTestCase):
def setUp(self):
super(FakeImageTestCase, self).setUp()
self.image_service = nova.image.fake.FakeImageService()

View File

@@ -0,0 +1,47 @@
# 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.
from nova import test
class ExampleSkipTestCase(test.TestCase):
test_counter = 0
@test.skip_test("Example usage of @test.skip_test()")
def test_skip_test_example(self):
self.fail("skip_test failed to work properly.")
@test.skip_if(True, "Example usage of @test.skip_if()")
def test_skip_if_example(self):
self.fail("skip_if failed to work properly.")
@test.skip_unless(False, "Example usage of @test.skip_unless()")
def test_skip_unless_example(self):
self.fail("skip_unless failed to work properly.")
@test.skip_if(False, "This test case should never be skipped.")
def test_001_increase_test_counter(self):
ExampleSkipTestCase.test_counter += 1
@test.skip_unless(True, "This test case should never be skipped.")
def test_002_increase_test_counter(self):
ExampleSkipTestCase.test_counter += 1
def test_003_verify_test_counter(self):
self.assertEquals(ExampleSkipTestCase.test_counter, 2,
"Tests were not skipped appropriately")

View File

@@ -772,7 +772,6 @@ class XenAPIMigrateInstance(test.TestCase):
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
conn.migrate_disk_and_power_off(instance, '127.0.0.1') conn.migrate_disk_and_power_off(instance, '127.0.0.1')
def test_revert_migrate(self): def test_revert_migrate(self):
instance = db.instance_create(self.context, self.values) instance = db.instance_create(self.context, self.values)
self.called = False self.called = False