merge with 1305

This commit is contained in:
vladimir.p
2011-07-22 16:05:14 -07:00
9 changed files with 733 additions and 48 deletions

View File

@@ -1,3 +1,4 @@
Adam Gandelman <adamg@canonical.com>
Alex Meade <alex.meade@rackspace.com>
Alexander Sakhnov <asakhnov@mirantis.com>
Andrey Brindeyev <abrindeyev@griddynamics.com>

View File

@@ -91,7 +91,7 @@ def init_leases(interface):
"""Get the list of hosts for an interface."""
ctxt = context.get_admin_context()
network_ref = db.network_get_by_bridge(ctxt, interface)
return linux_net.get_dhcp_leases(ctxt, network_ref['id'])
return linux_net.get_dhcp_leases(ctxt, network_ref)
def main():

View File

@@ -484,7 +484,7 @@ class ProjectCommands(object):
except db.api.NoMoreNetworks:
print _('No more networks available. If this is a new '
'installation, you need\nto call something like this:\n\n'
' nova-manage network create 10.0.0.0/8 10 64\n\n')
' nova-manage network create pvt 10.0.0.0/8 10 64\n\n')
except exception.ProcessExecutionError, e:
print e
print _("The above error may show that the certificate db has not "
@@ -505,7 +505,7 @@ class FixedIpCommands(object):
if host is None:
fixed_ips = db.fixed_ip_get_all(ctxt)
else:
fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host)
fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host)
except exception.NotFound as ex:
print "error: %s" % ex
sys.exit(2)
@@ -523,7 +523,7 @@ class FixedIpCommands(object):
instance = fixed_ip['instance']
hostname = instance['hostname']
host = instance['host']
mac_address = fixed_ip['mac_address']['address']
mac_address = fixed_ip['virtual_interface']['address']
print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (
fixed_ip['network']['cidr'],
fixed_ip['address'],
@@ -569,17 +569,17 @@ class NetworkCommands(object):
"""Class for managing networks."""
def create(self, label=None, fixed_range=None, num_networks=None,
network_size=None, vlan_start=None,
network_size=None, multi_host=None, vlan_start=None,
vpn_start=None, fixed_range_v6=None, gateway_v6=None,
flat_network_bridge=None, bridge_interface=None):
"""Creates fixed ips for host by range
arguments: label, fixed_range, [num_networks=FLAG],
[network_size=FLAG], [vlan_start=FLAG],
[network_size=FLAG], [multi_host=FLAG], [vlan_start=FLAG],
[vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG],
[flat_network_bridge=FLAG], [bridge_interface=FLAG]
If you wish to use a later argument fill in the gaps with 0s
Ex: network create private 10.0.0.0/8 1 15 0 0 0 0 xenbr1 eth1
network create private 10.0.0.0/8 1 15
If you wish to use a later argument fill in the gaps with ""s
Ex: network create private 10.0.0.0/8 1 16 T "" "" "" "" xenbr1 eth1
network create private 10.0.0.0/8 1 16
"""
if not label:
msg = _('a label (ex: public) is required to create networks.')
@@ -594,6 +594,10 @@ class NetworkCommands(object):
num_networks = FLAGS.num_networks
if not network_size:
network_size = FLAGS.network_size
if not multi_host:
multi_host = FLAGS.multi_host
else:
multi_host = multi_host == 'T'
if not vlan_start:
vlan_start = FLAGS.vlan_start
if not vpn_start:
@@ -612,6 +616,7 @@ class NetworkCommands(object):
net_manager.create_networks(context.get_admin_context(),
label=label,
cidr=fixed_range,
multi_host=multi_host,
num_networks=int(num_networks),
network_size=int(network_size),
vlan_start=int(vlan_start),

View File

@@ -92,7 +92,9 @@ class XmlConversionTestCase(test.TestCase):
conv = ec2utils._try_convert
self.assertEqual(conv('None'), None)
self.assertEqual(conv('True'), True)
self.assertEqual(conv('true'), True)
self.assertEqual(conv('False'), False)
self.assertEqual(conv('false'), False)
self.assertEqual(conv('0'), 0)
self.assertEqual(conv('42'), 42)
self.assertEqual(conv('3.14'), 3.14)
@@ -107,6 +109,8 @@ class Ec2utilsTestCase(test.TestCase):
def test_ec2_id_to_id(self):
self.assertEqual(ec2utils.ec2_id_to_id('i-0000001e'), 30)
self.assertEqual(ec2utils.ec2_id_to_id('ami-1d'), 29)
self.assertEqual(ec2utils.ec2_id_to_id('snap-0000001c'), 28)
self.assertEqual(ec2utils.ec2_id_to_id('vol-0000001b'), 27)
def test_bad_ec2_id(self):
self.assertRaises(exception.InvalidEc2Id,
@@ -116,6 +120,72 @@ class Ec2utilsTestCase(test.TestCase):
def test_id_to_ec2_id(self):
self.assertEqual(ec2utils.id_to_ec2_id(30), 'i-0000001e')
self.assertEqual(ec2utils.id_to_ec2_id(29, 'ami-%08x'), 'ami-0000001d')
self.assertEqual(ec2utils.id_to_ec2_snap_id(28), 'snap-0000001c')
self.assertEqual(ec2utils.id_to_ec2_vol_id(27), 'vol-0000001b')
def test_dict_from_dotted_str(self):
in_str = [('BlockDeviceMapping.1.DeviceName', '/dev/sda1'),
('BlockDeviceMapping.1.Ebs.SnapshotId', 'snap-0000001c'),
('BlockDeviceMapping.1.Ebs.VolumeSize', '80'),
('BlockDeviceMapping.1.Ebs.DeleteOnTermination', 'false'),
('BlockDeviceMapping.2.DeviceName', '/dev/sdc'),
('BlockDeviceMapping.2.VirtualName', 'ephemeral0')]
expected_dict = {
'block_device_mapping': {
'1': {'device_name': '/dev/sda1',
'ebs': {'snapshot_id': 'snap-0000001c',
'volume_size': 80,
'delete_on_termination': False}},
'2': {'device_name': '/dev/sdc',
'virtual_name': 'ephemeral0'}}}
out_dict = ec2utils.dict_from_dotted_str(in_str)
self.assertDictMatch(out_dict, expected_dict)
def test_properties_root_defice_name(self):
mappings = [{"device": "/dev/sda1", "virtual": "root"}]
properties0 = {'mappings': mappings}
properties1 = {'root_device_name': '/dev/sdb', 'mappings': mappings}
root_device_name = ec2utils.properties_root_device_name(properties0)
self.assertEqual(root_device_name, '/dev/sda1')
root_device_name = ec2utils.properties_root_device_name(properties1)
self.assertEqual(root_device_name, '/dev/sdb')
def test_mapping_prepend_dev(self):
mappings = [
{'virtual': 'ami',
'device': 'sda1'},
{'virtual': 'root',
'device': '/dev/sda1'},
{'virtual': 'swap',
'device': 'sdb1'},
{'virtual': 'swap',
'device': '/dev/sdb2'},
{'virtual': 'ephemeral0',
'device': 'sdc1'},
{'virtual': 'ephemeral1',
'device': '/dev/sdc1'}]
expected_result = [
{'virtual': 'ami',
'device': 'sda1'},
{'virtual': 'root',
'device': '/dev/sda1'},
{'virtual': 'swap',
'device': '/dev/sdb1'},
{'virtual': 'swap',
'device': '/dev/sdb2'},
{'virtual': 'ephemeral0',
'device': '/dev/sdc1'},
{'virtual': 'ephemeral1',
'device': '/dev/sdc1'}]
self.assertDictListMatch(ec2utils.mappings_prepend_dev(mappings),
expected_result)
class ApiEc2TestCase(test.TestCase):

View File

@@ -15,6 +15,7 @@
# 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 mox
from base64 import b64decode
from M2Crypto import BIO
@@ -29,6 +30,7 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
from nova import network
from nova import rpc
from nova import test
from nova import utils
@@ -45,7 +47,8 @@ LOG = logging.getLogger('nova.tests.cloud')
class CloudTestCase(test.TestCase):
def setUp(self):
super(CloudTestCase, self).setUp()
self.flags(connection_type='fake')
self.flags(connection_type='fake',
stub_network=True)
self.conn = rpc.Connection.instance()
@@ -131,6 +134,33 @@ class CloudTestCase(test.TestCase):
allocate,
self.context)
def test_release_address(self):
address = "10.10.10.10"
allocate = self.cloud.allocate_address
db.floating_ip_create(self.context,
{'address': address,
'host': self.network.host})
result = self.cloud.release_address(self.context, address)
self.assertEqual(result['releaseResponse'], ['Address released.'])
def test_release_address_still_associated(self):
address = "10.10.10.10"
fixed_ip = {'instance': {'id': 1}}
floating_ip = {'id': 0,
'address': address,
'fixed_ip_id': 0,
'fixed_ip': fixed_ip,
'project_id': None,
'auto_assigned': False}
network_api = network.api.API()
self.mox.StubOutWithMock(network_api.db, 'floating_ip_get_by_address')
network_api.db.floating_ip_get_by_address(mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(floating_ip)
self.mox.ReplayAll()
release = self.cloud.release_address
# ApiError: Floating ip is in use. Disassociate it before releasing.
self.assertRaises(exception.ApiError, release, self.context, address)
@test.skip_test("Skipping this pending future merge")
def test_associate_disassociate_address(self):
"""Verifies associate runs cleanly without raising an exception"""
@@ -290,7 +320,7 @@ class CloudTestCase(test.TestCase):
vol2 = db.volume_create(self.context, {})
result = self.cloud.describe_volumes(self.context)
self.assertEqual(len(result['volumeSet']), 2)
volume_id = ec2utils.id_to_ec2_id(vol2['id'], 'vol-%08x')
volume_id = ec2utils.id_to_ec2_vol_id(vol2['id'])
result = self.cloud.describe_volumes(self.context,
volume_id=[volume_id])
self.assertEqual(len(result['volumeSet']), 1)
@@ -306,7 +336,7 @@ class CloudTestCase(test.TestCase):
snap = db.snapshot_create(self.context, {'volume_id': vol['id'],
'volume_size': vol['size'],
'status': "available"})
snapshot_id = ec2utils.id_to_ec2_id(snap['id'], 'snap-%08x')
snapshot_id = ec2utils.id_to_ec2_snap_id(snap['id'])
result = self.cloud.create_volume(self.context,
snapshot_id=snapshot_id)
@@ -345,7 +375,7 @@ class CloudTestCase(test.TestCase):
snap2 = db.snapshot_create(self.context, {'volume_id': vol['id']})
result = self.cloud.describe_snapshots(self.context)
self.assertEqual(len(result['snapshotSet']), 2)
snapshot_id = ec2utils.id_to_ec2_id(snap2['id'], 'snap-%08x')
snapshot_id = ec2utils.id_to_ec2_snap_id(snap2['id'])
result = self.cloud.describe_snapshots(self.context,
snapshot_id=[snapshot_id])
self.assertEqual(len(result['snapshotSet']), 1)
@@ -359,7 +389,7 @@ class CloudTestCase(test.TestCase):
def test_create_snapshot(self):
"""Makes sure create_snapshot works."""
vol = db.volume_create(self.context, {'status': "available"})
volume_id = ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x')
volume_id = ec2utils.id_to_ec2_vol_id(vol['id'])
result = self.cloud.create_snapshot(self.context,
volume_id=volume_id)
@@ -376,7 +406,7 @@ class CloudTestCase(test.TestCase):
vol = db.volume_create(self.context, {'status': "available"})
snap = db.snapshot_create(self.context, {'volume_id': vol['id'],
'status': "available"})
snapshot_id = ec2utils.id_to_ec2_id(snap['id'], 'snap-%08x')
snapshot_id = ec2utils.id_to_ec2_snap_id(snap['id'])
result = self.cloud.delete_snapshot(self.context,
snapshot_id=snapshot_id)
@@ -415,6 +445,185 @@ class CloudTestCase(test.TestCase):
db.service_destroy(self.context, comp1['id'])
db.service_destroy(self.context, comp2['id'])
def _block_device_mapping_create(self, instance_id, mappings):
volumes = []
for bdm in mappings:
db.block_device_mapping_create(self.context, bdm)
if 'volume_id' in bdm:
values = {'id': bdm['volume_id']}
for bdm_key, vol_key in [('snapshot_id', 'snapshot_id'),
('snapshot_size', 'volume_size'),
('delete_on_termination',
'delete_on_termination')]:
if bdm_key in bdm:
values[vol_key] = bdm[bdm_key]
vol = db.volume_create(self.context, values)
db.volume_attached(self.context, vol['id'],
instance_id, bdm['device_name'])
volumes.append(vol)
return volumes
def _setUpBlockDeviceMapping(self):
inst1 = db.instance_create(self.context,
{'image_ref': 1,
'root_device_name': '/dev/sdb1'})
inst2 = db.instance_create(self.context,
{'image_ref': 2,
'root_device_name': '/dev/sdc1'})
instance_id = inst1['id']
mappings0 = [
{'instance_id': instance_id,
'device_name': '/dev/sdb1',
'snapshot_id': '1',
'volume_id': '2'},
{'instance_id': instance_id,
'device_name': '/dev/sdb2',
'volume_id': '3',
'volume_size': 1},
{'instance_id': instance_id,
'device_name': '/dev/sdb3',
'delete_on_termination': True,
'snapshot_id': '4',
'volume_id': '5'},
{'instance_id': instance_id,
'device_name': '/dev/sdb4',
'delete_on_termination': False,
'snapshot_id': '6',
'volume_id': '7'},
{'instance_id': instance_id,
'device_name': '/dev/sdb5',
'snapshot_id': '8',
'volume_id': '9',
'volume_size': 0},
{'instance_id': instance_id,
'device_name': '/dev/sdb6',
'snapshot_id': '10',
'volume_id': '11',
'volume_size': 1},
{'instance_id': instance_id,
'device_name': '/dev/sdb7',
'no_device': True},
{'instance_id': instance_id,
'device_name': '/dev/sdb8',
'virtual_name': 'swap'},
{'instance_id': instance_id,
'device_name': '/dev/sdb9',
'virtual_name': 'ephemeral3'}]
volumes = self._block_device_mapping_create(instance_id, mappings0)
return (inst1, inst2, volumes)
def _tearDownBlockDeviceMapping(self, inst1, inst2, volumes):
for vol in volumes:
db.volume_destroy(self.context, vol['id'])
for id in (inst1['id'], inst2['id']):
for bdm in db.block_device_mapping_get_all_by_instance(
self.context, id):
db.block_device_mapping_destroy(self.context, bdm['id'])
db.instance_destroy(self.context, inst2['id'])
db.instance_destroy(self.context, inst1['id'])
_expected_instance_bdm1 = {
'instanceId': 'i-00000001',
'rootDeviceName': '/dev/sdb1',
'rootDeviceType': 'ebs'}
_expected_block_device_mapping0 = [
{'deviceName': '/dev/sdb1',
'ebs': {'status': 'in-use',
'deleteOnTermination': False,
'volumeId': 2,
}},
{'deviceName': '/dev/sdb2',
'ebs': {'status': 'in-use',
'deleteOnTermination': False,
'volumeId': 3,
}},
{'deviceName': '/dev/sdb3',
'ebs': {'status': 'in-use',
'deleteOnTermination': True,
'volumeId': 5,
}},
{'deviceName': '/dev/sdb4',
'ebs': {'status': 'in-use',
'deleteOnTermination': False,
'volumeId': 7,
}},
{'deviceName': '/dev/sdb5',
'ebs': {'status': 'in-use',
'deleteOnTermination': False,
'volumeId': 9,
}},
{'deviceName': '/dev/sdb6',
'ebs': {'status': 'in-use',
'deleteOnTermination': False,
'volumeId': 11, }}]
# NOTE(yamahata): swap/ephemeral device case isn't supported yet.
_expected_instance_bdm2 = {
'instanceId': 'i-00000002',
'rootDeviceName': '/dev/sdc1',
'rootDeviceType': 'instance-store'}
def test_format_instance_bdm(self):
(inst1, inst2, volumes) = self._setUpBlockDeviceMapping()
result = {}
self.cloud._format_instance_bdm(self.context, inst1['id'], '/dev/sdb1',
result)
self.assertSubDictMatch(
{'rootDeviceType': self._expected_instance_bdm1['rootDeviceType']},
result)
self._assertEqualBlockDeviceMapping(
self._expected_block_device_mapping0, result['blockDeviceMapping'])
result = {}
self.cloud._format_instance_bdm(self.context, inst2['id'], '/dev/sdc1',
result)
self.assertSubDictMatch(
{'rootDeviceType': self._expected_instance_bdm2['rootDeviceType']},
result)
self._tearDownBlockDeviceMapping(inst1, inst2, volumes)
def _assertInstance(self, instance_id):
ec2_instance_id = ec2utils.id_to_ec2_id(instance_id)
result = self.cloud.describe_instances(self.context,
instance_id=[ec2_instance_id])
result = result['reservationSet'][0]
self.assertEqual(len(result['instancesSet']), 1)
result = result['instancesSet'][0]
self.assertEqual(result['instanceId'], ec2_instance_id)
return result
def _assertEqualBlockDeviceMapping(self, expected, result):
self.assertEqual(len(expected), len(result))
for x in expected:
found = False
for y in result:
if x['deviceName'] == y['deviceName']:
self.assertSubDictMatch(x, y)
found = True
break
self.assertTrue(found)
def test_describe_instances_bdm(self):
"""Make sure describe_instances works with root_device_name and
block device mappings
"""
(inst1, inst2, volumes) = self._setUpBlockDeviceMapping()
result = self._assertInstance(inst1['id'])
self.assertSubDictMatch(self._expected_instance_bdm1, result)
self._assertEqualBlockDeviceMapping(
self._expected_block_device_mapping0, result['blockDeviceMapping'])
result = self._assertInstance(inst2['id'])
self.assertSubDictMatch(self._expected_instance_bdm2, result)
self._tearDownBlockDeviceMapping(inst1, inst2, volumes)
def test_describe_images(self):
describe_images = self.cloud.describe_images
@@ -445,6 +654,161 @@ class CloudTestCase(test.TestCase):
self.assertRaises(exception.ImageNotFound, describe_images,
self.context, ['ami-fake'])
def assertDictListUnorderedMatch(self, L1, L2, key):
self.assertEqual(len(L1), len(L2))
for d1 in L1:
self.assertTrue(key in d1)
for d2 in L2:
self.assertTrue(key in d2)
if d1[key] == d2[key]:
self.assertDictMatch(d1, d2)
def _setUpImageSet(self, create_volumes_and_snapshots=False):
mappings1 = [
{'device': '/dev/sda1', 'virtual': 'root'},
{'device': 'sdb0', 'virtual': 'ephemeral0'},
{'device': 'sdb1', 'virtual': 'ephemeral1'},
{'device': 'sdb2', 'virtual': 'ephemeral2'},
{'device': 'sdb3', 'virtual': 'ephemeral3'},
{'device': 'sdb4', 'virtual': 'ephemeral4'},
{'device': 'sdc0', 'virtual': 'swap'},
{'device': 'sdc1', 'virtual': 'swap'},
{'device': 'sdc2', 'virtual': 'swap'},
{'device': 'sdc3', 'virtual': 'swap'},
{'device': 'sdc4', 'virtual': 'swap'}]
block_device_mapping1 = [
{'device_name': '/dev/sdb1', 'snapshot_id': 01234567},
{'device_name': '/dev/sdb2', 'volume_id': 01234567},
{'device_name': '/dev/sdb3', 'virtual_name': 'ephemeral5'},
{'device_name': '/dev/sdb4', 'no_device': True},
{'device_name': '/dev/sdc1', 'snapshot_id': 12345678},
{'device_name': '/dev/sdc2', 'volume_id': 12345678},
{'device_name': '/dev/sdc3', 'virtual_name': 'ephemeral6'},
{'device_name': '/dev/sdc4', 'no_device': True}]
image1 = {
'id': 1,
'properties': {
'kernel_id': 1,
'type': 'machine',
'image_state': 'available',
'mappings': mappings1,
'block_device_mapping': block_device_mapping1,
}
}
mappings2 = [{'device': '/dev/sda1', 'virtual': 'root'}]
block_device_mapping2 = [{'device_name': '/dev/sdb1',
'snapshot_id': 01234567}]
image2 = {
'id': 2,
'properties': {
'kernel_id': 2,
'type': 'machine',
'root_device_name': '/dev/sdb1',
'mappings': mappings2,
'block_device_mapping': block_device_mapping2}}
def fake_show(meh, context, image_id):
for i in [image1, image2]:
if i['id'] == image_id:
return i
raise exception.ImageNotFound(image_id=image_id)
def fake_detail(meh, context):
return [image1, image2]
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
self.stubs.Set(fake._FakeImageService, 'detail', fake_detail)
volumes = []
snapshots = []
if create_volumes_and_snapshots:
for bdm in block_device_mapping1:
if 'volume_id' in bdm:
vol = self._volume_create(bdm['volume_id'])
volumes.append(vol['id'])
if 'snapshot_id' in bdm:
snap = db.snapshot_create(self.context,
{'id': bdm['snapshot_id'],
'volume_id': 76543210,
'status': "available",
'volume_size': 1})
snapshots.append(snap['id'])
return (volumes, snapshots)
def _assertImageSet(self, result, root_device_type, root_device_name):
self.assertEqual(1, len(result['imagesSet']))
result = result['imagesSet'][0]
self.assertTrue('rootDeviceType' in result)
self.assertEqual(result['rootDeviceType'], root_device_type)
self.assertTrue('rootDeviceName' in result)
self.assertEqual(result['rootDeviceName'], root_device_name)
self.assertTrue('blockDeviceMapping' in result)
return result
_expected_root_device_name1 = '/dev/sda1'
# NOTE(yamahata): noDevice doesn't make sense when returning mapping
# It makes sense only when user overriding existing
# mapping.
_expected_bdms1 = [
{'deviceName': '/dev/sdb0', 'virtualName': 'ephemeral0'},
{'deviceName': '/dev/sdb1', 'ebs': {'snapshotId':
'snap-00053977'}},
{'deviceName': '/dev/sdb2', 'ebs': {'snapshotId':
'vol-00053977'}},
{'deviceName': '/dev/sdb3', 'virtualName': 'ephemeral5'},
# {'deviceName': '/dev/sdb4', 'noDevice': True},
{'deviceName': '/dev/sdc0', 'virtualName': 'swap'},
{'deviceName': '/dev/sdc1', 'ebs': {'snapshotId':
'snap-00bc614e'}},
{'deviceName': '/dev/sdc2', 'ebs': {'snapshotId':
'vol-00bc614e'}},
{'deviceName': '/dev/sdc3', 'virtualName': 'ephemeral6'},
# {'deviceName': '/dev/sdc4', 'noDevice': True}
]
_expected_root_device_name2 = '/dev/sdb1'
_expected_bdms2 = [{'deviceName': '/dev/sdb1',
'ebs': {'snapshotId': 'snap-00053977'}}]
# NOTE(yamahata):
# InstanceBlockDeviceMappingItemType
# rootDeviceType
# rootDeviceName
# blockDeviceMapping
# deviceName
# virtualName
# ebs
# snapshotId
# volumeSize
# deleteOnTermination
# noDevice
def test_describe_image_mapping(self):
"""test for rootDeviceName and blockDeiceMapping"""
describe_images = self.cloud.describe_images
self._setUpImageSet()
result = describe_images(self.context, ['ami-00000001'])
result = self._assertImageSet(result, 'instance-store',
self._expected_root_device_name1)
self.assertDictListUnorderedMatch(result['blockDeviceMapping'],
self._expected_bdms1, 'deviceName')
result = describe_images(self.context, ['ami-00000002'])
result = self._assertImageSet(result, 'ebs',
self._expected_root_device_name2)
self.assertDictListUnorderedMatch(result['blockDeviceMapping'],
self._expected_bdms2, 'deviceName')
self.stubs.UnsetAll()
def test_describe_image_attribute(self):
describe_image_attribute = self.cloud.describe_image_attribute
@@ -459,6 +823,32 @@ class CloudTestCase(test.TestCase):
'launchPermission')
self.assertEqual([{'group': 'all'}], result['launchPermission'])
def test_describe_image_attribute_root_device_name(self):
describe_image_attribute = self.cloud.describe_image_attribute
self._setUpImageSet()
result = describe_image_attribute(self.context, 'ami-00000001',
'rootDeviceName')
self.assertEqual(result['rootDeviceName'],
self._expected_root_device_name1)
result = describe_image_attribute(self.context, 'ami-00000002',
'rootDeviceName')
self.assertEqual(result['rootDeviceName'],
self._expected_root_device_name2)
def test_describe_image_attribute_block_device_mapping(self):
describe_image_attribute = self.cloud.describe_image_attribute
self._setUpImageSet()
result = describe_image_attribute(self.context, 'ami-00000001',
'blockDeviceMapping')
self.assertDictListUnorderedMatch(result['blockDeviceMapping'],
self._expected_bdms1, 'deviceName')
result = describe_image_attribute(self.context, 'ami-00000002',
'blockDeviceMapping')
self.assertDictListUnorderedMatch(result['blockDeviceMapping'],
self._expected_bdms2, 'deviceName')
def test_modify_image_attribute(self):
modify_image_attribute = self.cloud.modify_image_attribute
@@ -699,7 +1089,7 @@ class CloudTestCase(test.TestCase):
def test_update_of_volume_display_fields(self):
vol = db.volume_create(self.context, {})
self.cloud.update_volume(self.context,
ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x'),
ec2utils.id_to_ec2_vol_id(vol['id']),
display_name='c00l v0lum3')
vol = db.volume_get(self.context, vol['id'])
self.assertEqual('c00l v0lum3', vol['display_name'])
@@ -708,7 +1098,7 @@ class CloudTestCase(test.TestCase):
def test_update_of_volume_wont_update_private_fields(self):
vol = db.volume_create(self.context, {})
self.cloud.update_volume(self.context,
ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x'),
ec2utils.id_to_ec2_vol_id(vol['id']),
mountpoint='/not/here')
vol = db.volume_get(self.context, vol['id'])
self.assertEqual(None, vol['mountpoint'])
@@ -786,11 +1176,13 @@ class CloudTestCase(test.TestCase):
self._restart_compute_service()
def _volume_create(self):
def _volume_create(self, volume_id=None):
kwargs = {'status': 'available',
'host': self.volume.host,
'size': 1,
'attach_status': 'detached', }
if volume_id:
kwargs['id'] = volume_id
return db.volume_create(self.context, kwargs)
def _assert_volume_attached(self, vol, instance_id, mountpoint):
@@ -819,10 +1211,10 @@ class CloudTestCase(test.TestCase):
'max_count': 1,
'block_device_mapping': [{'device_name': '/dev/vdb',
'volume_id': vol1['id'],
'delete_on_termination': False, },
'delete_on_termination': False},
{'device_name': '/dev/vdc',
'volume_id': vol2['id'],
'delete_on_termination': True, },
'delete_on_termination': True},
]}
ec2_instance_id = self._run_instance_wait(**kwargs)
instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
@@ -954,7 +1346,7 @@ class CloudTestCase(test.TestCase):
def test_run_with_snapshot(self):
"""Makes sure run/stop/start instance with snapshot works."""
vol = self._volume_create()
ec2_volume_id = ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x')
ec2_volume_id = ec2utils.id_to_ec2_vol_id(vol['id'])
ec2_snapshot1_id = self._create_snapshot(ec2_volume_id)
snapshot1_id = ec2utils.ec2_id_to_id(ec2_snapshot1_id)
@@ -1013,3 +1405,33 @@ class CloudTestCase(test.TestCase):
self.cloud.delete_snapshot(self.context, snapshot_id)
greenthread.sleep(0.3)
db.volume_destroy(self.context, vol['id'])
def test_create_image(self):
"""Make sure that CreateImage works"""
# enforce periodic tasks run in short time to avoid wait for 60s.
self._restart_compute_service(periodic_interval=0.3)
(volumes, snapshots) = self._setUpImageSet(
create_volumes_and_snapshots=True)
kwargs = {'image_id': 'ami-1',
'instance_type': FLAGS.default_instance_type,
'max_count': 1}
ec2_instance_id = self._run_instance_wait(**kwargs)
# TODO(yamahata): s3._s3_create() can't be tested easily by unit test
# as there is no unit test for s3.create()
## result = self.cloud.create_image(self.context, ec2_instance_id,
## no_reboot=True)
## ec2_image_id = result['imageId']
## created_image = self.cloud.describe_images(self.context,
## [ec2_image_id])
self.cloud.terminate_instances(self.context, [ec2_instance_id])
for vol in volumes:
db.volume_destroy(self.context, vol)
for snap in snapshots:
db.snapshot_destroy(self.context, snap)
# TODO(yamahata): clean up snapshot created by CreateImage.
self._restart_compute_service()

View File

@@ -424,11 +424,12 @@ class ComputeTestCase(test.TestCase):
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
context = self.context.elevated()
instance_id = self._create_instance()
self.compute.prep_resize(context, instance_id, 1)
instance_ref = db.instance_get(context, instance_id)
self.compute.prep_resize(context, instance_ref['uuid'], 1)
migration_ref = db.migration_get_by_instance_and_status(context,
instance_id, 'pre-migrating')
instance_ref['uuid'], 'pre-migrating')
try:
self.compute.finish_resize(context, instance_id,
self.compute.finish_resize(context, instance_ref['uuid'],
int(migration_ref['id']), {})
except KeyError, e:
# Only catch key errors. We want other reasons for the test to
@@ -441,14 +442,15 @@ class ComputeTestCase(test.TestCase):
"""Ensure notifications on instance migrate/resize"""
instance_id = self._create_instance()
context = self.context.elevated()
inst_ref = db.instance_get(context, instance_id)
self.compute.run_instance(self.context, instance_id)
test_notifier.NOTIFICATIONS = []
db.instance_update(self.context, instance_id, {'host': 'foo'})
self.compute.prep_resize(context, instance_id, 1)
self.compute.prep_resize(context, inst_ref['uuid'], 1)
migration_ref = db.migration_get_by_instance_and_status(context,
instance_id, 'pre-migrating')
inst_ref['uuid'], 'pre-migrating')
self.assertEquals(len(test_notifier.NOTIFICATIONS), 1)
msg = test_notifier.NOTIFICATIONS[0]
@@ -471,13 +473,15 @@ class ComputeTestCase(test.TestCase):
"""Ensure instance can be migrated/resized"""
instance_id = self._create_instance()
context = self.context.elevated()
inst_ref = db.instance_get(context, instance_id)
self.compute.run_instance(self.context, instance_id)
db.instance_update(self.context, instance_id, {'host': 'foo'})
self.compute.prep_resize(context, instance_id, 1)
db.instance_update(self.context, inst_ref['uuid'],
{'host': 'foo'})
self.compute.prep_resize(context, inst_ref['uuid'], 1)
migration_ref = db.migration_get_by_instance_and_status(context,
instance_id, 'pre-migrating')
self.compute.resize_instance(context, instance_id,
inst_ref['uuid'], 'pre-migrating')
self.compute.resize_instance(context, inst_ref['uuid'],
migration_ref['id'])
self.compute.terminate_instance(context, instance_id)
@@ -519,6 +523,57 @@ class ComputeTestCase(test.TestCase):
self.compute.terminate_instance(context, instance_id)
def test_finish_revert_resize(self):
"""Ensure that the flavor is reverted to the original on revert"""
context = self.context.elevated()
instance_id = self._create_instance()
def fake(*args, **kwargs):
pass
self.stubs.Set(self.compute.driver, 'finish_resize', fake)
self.stubs.Set(self.compute.driver, 'revert_resize', fake)
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
self.compute.run_instance(self.context, instance_id)
# Confirm the instance size before the resize starts
inst_ref = db.instance_get(context, instance_id)
instance_type_ref = db.instance_type_get(context,
inst_ref['instance_type_id'])
self.assertEqual(instance_type_ref['flavorid'], 1)
db.instance_update(self.context, instance_id, {'host': 'foo'})
self.compute.prep_resize(context, inst_ref['uuid'], 3)
migration_ref = db.migration_get_by_instance_and_status(context,
inst_ref['uuid'], 'pre-migrating')
self.compute.resize_instance(context, inst_ref['uuid'],
migration_ref['id'])
self.compute.finish_resize(context, inst_ref['uuid'],
int(migration_ref['id']), {})
# Prove that the instance size is now the new size
inst_ref = db.instance_get(context, instance_id)
instance_type_ref = db.instance_type_get(context,
inst_ref['instance_type_id'])
self.assertEqual(instance_type_ref['flavorid'], 3)
# Finally, revert and confirm the old flavor has been applied
self.compute.revert_resize(context, inst_ref['uuid'],
migration_ref['id'])
self.compute.finish_revert_resize(context, inst_ref['uuid'],
migration_ref['id'])
inst_ref = db.instance_get(context, instance_id)
instance_type_ref = db.instance_type_get(context,
inst_ref['instance_type_id'])
self.assertEqual(instance_type_ref['flavorid'], 1)
self.compute.terminate_instance(context, instance_id)
def test_get_by_flavor_id(self):
type = instance_types.get_instance_type_by_flavor_id(1)
self.assertEqual(type['name'], 'm1.tiny')
@@ -818,3 +873,114 @@ class ComputeTestCase(test.TestCase):
LOG.info(_("After force-killing instances: %s"), instances)
self.assertEqual(len(instances), 1)
self.assertEqual(power_state.SHUTOFF, instances[0]['state'])
@staticmethod
def _parse_db_block_device_mapping(bdm_ref):
attr_list = ('delete_on_termination', 'device_name', 'no_device',
'virtual_name', 'volume_id', 'volume_size', 'snapshot_id')
bdm = {}
for attr in attr_list:
val = bdm_ref.get(attr, None)
if val:
bdm[attr] = val
return bdm
def test_update_block_device_mapping(self):
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': 'ephemeral0', 'device': 'sdc1'},
{'virtual': 'ephemeral1', 'device': 'sdc2'},
{'virtual': 'ephemeral2', 'device': 'sdc3'}]
block_device_mapping = [
# root
{'device_name': '/dev/sda1',
'snapshot_id': 0x12345678,
'delete_on_termination': False},
# overwrite swap
{'device_name': '/dev/sdb2',
'snapshot_id': 0x23456789,
'delete_on_termination': False},
{'device_name': '/dev/sdb3',
'snapshot_id': 0x3456789A},
{'device_name': '/dev/sdb4',
'no_device': True},
# overwrite ephemeral
{'device_name': '/dev/sdc2',
'snapshot_id': 0x456789AB,
'delete_on_termination': False},
{'device_name': '/dev/sdc3',
'snapshot_id': 0x56789ABC},
{'device_name': '/dev/sdc4',
'no_device': True},
# volume
{'device_name': '/dev/sdd1',
'snapshot_id': 0x87654321,
'delete_on_termination': False},
{'device_name': '/dev/sdd2',
'snapshot_id': 0x98765432},
{'device_name': '/dev/sdd3',
'snapshot_id': 0xA9875463},
{'device_name': '/dev/sdd4',
'no_device': True}]
self.compute_api._update_image_block_device_mapping(
self.context, 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': 'ephemeral0', 'device_name': '/dev/sdc1'},
{'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)
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'},
{'snapshot_id': 0x23456789, 'device_name': '/dev/sdb2'},
{'snapshot_id': 0x3456789A, 'device_name': '/dev/sdb3'},
{'no_device': True, 'device_name': '/dev/sdb4'},
{'virtual_name': 'ephemeral0', 'device_name': '/dev/sdc1'},
{'snapshot_id': 0x456789AB, 'device_name': '/dev/sdc2'},
{'snapshot_id': 0x56789ABC, 'device_name': '/dev/sdc3'},
{'no_device': True, 'device_name': '/dev/sdc4'},
{'snapshot_id': 0x87654321, 'device_name': '/dev/sdd1'},
{'snapshot_id': 0x98765432, 'device_name': '/dev/sdd2'},
{'snapshot_id': 0xA9875463, 'device_name': '/dev/sdd3'},
{'no_device': True, 'device_name': '/dev/sdd4'}]
bdms.sort()
expected_result.sort()
self.assertDictListMatch(bdms, expected_result)
for bdm in db.block_device_mapping_get_all_by_instance(
self.context, instance_id):
db.block_device_mapping_destroy(self.context, bdm['id'])
self.compute.terminate_instance(self.context, instance_id)

View File

@@ -58,6 +58,7 @@ def _create_network_info(count=1, ipv6=None):
'cidr': fake_ip,
'cidr_v6': fake_ip}
mapping = {'mac': fake,
'dhcp_server': fake,
'gateway': fake,
'gateway6': fake,
'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
@@ -242,7 +243,7 @@ class LibvirtConnTestCase(test.TestCase):
return """
<domain type='kvm'>
<devices>
<drive type='file'>
<disk type='file'>
<source file='filename'/>
</disk>
</devices>

View File

@@ -45,6 +45,7 @@ class FakeModel(dict):
networks = [{'id': 0,
'label': 'test0',
'injected': False,
'multi_host': False,
'cidr': '192.168.0.0/24',
'cidr_v6': '2001:db8::/64',
'gateway_v6': '2001:db8::1',
@@ -62,6 +63,7 @@ networks = [{'id': 0,
{'id': 1,
'label': 'test1',
'injected': False,
'multi_host': False,
'cidr': '192.168.1.0/24',
'cidr_v6': '2001:db9::/64',
'gateway_v6': '2001:db9::1',
@@ -122,34 +124,20 @@ class FlatNetworkTestCase(test.TestCase):
self.network = network_manager.FlatManager(host=HOST)
self.network.db = db
def test_set_network_hosts(self):
self.mox.StubOutWithMock(db, 'network_get_all')
self.mox.StubOutWithMock(db, 'network_set_host')
self.mox.StubOutWithMock(db, 'network_update')
db.network_get_all(mox.IgnoreArg()).AndReturn([networks[0]])
db.network_set_host(mox.IgnoreArg(),
networks[0]['id'],
mox.IgnoreArg()).AndReturn(HOST)
db.network_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
self.mox.ReplayAll()
self.network.set_network_hosts(None)
def test_get_instance_nw_info(self):
self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance')
self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
self.mox.StubOutWithMock(db, 'instance_type_get_by_id')
self.mox.StubOutWithMock(db, 'instance_type_get')
db.fixed_ip_get_by_instance(mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(fixed_ips)
db.virtual_interface_get_by_instance(mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(vifs)
db.instance_type_get_by_id(mox.IgnoreArg(),
db.instance_type_get(mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(flavor)
self.mox.ReplayAll()
nw_info = self.network.get_instance_nw_info(None, 0, 0)
nw_info = self.network.get_instance_nw_info(None, 0, 0, None)
self.assertTrue(nw_info)
@@ -164,6 +152,7 @@ class FlatNetworkTestCase(test.TestCase):
self.assertDictMatch(nw[0], check)
check = {'broadcast': '192.168.%s.255' % i,
'dhcp_server': '192.168.%s.1' % i,
'dns': 'DONTCARE',
'gateway': '192.168.%s.1' % i,
'gateway6': '2001:db%s::1' % i8,

View File

@@ -27,8 +27,10 @@ from nova import exception
from nova import db
from nova import flags
from nova import log as logging
from nova import rpc
from nova import test
from nova import utils
from nova import volume
FLAGS = flags.FLAGS
LOG = logging.getLogger('nova.tests.volume')
@@ -43,6 +45,11 @@ class VolumeTestCase(test.TestCase):
self.flags(connection_type='fake')
self.volume = utils.import_object(FLAGS.volume_manager)
self.context = context.get_admin_context()
self.instance_id = db.instance_create(self.context, {})['id']
def tearDown(self):
db.instance_destroy(self.context, self.instance_id)
super(VolumeTestCase, self).tearDown()
@staticmethod
def _create_volume(size='0', snapshot_id=None):
@@ -223,6 +230,30 @@ class VolumeTestCase(test.TestCase):
snapshot_id)
self.volume.delete_volume(self.context, volume_id)
def test_create_snapshot_force(self):
"""Test snapshot in use can be created forcibly."""
def fake_cast(ctxt, topic, msg):
pass
self.stubs.Set(rpc, 'cast', fake_cast)
volume_id = self._create_volume()
self.volume.create_volume(self.context, volume_id)
db.volume_attached(self.context, volume_id, self.instance_id,
'/dev/sda1')
volume_api = volume.api.API()
self.assertRaises(exception.ApiError,
volume_api.create_snapshot,
self.context, volume_id,
'fake_name', 'fake_description')
snapshot_ref = volume_api.create_snapshot_force(self.context,
volume_id,
'fake_name',
'fake_description')
db.snapshot_destroy(self.context, snapshot_ref['id'])
db.volume_destroy(self.context, volume_id)
class DriverTestCase(test.TestCase):
"""Base Test class for Drivers."""