merged with nova-1411

This commit is contained in:
vladimir.p
2011-08-09 15:21:46 -07:00
16 changed files with 836 additions and 39 deletions

View File

@@ -18,6 +18,8 @@
<devin.carlen@gmail.com> <devcamcar@illian.local>
<ewan.mellor@citrix.com> <emellor@silver>
<itoumsn@nttdata.co.jp> <itoumsn@shayol>
<jake@ansolabs.com> <jake@markupisart.com>
<jake@ansolabs.com> <admin@jakedahn.com>
<jaypipes@gmail.com> <jpipes@serialcoder>
<jmckenty@gmail.com> <jmckenty@joshua-mckentys-macbook-pro.local>
<jmckenty@gmail.com> <jmckenty@yyj-dhcp171.corp.flock.com>

View File

@@ -37,6 +37,7 @@ Hisaharu Ishii <ishii.hisaharu@lab.ntt.co.jp>
Hisaki Ohara <hisaki.ohara@intel.com>
Ilya Alekseyev <ilyaalekseyev@acm.org>
Isaku Yamahata <yamahata@valinux.co.jp>
Jake Dahn <jake@ansolabs.com>
Jason Cannavale <jason.cannavale@rackspace.com>
Jason Koelker <jason@koelker.net>
Jay Pipes <jaypipes@gmail.com>

View File

@@ -10,6 +10,7 @@ graft bzrplugins
graft contrib
graft po
graft plugins
graft nova/api/openstack/schemas
include nova/api/openstack/notes.txt
include nova/auth/*.schema
include nova/auth/novarc.template

View File

@@ -732,8 +732,7 @@ class NetworkCommands(object):
network_size = FLAGS.network_size
subnet = 32 - int(math.log(network_size, 2))
oversize_msg = _('Subnet(s) too large, defaulting to /%s.'
' To override, specify network_size flag.'
) % subnet
' To override, specify network_size flag.') % subnet
print oversize_msg
else:
network_size = fixnet.size
@@ -1411,10 +1410,12 @@ class InstanceTypeCommands(object):
@args('--name', dest='name', metavar='<name>',
help='Name of instance type/flavor')
def delete(self, name, purge=None):
@args('--purge', action="store_true", dest='purge', default=False,
help='purge record from database')
def delete(self, name, purge):
"""Marks instance types / flavors as deleted"""
try:
if purge == "--purge":
if purge:
instance_types.purge(name)
verb = "purged"
else:

View File

@@ -16,3 +16,4 @@ export NOVA_API_KEY="%(access)s"
export NOVA_USERNAME="%(user)s"
export NOVA_PROJECT_ID="%(project)s"
export NOVA_URL="%(os)s"
export NOVA_VERSION="1.1"

View File

@@ -318,7 +318,7 @@ DEFINE_string('osapi_extensions_path', '/var/lib/nova/extensions',
DEFINE_string('osapi_host', '$my_ip', 'ip of api server')
DEFINE_string('osapi_scheme', 'http', 'prefix for openstack')
DEFINE_integer('osapi_port', 8774, 'OpenStack API port')
DEFINE_string('osapi_path', '/v1.0/', 'suffix for openstack')
DEFINE_string('osapi_path', '/v1.1/', 'suffix for openstack')
DEFINE_integer('osapi_max_limit', 1000,
'max number of items returned in a collection response')

View File

@@ -17,7 +17,8 @@
Handles all requests relating to schedulers.
"""
import novaclient
from novaclient import v1_1 as novaclient
from novaclient import exceptions as novaclient_exceptions
from nova import db
from nova import exception
@@ -112,7 +113,7 @@ def _wrap_method(function, self):
def _process(func, zone):
"""Worker stub for green thread pool. Give the worker
an authenticated nova client and zone info."""
nova = novaclient.OpenStack(zone.username, zone.password, None,
nova = novaclient.Client(zone.username, zone.password, None,
zone.api_url)
nova.authenticate()
return func(nova, zone)
@@ -132,10 +133,10 @@ def call_zone_method(context, method_name, errors_to_ignore=None,
zones = db.zone_get_all(context)
for zone in zones:
try:
nova = novaclient.OpenStack(zone.username, zone.password, None,
nova = novaclient.Client(zone.username, zone.password, None,
zone.api_url)
nova.authenticate()
except novaclient.exceptions.BadRequest, e:
except novaclient_exceptions.BadRequest, e:
url = zone.api_url
LOG.warn(_("Failed request to zone; URL=%(url)s: %(e)s")
% locals())
@@ -188,7 +189,7 @@ def _issue_novaclient_command(nova, zone, collection,
if method_name in ['find', 'findall']:
try:
return getattr(manager, method_name)(**kwargs)
except novaclient.NotFound:
except novaclient_exceptions.NotFound:
url = zone.api_url
LOG.debug(_("%(collection)s.%(method_name)s didn't find "
"anything matching '%(kwargs)s' on '%(url)s'" %
@@ -200,7 +201,7 @@ def _issue_novaclient_command(nova, zone, collection,
item = args.pop(0)
try:
result = manager.get(item)
except novaclient.NotFound:
except novaclient_exceptions.NotFound:
url = zone.api_url
LOG.debug(_("%(collection)s '%(item)s' not found on '%(url)s'" %
locals()))

View File

@@ -24,7 +24,9 @@ import operator
import json
import M2Crypto
import novaclient
from novaclient import v1_1 as novaclient
from novaclient import exceptions as novaclient_exceptions
from nova import crypto
from nova import db
@@ -118,10 +120,9 @@ class ZoneAwareScheduler(driver.Scheduler):
% locals())
nova = None
try:
nova = novaclient.OpenStack(zone.username, zone.password, None,
url)
nova = novaclient.Client(zone.username, zone.password, None, url)
nova.authenticate()
except novaclient.exceptions.BadRequest, e:
except novaclient_exceptions.BadRequest, e:
raise exception.NotAuthorized(_("Bad credentials attempting "
"to talk to zone at %(url)s.") % locals())

View File

@@ -18,10 +18,11 @@ ZoneManager oversees all communications with child Zones.
"""
import datetime
import novaclient
import thread
import traceback
from novaclient import v1_1 as novaclient
from eventlet import greenpool
from nova import db
@@ -89,8 +90,8 @@ class ZoneState(object):
def _call_novaclient(zone):
"""Call novaclient. Broken out for testing purposes."""
client = novaclient.OpenStack(zone.username, zone.password, None,
zone.api_url)
client = novaclient.Client(zone.username, zone.password, None,
zone.api_url)
return client.zones.info()._info

View File

@@ -27,6 +27,7 @@ import random
import StringIO
import webob
from nova import block_device
from nova import context
from nova import exception
from nova import test
@@ -147,10 +148,12 @@ class Ec2utilsTestCase(test.TestCase):
properties0 = {'mappings': mappings}
properties1 = {'root_device_name': '/dev/sdb', 'mappings': mappings}
root_device_name = ec2utils.properties_root_device_name(properties0)
root_device_name = block_device.properties_root_device_name(
properties0)
self.assertEqual(root_device_name, '/dev/sda1')
root_device_name = ec2utils.properties_root_device_name(properties1)
root_device_name = block_device.properties_root_device_name(
properties1)
self.assertEqual(root_device_name, '/dev/sdb')
def test_mapping_prepend_dev(self):
@@ -184,7 +187,7 @@ class Ec2utilsTestCase(test.TestCase):
'device': '/dev/sdc1'},
{'virtual': 'ephemeral1',
'device': '/dev/sdc1'}]
self.assertDictListMatch(ec2utils.mappings_prepend_dev(mappings),
self.assertDictListMatch(block_device.mappings_prepend_dev(mappings),
expected_result)
@@ -336,6 +339,33 @@ class ApiEc2TestCase(test.TestCase):
self.ec2.delete_security_group(security_group_name)
def test_group_name_valid_chars_security_group(self):
""" Test that we sanely handle invalid security group names.
API Spec states we should only accept alphanumeric characters,
spaces, dashes, and underscores. """
self.expect_http()
self.mox.ReplayAll()
# Test block group_name of non alphanumeric characters, spaces,
# dashes, and underscores.
security_group_name = "aa #^% -=99"
self.assertRaises(EC2ResponseError, self.ec2.create_security_group,
security_group_name, 'test group')
def test_group_name_valid_length_security_group(self):
"""Test that we sanely handle invalid security group names.
API Spec states that the length should not exceed 255 chars """
self.expect_http()
self.mox.ReplayAll()
# Test block group_name > 255 chars
security_group_name = "".join(random.choice("poiuytrewqasdfghjklmnbvc")
for x in range(random.randint(256, 266)))
self.assertRaises(EC2ResponseError, self.ec2.create_security_group,
security_group_name, 'test group')
def test_authorize_revoke_security_group_cidr(self):
"""
Test that we can add and remove CIDR based rules

View File

@@ -17,6 +17,8 @@
# under the License.
import mox
import functools
from base64 import b64decode
from M2Crypto import BIO
from M2Crypto import RSA
@@ -892,13 +894,16 @@ class CloudTestCase(test.TestCase):
def test_modify_image_attribute(self):
modify_image_attribute = self.cloud.modify_image_attribute
fake_metadata = {'id': 1, 'container_format': 'ami',
'properties': {'kernel_id': 1, 'ramdisk_id': 1,
'type': 'machine'}, 'is_public': False}
def fake_show(meh, context, id):
return {'id': 1, 'container_format': 'ami',
'properties': {'kernel_id': 1, 'ramdisk_id': 1,
'type': 'machine'}, 'is_public': False}
return fake_metadata
def fake_update(meh, context, image_id, metadata, data=None):
return metadata
fake_metadata.update(metadata)
return fake_metadata
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
@@ -1464,3 +1469,147 @@ class CloudTestCase(test.TestCase):
# TODO(yamahata): clean up snapshot created by CreateImage.
self._restart_compute_service()
@staticmethod
def _fake_bdm_get(ctxt, id):
return [{'volume_id': 87654321,
'snapshot_id': None,
'no_device': None,
'virtual_name': None,
'delete_on_termination': True,
'device_name': '/dev/sdh'},
{'volume_id': None,
'snapshot_id': 98765432,
'no_device': None,
'virtual_name': None,
'delete_on_termination': True,
'device_name': '/dev/sdi'},
{'volume_id': None,
'snapshot_id': None,
'no_device': True,
'virtual_name': None,
'delete_on_termination': None,
'device_name': None},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'ephemeral0',
'delete_on_termination': None,
'device_name': '/dev/sdb'},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'swap',
'delete_on_termination': None,
'device_name': '/dev/sdc'},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'ephemeral1',
'delete_on_termination': None,
'device_name': '/dev/sdd'},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'ephemeral2',
'delete_on_termination': None,
'device_name': '/dev/sd3'},
]
def test_get_instance_mapping(self):
"""Make sure that _get_instance_mapping works"""
ctxt = None
instance_ref0 = {'id': 0,
'root_device_name': None}
instance_ref1 = {'id': 0,
'root_device_name': '/dev/sda1'}
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
self._fake_bdm_get)
expected = {'ami': 'sda1',
'root': '/dev/sda1',
'ephemeral0': '/dev/sdb',
'swap': '/dev/sdc',
'ephemeral1': '/dev/sdd',
'ephemeral2': '/dev/sd3'}
self.assertEqual(self.cloud._format_instance_mapping(ctxt,
instance_ref0),
cloud._DEFAULT_MAPPINGS)
self.assertEqual(self.cloud._format_instance_mapping(ctxt,
instance_ref1),
expected)
def test_describe_instance_attribute(self):
"""Make sure that describe_instance_attribute works"""
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
self._fake_bdm_get)
def fake_get(ctxt, instance_id):
return {
'id': 0,
'root_device_name': '/dev/sdh',
'security_groups': [{'name': 'fake0'}, {'name': 'fake1'}],
'state_description': 'stopping',
'instance_type': {'name': 'fake_type'},
'kernel_id': 1,
'ramdisk_id': 2,
'user_data': 'fake-user data',
}
self.stubs.Set(self.cloud.compute_api, 'get', fake_get)
def fake_volume_get(ctxt, volume_id, session=None):
if volume_id == 87654321:
return {'id': volume_id,
'attach_time': '13:56:24',
'status': 'in-use'}
raise exception.VolumeNotFound(volume_id=volume_id)
self.stubs.Set(db.api, 'volume_get', fake_volume_get)
get_attribute = functools.partial(
self.cloud.describe_instance_attribute,
self.context, 'i-12345678')
bdm = get_attribute('blockDeviceMapping')
bdm['blockDeviceMapping'].sort()
expected_bdm = {'instance_id': 'i-12345678',
'rootDeviceType': 'ebs',
'blockDeviceMapping': [
{'deviceName': '/dev/sdh',
'ebs': {'status': 'in-use',
'deleteOnTermination': True,
'volumeId': 87654321,
'attachTime': '13:56:24'}}]}
expected_bdm['blockDeviceMapping'].sort()
self.assertEqual(bdm, expected_bdm)
# NOTE(yamahata): this isn't supported
# get_attribute('disableApiTermination')
groupSet = get_attribute('groupSet')
groupSet['groupSet'].sort()
expected_groupSet = {'instance_id': 'i-12345678',
'groupSet': [{'groupId': 'fake0'},
{'groupId': 'fake1'}]}
expected_groupSet['groupSet'].sort()
self.assertEqual(groupSet, expected_groupSet)
self.assertEqual(get_attribute('instanceInitiatedShutdownBehavior'),
{'instance_id': 'i-12345678',
'instanceInitiatedShutdownBehavior': 'stop'})
self.assertEqual(get_attribute('instanceType'),
{'instance_id': 'i-12345678',
'instanceType': 'fake_type'})
self.assertEqual(get_attribute('kernel'),
{'instance_id': 'i-12345678',
'kernel': 'aki-00000001'})
self.assertEqual(get_attribute('ramdisk'),
{'instance_id': 'i-12345678',
'ramdisk': 'ari-00000002'})
self.assertEqual(get_attribute('rootDeviceName'),
{'instance_id': 'i-12345678',
'rootDeviceName': '/dev/sdh'})
# NOTE(yamahata): this isn't supported
# get_attribute('sourceDestCheck')
self.assertEqual(get_attribute('userData'),
{'instance_id': 'i-12345678',
'userData': '}\xa9\x1e\xba\xc7\xabu\xabZ'})

View File

@@ -26,6 +26,7 @@ from nova.compute import power_state
from nova import context
from nova import db
from nova.db.sqlalchemy import models
from nova.db.sqlalchemy import api as sqlalchemy_api
from nova import exception
from nova import flags
import nova.image.fake
@@ -73,8 +74,11 @@ class ComputeTestCase(test.TestCase):
self.stubs.Set(nova.image.fake._FakeImageService, 'show', fake_show)
def _create_instance(self, params={}):
def _create_instance(self, params=None):
"""Create a test instance"""
if params is None:
params = {}
inst = {}
inst['image_ref'] = 1
inst['reservation_id'] = 'r-fakeres'
@@ -864,6 +868,458 @@ class ComputeTestCase(test.TestCase):
self.assertEqual(len(instances), 1)
self.assertEqual(power_state.SHUTOFF, instances[0]['state'])
def test_get_all_by_name_regexp(self):
"""Test searching instances by name (display_name)"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'display_name': 'woot'})
instance_id2 = self._create_instance({
'display_name': 'woo',
'id': 20})
instance_id3 = self._create_instance({
'display_name': 'not-woot',
'id': 30})
instances = self.compute_api.get_all(c,
search_opts={'name': 'woo.*'})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id1 in instance_ids)
self.assertTrue(instance_id2 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'name': 'woot.*'})
instance_ids = [instance.id for instance in instances]
self.assertEqual(len(instances), 1)
self.assertTrue(instance_id1 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'name': '.*oot.*'})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id1 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'name': 'n.*'})
self.assertEqual(len(instances), 1)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id3 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'name': 'noth.*'})
self.assertEqual(len(instances), 0)
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_instance_name_regexp(self):
"""Test searching instances by name"""
self.flags(instance_name_template='instance-%d')
c = context.get_admin_context()
instance_id1 = self._create_instance()
instance_id2 = self._create_instance({'id': 2})
instance_id3 = self._create_instance({'id': 10})
instances = self.compute_api.get_all(c,
search_opts={'instance_name': 'instance.*'})
self.assertEqual(len(instances), 3)
instances = self.compute_api.get_all(c,
search_opts={'instance_name': '.*\-\d$'})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id1 in instance_ids)
self.assertTrue(instance_id2 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'instance_name': 'i.*2'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id2)
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_by_fixed_ip(self):
"""Test getting 1 instance by Fixed IP"""
c = context.get_admin_context()
instance_id1 = self._create_instance()
instance_id2 = self._create_instance({'id': 20})
instance_id3 = self._create_instance({'id': 30})
vif_ref1 = db.virtual_interface_create(c,
{'address': '12:34:56:78:90:12',
'instance_id': instance_id1,
'network_id': 1})
vif_ref2 = db.virtual_interface_create(c,
{'address': '90:12:34:56:78:90',
'instance_id': instance_id2,
'network_id': 1})
db.fixed_ip_create(c,
{'address': '1.1.1.1',
'instance_id': instance_id1,
'virtual_interface_id': vif_ref1['id']})
db.fixed_ip_create(c,
{'address': '1.1.2.1',
'instance_id': instance_id2,
'virtual_interface_id': vif_ref2['id']})
# regex not allowed
instances = self.compute_api.get_all(c,
search_opts={'fixed_ip': '.*'})
self.assertEqual(len(instances), 0)
instances = self.compute_api.get_all(c,
search_opts={'fixed_ip': '1.1.3.1'})
self.assertEqual(len(instances), 0)
instances = self.compute_api.get_all(c,
search_opts={'fixed_ip': '1.1.1.1'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id1)
instances = self.compute_api.get_all(c,
search_opts={'fixed_ip': '1.1.2.1'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id2)
db.virtual_interface_delete(c, vif_ref1['id'])
db.virtual_interface_delete(c, vif_ref2['id'])
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
def test_get_all_by_ip_regexp(self):
"""Test searching by Floating and Fixed IP"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'display_name': 'woot'})
instance_id2 = self._create_instance({
'display_name': 'woo',
'id': 20})
instance_id3 = self._create_instance({
'display_name': 'not-woot',
'id': 30})
vif_ref1 = db.virtual_interface_create(c,
{'address': '12:34:56:78:90:12',
'instance_id': instance_id1,
'network_id': 1})
vif_ref2 = db.virtual_interface_create(c,
{'address': '90:12:34:56:78:90',
'instance_id': instance_id2,
'network_id': 1})
vif_ref3 = db.virtual_interface_create(c,
{'address': '34:56:78:90:12:34',
'instance_id': instance_id3,
'network_id': 1})
db.fixed_ip_create(c,
{'address': '1.1.1.1',
'instance_id': instance_id1,
'virtual_interface_id': vif_ref1['id']})
db.fixed_ip_create(c,
{'address': '1.1.2.1',
'instance_id': instance_id2,
'virtual_interface_id': vif_ref2['id']})
fix_addr = db.fixed_ip_create(c,
{'address': '1.1.3.1',
'instance_id': instance_id3,
'virtual_interface_id': vif_ref3['id']})
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
flo_ref = db.floating_ip_create(c,
{'address': '10.0.0.2',
'fixed_ip_id': fix_ref['id']})
# ends up matching 2nd octet here.. so all 3 match
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*\.1'})
self.assertEqual(len(instances), 3)
instances = self.compute_api.get_all(c,
search_opts={'ip': '1.*'})
self.assertEqual(len(instances), 3)
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*\.1.\d+$'})
self.assertEqual(len(instances), 1)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id1 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*\.2.+'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id2)
instances = self.compute_api.get_all(c,
search_opts={'ip': '10.*'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id3)
db.virtual_interface_delete(c, vif_ref1['id'])
db.virtual_interface_delete(c, vif_ref2['id'])
db.virtual_interface_delete(c, vif_ref3['id'])
db.floating_ip_destroy(c, '10.0.0.2')
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_ipv6_regexp(self):
"""Test searching by IPv6 address"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'display_name': 'woot'})
instance_id2 = self._create_instance({
'display_name': 'woo',
'id': 20})
instance_id3 = self._create_instance({
'display_name': 'not-woot',
'id': 30})
vif_ref1 = db.virtual_interface_create(c,
{'address': '12:34:56:78:90:12',
'instance_id': instance_id1,
'network_id': 1})
vif_ref2 = db.virtual_interface_create(c,
{'address': '90:12:34:56:78:90',
'instance_id': instance_id2,
'network_id': 1})
vif_ref3 = db.virtual_interface_create(c,
{'address': '34:56:78:90:12:34',
'instance_id': instance_id3,
'network_id': 1})
# This will create IPv6 addresses of:
# 1: fd00::1034:56ff:fe78:9012
# 20: fd00::9212:34ff:fe56:7890
# 30: fd00::3656:78ff:fe90:1234
instances = self.compute_api.get_all(c,
search_opts={'ip6': '.*1034.*'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id1)
instances = self.compute_api.get_all(c,
search_opts={'ip6': '^fd00.*'})
self.assertEqual(len(instances), 3)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id1 in instance_ids)
self.assertTrue(instance_id2 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
instances = self.compute_api.get_all(c,
search_opts={'ip6': '^.*12.*34.*'})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id2 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
db.virtual_interface_delete(c, vif_ref1['id'])
db.virtual_interface_delete(c, vif_ref2['id'])
db.virtual_interface_delete(c, vif_ref3['id'])
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_multiple_options_at_once(self):
"""Test searching by multiple options at once"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'display_name': 'woot'})
instance_id2 = self._create_instance({
'display_name': 'woo',
'id': 20})
instance_id3 = self._create_instance({
'display_name': 'not-woot',
'id': 30})
vif_ref1 = db.virtual_interface_create(c,
{'address': '12:34:56:78:90:12',
'instance_id': instance_id1,
'network_id': 1})
vif_ref2 = db.virtual_interface_create(c,
{'address': '90:12:34:56:78:90',
'instance_id': instance_id2,
'network_id': 1})
vif_ref3 = db.virtual_interface_create(c,
{'address': '34:56:78:90:12:34',
'instance_id': instance_id3,
'network_id': 1})
db.fixed_ip_create(c,
{'address': '1.1.1.1',
'instance_id': instance_id1,
'virtual_interface_id': vif_ref1['id']})
db.fixed_ip_create(c,
{'address': '1.1.2.1',
'instance_id': instance_id2,
'virtual_interface_id': vif_ref2['id']})
fix_addr = db.fixed_ip_create(c,
{'address': '1.1.3.1',
'instance_id': instance_id3,
'virtual_interface_id': vif_ref3['id']})
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
flo_ref = db.floating_ip_create(c,
{'address': '10.0.0.2',
'fixed_ip_id': fix_ref['id']})
# ip ends up matching 2nd octet here.. so all 3 match ip
# but 'name' only matches one
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*\.1', 'name': 'not.*'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id3)
# ip ends up matching any ip with a '2' in it.. so instance
# 2 and 3.. but name should only match #2
# but 'name' only matches one
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*2', 'name': '^woo.*'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id2)
# same as above but no match on name (name matches instance_id1
# but the ip query doesn't
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*2.*', 'name': '^woot.*'})
self.assertEqual(len(instances), 0)
# ip matches all 3... ipv6 matches #2+#3...name matches #3
instances = self.compute_api.get_all(c,
search_opts={'ip': '.*\.1',
'name': 'not.*',
'ip6': '^.*12.*34.*'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id3)
db.virtual_interface_delete(c, vif_ref1['id'])
db.virtual_interface_delete(c, vif_ref2['id'])
db.virtual_interface_delete(c, vif_ref3['id'])
db.floating_ip_destroy(c, '10.0.0.2')
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_image(self):
"""Test searching instances by image"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'image_ref': '1234'})
instance_id2 = self._create_instance({
'id': 2,
'image_ref': '4567'})
instance_id3 = self._create_instance({
'id': 10,
'image_ref': '4567'})
instances = self.compute_api.get_all(c,
search_opts={'image': '123'})
self.assertEqual(len(instances), 0)
instances = self.compute_api.get_all(c,
search_opts={'image': '1234'})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id1)
instances = self.compute_api.get_all(c,
search_opts={'image': '4567'})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id2 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
# Test passing a list as search arg
instances = self.compute_api.get_all(c,
search_opts={'image': ['1234', '4567']})
self.assertEqual(len(instances), 3)
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_flavor(self):
"""Test searching instances by image"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'instance_type_id': 1})
instance_id2 = self._create_instance({
'id': 2,
'instance_type_id': 2})
instance_id3 = self._create_instance({
'id': 10,
'instance_type_id': 2})
# NOTE(comstud): Migrations set up the instance_types table
# for us. Therefore, we assume the following is true for
# these tests:
# instance_type_id 1 == flavor 3
# instance_type_id 2 == flavor 1
# instance_type_id 3 == flavor 4
# instance_type_id 4 == flavor 5
# instance_type_id 5 == flavor 2
instances = self.compute_api.get_all(c,
search_opts={'flavor': 5})
self.assertEqual(len(instances), 0)
self.assertRaises(exception.FlavorNotFound,
self.compute_api.get_all,
c, search_opts={'flavor': 99})
instances = self.compute_api.get_all(c,
search_opts={'flavor': 3})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id1)
instances = self.compute_api.get_all(c,
search_opts={'flavor': 1})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id2 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
def test_get_all_by_state(self):
"""Test searching instances by state"""
c = context.get_admin_context()
instance_id1 = self._create_instance({'state': power_state.SHUTDOWN})
instance_id2 = self._create_instance({
'id': 2,
'state': power_state.RUNNING})
instance_id3 = self._create_instance({
'id': 10,
'state': power_state.RUNNING})
instances = self.compute_api.get_all(c,
search_opts={'state': power_state.SUSPENDED})
self.assertEqual(len(instances), 0)
instances = self.compute_api.get_all(c,
search_opts={'state': power_state.SHUTDOWN})
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].id, instance_id1)
instances = self.compute_api.get_all(c,
search_opts={'state': power_state.RUNNING})
self.assertEqual(len(instances), 2)
instance_ids = [instance.id for instance in instances]
self.assertTrue(instance_id2 in instance_ids)
self.assertTrue(instance_id3 in instance_ids)
# Test passing a list as search arg
instances = self.compute_api.get_all(c,
search_opts={'state': [power_state.SHUTDOWN,
power_state.RUNNING]})
self.assertEqual(len(instances), 3)
db.instance_destroy(c, instance_id1)
db.instance_destroy(c, instance_id2)
db.instance_destroy(c, instance_id3)
@staticmethod
def _parse_db_block_device_mapping(bdm_ref):
attr_list = ('delete_on_termination', 'device_name', 'no_device',
@@ -877,15 +1333,17 @@ class ComputeTestCase(test.TestCase):
return bdm
def test_update_block_device_mapping(self):
swap_size = 1
instance_type = {'swap': swap_size}
instance_id = self._create_instance()
mappings = [
{'virtual': 'ami', 'device': 'sda1'},
{'virtual': 'root', 'device': '/dev/sda1'},
{'virtual': 'swap', 'device': 'sdb1'},
{'virtual': 'swap', 'device': 'sdb2'},
{'virtual': 'swap', 'device': 'sdb3'},
{'virtual': 'swap', 'device': 'sdb4'},
{'virtual': 'swap', 'device': 'sdb3'},
{'virtual': 'swap', 'device': 'sdb2'},
{'virtual': 'swap', 'device': 'sdb1'},
{'virtual': 'ephemeral0', 'device': 'sdc1'},
{'virtual': 'ephemeral1', 'device': 'sdc2'},
@@ -927,32 +1385,36 @@ class ComputeTestCase(test.TestCase):
'no_device': True}]
self.compute_api._update_image_block_device_mapping(
self.context, instance_id, mappings)
self.context, instance_type, instance_id, mappings)
bdms = [self._parse_db_block_device_mapping(bdm_ref)
for bdm_ref in db.block_device_mapping_get_all_by_instance(
self.context, instance_id)]
expected_result = [
{'virtual_name': 'swap', 'device_name': '/dev/sdb1'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb2'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb3'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb4'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb1',
'volume_size': swap_size},
{'virtual_name': 'ephemeral0', 'device_name': '/dev/sdc1'},
{'virtual_name': 'ephemeral1', 'device_name': '/dev/sdc2'},
{'virtual_name': 'ephemeral2', 'device_name': '/dev/sdc3'}]
# NOTE(yamahata): ATM only ephemeral0 is supported.
# they're ignored for now
#{'virtual_name': 'ephemeral1', 'device_name': '/dev/sdc2'},
#{'virtual_name': 'ephemeral2', 'device_name': '/dev/sdc3'}
]
bdms.sort()
expected_result.sort()
self.assertDictListMatch(bdms, expected_result)
self.compute_api._update_block_device_mapping(
self.context, instance_id, block_device_mapping)
self.context, instance_types.get_default_instance_type(),
instance_id, block_device_mapping)
bdms = [self._parse_db_block_device_mapping(bdm_ref)
for bdm_ref in db.block_device_mapping_get_all_by_instance(
self.context, instance_id)]
expected_result = [
{'snapshot_id': 0x12345678, 'device_name': '/dev/sda1'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb1'},
{'virtual_name': 'swap', 'device_name': '/dev/sdb1',
'volume_size': swap_size},
{'snapshot_id': 0x23456789, 'device_name': '/dev/sdb2'},
{'snapshot_id': 0x3456789A, 'device_name': '/dev/sdb3'},
{'no_device': True, 'device_name': '/dev/sdb4'},
@@ -974,3 +1436,13 @@ class ComputeTestCase(test.TestCase):
self.context, instance_id):
db.block_device_mapping_destroy(self.context, bdm['id'])
self.compute.terminate_instance(self.context, instance_id)
def test_ephemeral_size(self):
local_size = 2
inst_type = {'local_gb': local_size}
self.assertEqual(self.compute_api._ephemeral_size(inst_type,
'ephemeral0'),
local_size)
self.assertEqual(self.compute_api._ephemeral_size(inst_type,
'ephemeral1'),
0)

View File

@@ -48,6 +48,10 @@ def stub_set_host_enabled(context, host, enabled):
return status
def stub_host_power_action(context, host, action):
return action
class FakeRequest(object):
environ = {"nova.context": context.get_admin_context()}
@@ -62,6 +66,8 @@ class HostTestCase(test.TestCase):
self.stubs.Set(scheduler_api, 'get_host_list', stub_get_host_list)
self.stubs.Set(self.controller.compute_api, 'set_host_enabled',
stub_set_host_enabled)
self.stubs.Set(self.controller.compute_api, 'host_power_action',
stub_host_power_action)
def test_list_hosts(self):
"""Verify that the compute hosts are returned."""
@@ -87,6 +93,18 @@ class HostTestCase(test.TestCase):
result_c2 = self.controller.update(self.req, "host_c2", body=en_body)
self.assertEqual(result_c2["status"], "disabled")
def test_host_startup(self):
result = self.controller.startup(self.req, "host_c1")
self.assertEqual(result["power_action"], "startup")
def test_host_shutdown(self):
result = self.controller.shutdown(self.req, "host_c1")
self.assertEqual(result["power_action"], "shutdown")
def test_host_reboot(self):
result = self.controller.reboot(self.req, "host_c1")
self.assertEqual(result["power_action"], "reboot")
def test_bad_status_value(self):
bad_body = {"status": "bad"}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,

View File

@@ -169,6 +169,7 @@ class LibvirtConnTestCase(test.TestCase):
'project_id': 'fake',
'bridge': 'br101',
'image_ref': '123456',
'local_gb': 20,
'instance_type_id': '5'} # m1.small
def lazy_load_library_exists(self):
@@ -744,6 +745,42 @@ class LibvirtConnTestCase(test.TestCase):
ip = conn.get_host_ip_addr()
self.assertEquals(ip, FLAGS.my_ip)
def test_volume_in_mapping(self):
conn = connection.LibvirtConnection(False)
swap = {'device_name': '/dev/sdb',
'swap_size': 1}
ephemerals = [{'num': 0,
'virtual_name': 'ephemeral0',
'device_name': '/dev/sdc1',
'size': 1},
{'num': 2,
'virtual_name': 'ephemeral2',
'device_name': '/dev/sdd',
'size': 1}]
block_device_mapping = [{'mount_device': '/dev/sde',
'device_path': 'fake_device'},
{'mount_device': '/dev/sdf',
'device_path': 'fake_device'}]
block_device_info = {
'root_device_name': '/dev/sda',
'swap': swap,
'ephemerals': ephemerals,
'block_device_mapping': block_device_mapping}
def _assert_volume_in_mapping(device_name, true_or_false):
self.assertEquals(conn._volume_in_mapping(device_name,
block_device_info),
true_or_false)
_assert_volume_in_mapping('sda', False)
_assert_volume_in_mapping('sdb', True)
_assert_volume_in_mapping('sdc1', True)
_assert_volume_in_mapping('sdd', True)
_assert_volume_in_mapping('sde', True)
_assert_volume_in_mapping('sdf', True)
_assert_volume_in_mapping('sdg', False)
_assert_volume_in_mapping('sdh1', False)
class NWFilterFakes:
def __init__(self):

83
nova/tests/test_virt.py Normal file
View File

@@ -0,0 +1,83 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 Isaku Yamahata
# 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 flags
from nova import test
from nova.virt import driver
FLAGS = flags.FLAGS
class TestVirtDriver(test.TestCase):
def test_block_device(self):
swap = {'device_name': '/dev/sdb',
'swap_size': 1}
ephemerals = [{'num': 0,
'virtual_name': 'ephemeral0',
'device_name': '/dev/sdc1',
'size': 1}]
block_device_mapping = [{'mount_device': '/dev/sde',
'device_path': 'fake_device'}]
block_device_info = {
'root_device_name': '/dev/sda',
'swap': swap,
'ephemerals': ephemerals,
'block_device_mapping': block_device_mapping}
empty_block_device_info = {}
self.assertEqual(
driver.block_device_info_get_root(block_device_info), '/dev/sda')
self.assertEqual(
driver.block_device_info_get_root(empty_block_device_info), None)
self.assertEqual(
driver.block_device_info_get_root(None), None)
self.assertEqual(
driver.block_device_info_get_swap(block_device_info), swap)
self.assertEqual(driver.block_device_info_get_swap(
empty_block_device_info)['device_name'], None)
self.assertEqual(driver.block_device_info_get_swap(
empty_block_device_info)['swap_size'], 0)
self.assertEqual(
driver.block_device_info_get_swap({'swap': None})['device_name'],
None)
self.assertEqual(
driver.block_device_info_get_swap({'swap': None})['swap_size'],
0)
self.assertEqual(
driver.block_device_info_get_swap(None)['device_name'], None)
self.assertEqual(
driver.block_device_info_get_swap(None)['swap_size'], 0)
self.assertEqual(
driver.block_device_info_get_ephemerals(block_device_info),
ephemerals)
self.assertEqual(
driver.block_device_info_get_ephemerals(empty_block_device_info),
[])
self.assertEqual(
driver.block_device_info_get_ephemerals(None),
[])
def test_swap_is_usable(self):
self.assertFalse(driver.swap_is_usable(None))
self.assertFalse(driver.swap_is_usable({'device_name': None}))
self.assertFalse(driver.swap_is_usable({'device_name': '/dev/sdb',
'swap_size': 0}))
self.assertTrue(driver.swap_is_usable({'device_name': '/dev/sdb',
'swap_size': 1}))

View File

@@ -18,7 +18,6 @@ Tests For ZoneManager
import datetime
import mox
import novaclient
from nova import context
from nova import db