summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-10-29 01:57:13 +0000
committerGerrit Code Review <review@openstack.org>2012-10-29 01:57:13 +0000
commite8af7fb5d725287362323fe451593665cb5ce593 (patch)
tree1eee7b567fed959b95facfeb0b609c1bbaf64fa2 /nova/tests
parent580747edd6a7d5fb205bbfddba9eb6a338de1e25 (diff)
parent7e2b93acc59dea81d52684f7f659fcff32507e14 (diff)
Merge "removes the nova-volume code from nova"
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/ec2/test_cinder_cloud.py14
-rw-r--r--nova/tests/api/ec2/test_cloud.py576
-rw-r--r--nova/tests/api/ec2/test_ec2_validate.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_snapshots.py16
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_volume_types.py224
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_volume_types_extra_specs.py198
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_volumes.py15
-rw-r--r--nova/tests/api/openstack/compute/test_extensions.py1
-rw-r--r--nova/tests/api/openstack/fakes.py1
-rw-r--r--nova/tests/api/openstack/volume/__init__.py19
-rw-r--r--nova/tests/api/openstack/volume/contrib/__init__.py19
-rw-r--r--nova/tests/api/openstack/volume/contrib/test_admin_actions.py184
-rw-r--r--nova/tests/api/openstack/volume/contrib/test_types_extra_specs.py226
-rw-r--r--nova/tests/api/openstack/volume/contrib/test_types_manage.py122
-rw-r--r--nova/tests/api/openstack/volume/contrib/test_volume_actions.py162
-rw-r--r--nova/tests/api/openstack/volume/extensions/__init__.py15
-rw-r--r--nova/tests/api/openstack/volume/extensions/foxinsocks.py94
-rw-r--r--nova/tests/api/openstack/volume/test_extensions.py155
-rw-r--r--nova/tests/api/openstack/volume/test_router.py112
-rw-r--r--nova/tests/api/openstack/volume/test_snapshots.py299
-rw-r--r--nova/tests/api/openstack/volume/test_types.py194
-rw-r--r--nova/tests/api/openstack/volume/test_volumes.py602
-rw-r--r--nova/tests/compute/test_compute.py60
-rw-r--r--nova/tests/fake_flags.py2
-rw-r--r--nova/tests/fake_volume.py14
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl8
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl3
-rw-r--r--nova/tests/integrated/integrated_helpers.py3
-rw-r--r--nova/tests/integrated/test_volumes.py181
-rw-r--r--nova/tests/scheduler/test_scheduler.py70
-rw-r--r--nova/tests/test_cinder.py3
-rw-r--r--nova/tests/test_iscsi.py121
-rw-r--r--nova/tests/test_libvirt.py1
-rw-r--r--nova/tests/test_netapp.py1380
-rw-r--r--nova/tests/test_netapp_nfs.py234
-rw-r--r--nova/tests/test_nexenta.py278
-rw-r--r--nova/tests/test_nfs.py569
-rw-r--r--nova/tests/test_plugin_api_extensions.py1
-rw-r--r--nova/tests/test_quota.py23
-rw-r--r--nova/tests/test_rbd.py161
-rw-r--r--nova/tests/test_solidfire.py208
-rw-r--r--nova/tests/test_storwize_svc.py1376
-rw-r--r--nova/tests/test_volume.py931
-rw-r--r--nova/tests/test_volume_types.py167
-rw-r--r--nova/tests/test_volume_types_extra_specs.py130
-rw-r--r--nova/tests/test_volume_utils.py91
-rw-r--r--nova/tests/test_xenapi.py2
-rw-r--r--nova/tests/test_xensm.py140
-rw-r--r--nova/tests/volume/test_HpSanISCSIDriver.py209
49 files changed, 95 insertions, 9520 deletions
diff --git a/nova/tests/api/ec2/test_cinder_cloud.py b/nova/tests/api/ec2/test_cinder_cloud.py
index 389f71b7b..49ee9c152 100644
--- a/nova/tests/api/ec2/test_cinder_cloud.py
+++ b/nova/tests/api/ec2/test_cinder_cloud.py
@@ -18,7 +18,6 @@
# under the License.
import copy
-import shutil
import tempfile
from nova.api.ec2 import cloud
@@ -85,8 +84,7 @@ class CinderCloudTestCase(test.TestCase):
super(CinderCloudTestCase, self).setUp()
vol_tmpdir = tempfile.mkdtemp()
self.flags(compute_driver='nova.virt.fake.FakeDriver',
- volume_api_class='nova.tests.fake_volume.API',
- volumes_dir=vol_tmpdir)
+ volume_api_class='nova.tests.fake_volume.API')
def fake_show(meh, context, id):
return {'id': id,
@@ -123,7 +121,6 @@ class CinderCloudTestCase(test.TestCase):
self.compute = self.start_service('compute')
self.scheduler = self.start_service('scheduler')
self.network = self.start_service('network')
- self.volume = self.start_service('volume')
self.user_id = 'fake'
self.project_id = 'fake'
@@ -143,10 +140,6 @@ class CinderCloudTestCase(test.TestCase):
'76fa36fc-c930-4bf3-8c8a-ea2a2420deb6')
def tearDown(self):
- try:
- shutil.rmtree(FLAGS.volumes_dir)
- except OSError, e:
- pass
self.volume_api.reset_fake_api(self.context)
super(CinderCloudTestCase, self).tearDown()
fake.FakeImageService_reset()
@@ -312,7 +305,7 @@ class CinderCloudTestCase(test.TestCase):
kwargs = {'name': 'bdmtest-volume',
'description': 'bdm test volume description',
'status': 'available',
- 'host': self.volume.host,
+ 'host': 'fake',
'size': 1,
'attach_status': 'detached',
'volume_id': values['id']}
@@ -642,13 +635,12 @@ class CinderCloudTestCase(test.TestCase):
kwargs = {'name': 'test-volume',
'description': 'test volume description',
'status': 'available',
- 'host': self.volume.host,
+ 'host': 'fake',
'size': 1,
'attach_status': 'detached'}
if volume_id:
kwargs['volume_id'] = volume_id
return self.volume_api.create_with_kwargs(self.context, **kwargs)
- #return db.volume_create(self.context, kwargs)
def _assert_volume_attached(self, vol, instance_uuid, mountpoint):
self.assertEqual(vol['instance_uuid'], instance_uuid)
diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py
index d86897dc1..1abde1069 100644
--- a/nova/tests/api/ec2/test_cloud.py
+++ b/nova/tests/api/ec2/test_cloud.py
@@ -22,7 +22,6 @@ import copy
import datetime
import functools
import os
-import shutil
import string
import tempfile
@@ -46,7 +45,7 @@ from nova.tests import fake_network
from nova.tests.image import fake
from nova import utils
from nova.virt import fake as fake_virt
-from nova.volume import iscsi
+from nova import volume
LOG = logging.getLogger(__name__)
@@ -97,10 +96,8 @@ class CloudTestCase(test.TestCase):
super(CloudTestCase, self).setUp()
vol_tmpdir = tempfile.mkdtemp()
self.flags(compute_driver='nova.virt.fake.FakeDriver',
+ volume_api_class='nova.tests.fake_volume.API',
volumes_dir=vol_tmpdir)
- self.stubs.Set(iscsi.TgtAdm, '_get_target', self.fake_get_target)
- self.stubs.Set(iscsi.TgtAdm, 'remove_iscsi_target',
- self.fake_remove_iscsi_target)
def fake_show(meh, context, id):
return {'id': id,
@@ -137,13 +134,13 @@ class CloudTestCase(test.TestCase):
self.compute = self.start_service('compute')
self.scheduler = self.start_service('scheduler')
self.network = self.start_service('network')
- self.volume = self.start_service('volume')
self.user_id = 'fake'
self.project_id = 'fake'
self.context = context.RequestContext(self.user_id,
self.project_id,
is_admin=True)
+ self.volume_api = volume.API()
# NOTE(comstud): Make 'cast' behave like a 'call' which will
# ensure that operations complete
@@ -156,10 +153,7 @@ class CloudTestCase(test.TestCase):
'76fa36fc-c930-4bf3-8c8a-ea2a2420deb6')
def tearDown(self):
- try:
- shutil.rmtree(FLAGS.volumes_dir)
- except OSError, e:
- pass
+ self.volume_api.reset_fake_api(self.context)
super(CloudTestCase, self).tearDown()
fake.FakeImageService_reset()
@@ -681,63 +675,6 @@ class CloudTestCase(test.TestCase):
self.cloud.delete_security_group(self.context, 'testgrp')
- def test_describe_volumes(self):
- """Makes sure describe_volumes works and filters results."""
- vol1 = db.volume_create(self.context, {'project_id': self.project_id})
- vol2 = db.volume_create(self.context, {'project_id': self.project_id})
- result = self.cloud.describe_volumes(self.context)
- self.assertEqual(len(result['volumeSet']), 2)
- 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)
- self.assertEqual(
- ec2utils.ec2_vol_id_to_uuid(
- result['volumeSet'][0]['volumeId']),
- vol2['id'])
- db.volume_destroy(self.context, vol1['id'])
- db.volume_destroy(self.context, vol2['id'])
-
- def test_create_volume_in_availability_zone(self):
- """Makes sure create_volume works when we specify an availability
- zone
- """
- availability_zone = 'zone1:host1'
-
- result = self.cloud.create_volume(self.context,
- size=1,
- availability_zone=availability_zone)
- volume_id = result['volumeId']
- availabilityZone = result['availabilityZone']
- self.assertEqual(availabilityZone, availability_zone)
- result = self.cloud.describe_volumes(self.context)
- self.assertEqual(len(result['volumeSet']), 1)
- self.assertEqual(result['volumeSet'][0]['volumeId'], volume_id)
- self.assertEqual(result['volumeSet'][0]['availabilityZone'],
- availabilityZone)
-
- db.volume_destroy(self.context, ec2utils.ec2_vol_id_to_uuid(volume_id))
-
- def test_create_volume_from_snapshot(self):
- """Makes sure create_volume works when we specify a snapshot."""
- vol = db.volume_create(self.context, {'size': 1,
- 'project_id': self.project_id})
- snap = db.snapshot_create(self.context, {'volume_id': vol['id'],
- 'volume_size': vol['size'],
- 'status': "available"})
- snapshot_id = ec2utils.id_to_ec2_snap_id(snap['id'])
-
- result = self.cloud.create_volume(self.context,
- snapshot_id=snapshot_id)
- volume_id = result['volumeId']
- result = self.cloud.describe_volumes(self.context)
- self.assertEqual(len(result['volumeSet']), 2)
- self.assertEqual(result['volumeSet'][1]['volumeId'], volume_id)
-
- db.volume_destroy(self.context, ec2utils.ec2_vol_id_to_uuid(volume_id))
- db.snapshot_destroy(self.context, snap['id'])
- db.volume_destroy(self.context, vol['id'])
-
def test_describe_availability_zones(self):
"""Makes sure describe_availability_zones works and filters results."""
service1 = db.service_create(self.context, {'host': 'host1_zones',
@@ -772,63 +709,10 @@ class CloudTestCase(test.TestCase):
result = self.cloud.describe_availability_zones(admin_ctxt,
zone_name='verbose')
- self.assertEqual(len(result['availabilityZoneInfo']), 15)
+ self.assertEqual(len(result['availabilityZoneInfo']), 13)
db.service_destroy(self.context, service1['id'])
db.service_destroy(self.context, service2['id'])
- def test_describe_snapshots(self):
- """Makes sure describe_snapshots works and filters results."""
- vol = db.volume_create(self.context, {})
- snap1 = db.snapshot_create(self.context,
- {'volume_id': vol['id'], 'project_id': self.project_id})
- snap2 = db.snapshot_create(self.context,
- {'volume_id': vol['id'], 'project_id': self.project_id})
- result = self.cloud.describe_snapshots(self.context)
- self.assertEqual(len(result['snapshotSet']), 2)
- 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)
- self.assertEqual(
- ec2utils.ec2_snap_id_to_uuid(
- result['snapshotSet'][0]['snapshotId']),
- snap2['id'])
- db.snapshot_destroy(self.context, snap1['id'])
- db.snapshot_destroy(self.context, snap2['id'])
- db.volume_destroy(self.context, vol['id'])
-
- def test_create_snapshot(self):
- """Makes sure create_snapshot works."""
- vol = db.volume_create(self.context,
- {'status': "available", 'size': 0})
- volume_id = ec2utils.id_to_ec2_vol_id(vol['id'])
-
- result = self.cloud.create_snapshot(self.context,
- volume_id=volume_id)
- snapshot_id = result['snapshotId']
- result = self.cloud.describe_snapshots(self.context)
- self.assertEqual(len(result['snapshotSet']), 1)
- self.assertEqual(result['snapshotSet'][0]['snapshotId'], snapshot_id)
-
- db.snapshot_destroy(self.context, ec2utils.ec2_id_to_id(snapshot_id))
- db.volume_destroy(self.context, vol['id'])
-
- def test_delete_snapshot(self):
- """Makes sure delete_snapshot works."""
- vol = db.volume_create(self.context,
- {'status': "available", 'size': 0})
- snap = db.snapshot_create(self.context,
- {'volume_id': vol['id'],
- 'status': "available",
- 'volume_size': 0})
- snapshot_id = ec2utils.id_to_ec2_snap_id(snap['id'])
-
- result = self.cloud.delete_snapshot(self.context,
- snapshot_id=snapshot_id)
- self.assertTrue(result)
-
- db.volume_destroy(self.context, vol['id'])
-
def test_describe_instances(self):
"""Makes sure describe_instances works and filters results."""
self.flags(use_ipv6=True)
@@ -1035,189 +919,6 @@ class CloudTestCase(test.TestCase):
result = self.cloud.describe_instances(self.context)
self.assertEqual(len(result['reservationSet']), 2)
- def _block_device_mapping_create(self, instance_uuid, 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_uuid, bdm['device_name'])
- volumes.append(vol)
- return volumes
-
- def _setUpBlockDeviceMapping(self):
- image_uuid = 'cedef40a-ed67-4d10-800e-17455edce175'
- inst1 = db.instance_create(self.context,
- {'image_ref': image_uuid,
- 'instance_type_id': 1,
- 'root_device_name': '/dev/sdb1'})
- inst2 = db.instance_create(self.context,
- {'image_ref': image_uuid,
- 'instance_type_id': 1,
- 'root_device_name': '/dev/sdc1'})
-
- instance_id = inst1['id']
- instance_uuid = inst1['uuid']
- mappings0 = [
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb1',
- 'snapshot_id': '1',
- 'volume_id': '2'},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb2',
- 'volume_id': '3',
- 'volume_size': 1},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb3',
- 'delete_on_termination': True,
- 'snapshot_id': '4',
- 'volume_id': '5'},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb4',
- 'delete_on_termination': False,
- 'snapshot_id': '6',
- 'volume_id': '7'},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb5',
- 'snapshot_id': '8',
- 'volume_id': '9',
- 'volume_size': 0},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb6',
- 'snapshot_id': '10',
- 'volume_id': '11',
- 'volume_size': 1},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb7',
- 'no_device': True},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb8',
- 'virtual_name': 'swap'},
- {'instance_uuid': instance_uuid,
- 'device_name': '/dev/sdb9',
- 'virtual_name': 'ephemeral3'}]
-
- volumes = self._block_device_mapping_create(instance_uuid, mappings0)
- return (inst1, inst2, volumes)
-
- def _tearDownBlockDeviceMapping(self, inst1, inst2, volumes):
- for vol in volumes:
- db.volume_destroy(self.context, vol['id'])
- for uuid in (inst1['uuid'], inst2['uuid']):
- for bdm in db.block_device_mapping_get_all_by_instance(
- self.context, uuid):
- db.block_device_mapping_destroy(self.context, bdm['id'])
- db.instance_destroy(self.context, inst2['uuid'])
- db.instance_destroy(self.context, inst1['uuid'])
-
- _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['uuid'],
- '/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['uuid'],
- '/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_inst_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['uuid'])
- self.assertSubDictMatch(self._expected_instance_bdm1, result)
- self._assertEqualBlockDeviceMapping(
- self._expected_block_device_mapping0, result['blockDeviceMapping'])
-
- result = self._assertInstance(inst2['uuid'])
- self.assertSubDictMatch(self._expected_instance_bdm2, result)
-
- self._tearDownBlockDeviceMapping(inst1, inst2, volumes)
-
def test_describe_images(self):
describe_images = self.cloud.describe_images
@@ -1281,13 +982,17 @@ class CloudTestCase(test.TestCase):
{'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/sdb1',
+ 'snapshot_id': 'ccec42a2-c220-4806-b762-6b12fbb592e3'},
+ {'device_name': '/dev/sdb2',
+ 'volume_id': 'ccec42a2-c220-4806-b762-6b12fbb592e4'},
{'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/sdc1',
+ 'snapshot_id': 'ccec42a2-c220-4806-b762-6b12fbb592e5'},
+ {'device_name': '/dev/sdc2',
+ 'volume_id': 'ccec42a2-c220-4806-b762-6b12fbb592e6'},
{'device_name': '/dev/sdc3', 'virtual_name': 'ephemeral6'},
{'device_name': '/dev/sdc4', 'no_device': True}]
image1 = {
@@ -1305,7 +1010,7 @@ class CloudTestCase(test.TestCase):
mappings2 = [{'device': '/dev/sda1', 'virtual': 'root'}]
block_device_mapping2 = [{'device_name': '/dev/sdb1',
- 'snapshot_id': 01234567}]
+ 'snapshot_id': 'ccec42a2-c220-4806-b762-6b12fbb592e7'}]
image2 = {
'id': '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6',
'name': 'fake_name',
@@ -1338,11 +1043,7 @@ class CloudTestCase(test.TestCase):
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': 01234567,
- 'status': "available",
- 'volume_size': 1})
+ snap = self._snapshot_create(bdm['snapshot_id'])
snapshots.append(snap['id'])
return (volumes, snapshots)
@@ -1364,24 +1065,24 @@ class CloudTestCase(test.TestCase):
_expected_bdms1 = [
{'deviceName': '/dev/sdb0', 'virtualName': 'ephemeral0'},
{'deviceName': '/dev/sdb1', 'ebs': {'snapshotId':
- 'snap-00053977'}},
+ 'snap-00000001'}},
{'deviceName': '/dev/sdb2', 'ebs': {'snapshotId':
- 'vol-00053977'}},
+ 'vol-00000001'}},
{'deviceName': '/dev/sdb3', 'virtualName': 'ephemeral5'},
# {'deviceName': '/dev/sdb4', 'noDevice': True},
{'deviceName': '/dev/sdc0', 'virtualName': 'swap'},
{'deviceName': '/dev/sdc1', 'ebs': {'snapshotId':
- 'snap-00bc614e'}},
+ 'snap-00000002'}},
{'deviceName': '/dev/sdc2', 'ebs': {'snapshotId':
- 'vol-00bc614e'}},
+ 'vol-00000002'}},
{'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'}}]
+ 'ebs': {'snapshotId': 'snap-00000003'}}]
# NOTE(yamahata):
# InstanceBlockDeviceMappingItemType
@@ -2066,228 +1767,30 @@ class CloudTestCase(test.TestCase):
self.assertTrue(result)
def _volume_create(self, volume_id=None):
- location = '10.0.2.15:3260'
- iqn = 'iqn.2010-10.org.openstack:%s' % volume_id
- kwargs = {'status': 'available',
- 'host': self.volume.host,
+ kwargs = {'name': 'test-volume',
+ 'description': 'test volume description',
+ 'status': 'available',
+ 'host': 'fake',
'size': 1,
- 'provider_location': '1 %s,fake %s' % (location, iqn),
- 'attach_status': 'detached', }
+ 'attach_status': 'detached'}
if volume_id:
- kwargs['id'] = volume_id
- return db.volume_create(self.context, kwargs)
-
- def _assert_volume_attached(self, vol, instance_uuid, mountpoint):
- self.assertEqual(vol['instance_uuid'], instance_uuid)
- self.assertEqual(vol['mountpoint'], mountpoint)
- self.assertEqual(vol['status'], "in-use")
- self.assertEqual(vol['attach_status'], "attached")
- self.assertNotEqual(vol['attach_time'], None)
-
- def _assert_volume_detached(self, vol):
- self.assertEqual(vol['instance_uuid'], None)
- self.assertEqual(vol['mountpoint'], None)
- self.assertEqual(vol['status'], "available")
- self.assertEqual(vol['attach_status'], "detached")
- self.assertEqual(vol['attach_time'], None)
-
- def test_stop_start_with_volume(self):
- """Make sure run instance with block device mapping works"""
-
- # enforce periodic tasks run in short time to avoid wait for 60s.
- self._restart_compute_service(periodic_interval=0.3)
-
- vol1 = self._volume_create()
- vol2 = self._volume_create()
- kwargs = {'image_id': 'ami-1',
- 'instance_type': FLAGS.default_instance_type,
- 'max_count': 1,
- 'block_device_mapping': [{'device_name': '/dev/vdb',
- 'volume_id': vol1['id'],
- 'delete_on_termination': False},
- {'device_name': '/dev/vdc',
- 'volume_id': vol2['id'],
- 'delete_on_termination': True},
- ]}
- ec2_instance_id = self._run_instance(**kwargs)
- instance_uuid = ec2utils.ec2_instance_id_to_uuid(self.context,
- ec2_instance_id)
- instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
-
- vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
- self.assertEqual(len(vols), 2)
- for vol in vols:
- self.assertTrue(vol['id'] == vol1['id'] or vol['id'] == vol2['id'])
-
- vol = db.volume_get(self.context, vol1['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/vdb')
-
- vol = db.volume_get(self.context, vol2['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/vdc')
-
- result = self.cloud.stop_instances(self.context, [ec2_instance_id])
- self.assertTrue(result)
-
- vol = db.volume_get(self.context, vol1['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/vdb')
-
- vol = db.volume_get(self.context, vol2['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/vdc')
-
- self.cloud.start_instances(self.context, [ec2_instance_id])
- vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
- self.assertEqual(len(vols), 2)
- for vol in vols:
- self.assertTrue(vol['id'] == vol1['id'] or vol['id'] == vol2['id'])
- self.assertTrue(vol['mountpoint'] == '/dev/vdb' or
- vol['mountpoint'] == '/dev/vdc')
- self.assertEqual(vol['instance_uuid'], instance_uuid)
- self.assertEqual(vol['status'], "in-use")
- self.assertEqual(vol['attach_status'], "attached")
-
- self.cloud.terminate_instances(self.context, [ec2_instance_id])
-
- admin_ctxt = context.get_admin_context(read_deleted="no")
- vol = db.volume_get(admin_ctxt, vol1['id'])
- self.assertFalse(vol['deleted'])
- db.volume_destroy(self.context, vol1['id'])
-
- admin_ctxt = context.get_admin_context(read_deleted="only")
- vol = db.volume_get(admin_ctxt, vol2['id'])
- self.assertTrue(vol['deleted'])
-
- self._restart_compute_service()
-
- def test_stop_with_attached_volume(self):
- """Make sure attach info is reflected to block device mapping"""
- # enforce periodic tasks run in short time to avoid wait for 60s.
- self._restart_compute_service(periodic_interval=0.3)
-
- vol1 = self._volume_create()
- vol2 = self._volume_create()
- kwargs = {'image_id': 'ami-1',
- 'instance_type': FLAGS.default_instance_type,
- 'max_count': 1,
- 'block_device_mapping': [{'device_name': '/dev/sdb',
- 'volume_id': vol1['id'],
- 'delete_on_termination': True}]}
- ec2_instance_id = self._run_instance(**kwargs)
- instance_id = ec2utils.ec2_id_to_id(ec2_instance_id)
- instance_uuid = ec2utils.ec2_instance_id_to_uuid(self.context,
- ec2_instance_id)
-
- vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
- self.assertEqual(len(vols), 1)
- for vol in vols:
- self.assertEqual(vol['id'], vol1['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/sdb')
-
- vol = db.volume_get(self.context, vol2['id'])
- self._assert_volume_detached(vol)
-
- instance = db.instance_get(self.context, instance_id)
- self.cloud.compute_api.attach_volume(self.context,
- instance,
- volume_id=vol2['id'],
- device='/dev/vdc')
- vol = db.volume_get(self.context, vol2['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/sdc')
-
- self.cloud.compute_api.detach_volume(self.context,
- volume_id=vol1['id'])
- vol = db.volume_get(self.context, vol1['id'])
- self._assert_volume_detached(vol)
-
- result = self.cloud.stop_instances(self.context, [ec2_instance_id])
- self.assertTrue(result)
-
- vol = db.volume_get(self.context, vol2['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/sdc')
-
- self.cloud.start_instances(self.context, [ec2_instance_id])
- vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
- self.assertEqual(len(vols), 1)
- for vol in vols:
- self.assertEqual(vol['id'], vol2['id'])
- self._assert_volume_attached(vol, instance_uuid, '/dev/sdc')
-
- vol = db.volume_get(self.context, vol1['id'])
- self._assert_volume_detached(vol)
-
- self.cloud.terminate_instances(self.context, [ec2_instance_id])
-
- for vol_id in (vol1['id'], vol2['id']):
- vol = db.volume_get(self.context, vol_id)
- self.assertEqual(vol['id'], vol_id)
- self._assert_volume_detached(vol)
- db.volume_destroy(self.context, vol_id)
-
- self._restart_compute_service()
+ kwargs['volume_id'] = volume_id
+ return self.volume_api.create_with_kwargs(self.context, **kwargs)
+
+ def _snapshot_create(self, snapshot_id=None):
+ kwargs = {'volume_id': 'ccec42a2-c220-4806-b762-6b12fbb592e4',
+ 'status': "available",
+ 'volume_size': 1}
+ if snapshot_id:
+ kwargs['snap_id'] = snapshot_id
+ return self.volume_api.create_snapshot_with_kwargs(self.context,
+ **kwargs)
def _create_snapshot(self, ec2_volume_id):
result = self.cloud.create_snapshot(self.context,
volume_id=ec2_volume_id)
return result['snapshotId']
- 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_vol_id(vol['id'])
-
- ec2_snapshot1_id = self._create_snapshot(ec2_volume_id)
- snapshot1_id = ec2utils.ec2_snap_id_to_uuid(ec2_snapshot1_id)
- ec2_snapshot2_id = self._create_snapshot(ec2_volume_id)
- snapshot2_id = ec2utils.ec2_snap_id_to_uuid(ec2_snapshot2_id)
-
- kwargs = {'image_id': 'ami-1',
- 'instance_type': FLAGS.default_instance_type,
- 'max_count': 1,
- 'block_device_mapping': [{'device_name': '/dev/vdb',
- 'snapshot_id': snapshot1_id,
- 'delete_on_termination': False, },
- {'device_name': '/dev/vdc',
- 'snapshot_id': snapshot2_id,
- 'delete_on_termination': True}]}
- ec2_instance_id = self._run_instance(**kwargs)
- instance_id = ec2utils.ec2_vol_id_to_uuid(ec2_instance_id)
- instance_uuid = ec2utils.ec2_instance_id_to_uuid(self.context,
- ec2_instance_id)
-
- vols = db.volume_get_all_by_instance_uuid(self.context, instance_uuid)
- self.assertEqual(len(vols), 2)
- vol1_id = None
- vol2_id = None
- for vol in vols:
- snapshot_id = vol['snapshot_id']
- if snapshot_id == snapshot1_id:
- vol1_id = vol['id']
- mountpoint = '/dev/vdb'
- elif snapshot_id == snapshot2_id:
- vol2_id = vol['id']
- mountpoint = '/dev/vdc'
- else:
- self.fail()
-
- self._assert_volume_attached(vol, instance_uuid, mountpoint)
-
- self.assertTrue(vol1_id)
- self.assertTrue(vol2_id)
-
- self.cloud.terminate_instances(self.context, [ec2_instance_id])
-
- admin_ctxt = context.get_admin_context(read_deleted="no")
- vol = db.volume_get(admin_ctxt, vol1_id)
- self._assert_volume_detached(vol)
- self.assertFalse(vol['deleted'])
- db.volume_destroy(self.context, vol1_id)
-
- admin_ctxt = context.get_admin_context(read_deleted="only")
- vol = db.volume_get(admin_ctxt, vol2_id)
- self.assertTrue(vol['deleted'])
-
- for snapshot_id in (ec2_snapshot1_id, ec2_snapshot2_id):
- self.cloud.delete_snapshot(self.context, snapshot_id)
-
def _do_test_create_image(self, no_reboot):
"""Make sure that CreateImage works"""
# enforce periodic tasks run in short time to avoid wait for 60s.
@@ -2363,7 +1866,7 @@ class CloudTestCase(test.TestCase):
self.assertEquals(bdm.get('deviceName'), 'sda1')
self.assertTrue('ebs' in bdm)
self.assertEquals(bdm['ebs'].get('snapshotId'),
- 'snap-%08x' % snapshots[0])
+ ec2utils.id_to_ec2_snap_id(snapshots[0]))
self.assertEquals(created_image.get('kernelId'), 'aki-00000001')
self.assertEquals(created_image.get('ramdiskId'), 'ari-00000002')
self.assertEquals(created_image.get('rootDeviceType'), 'ebs')
@@ -2371,11 +1874,6 @@ class CloudTestCase(test.TestCase):
self.assertNotEqual(virt_driver.get('powered_off'), no_reboot)
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()
diff --git a/nova/tests/api/ec2/test_ec2_validate.py b/nova/tests/api/ec2/test_ec2_validate.py
index 9a14a7d7c..f46262c35 100644
--- a/nova/tests/api/ec2/test_ec2_validate.py
+++ b/nova/tests/api/ec2/test_ec2_validate.py
@@ -50,7 +50,6 @@ class EC2ValidateTestCase(test.TestCase):
self.compute = self.start_service('compute')
self.scheduter = self.start_service('scheduler')
self.network = self.start_service('network')
- self.volume = self.start_service('volume')
self.image_service = fake.FakeImageService()
self.user_id = 'fake'
diff --git a/nova/tests/api/openstack/compute/contrib/test_snapshots.py b/nova/tests/api/openstack/compute/contrib/test_snapshots.py
index ad259c302..6e76fc04a 100644
--- a/nova/tests/api/openstack/compute/contrib/test_snapshots.py
+++ b/nova/tests/api/openstack/compute/contrib/test_snapshots.py
@@ -25,7 +25,7 @@ from nova.openstack.common import log as logging
from nova.openstack.common import timeutils
from nova import test
from nova.tests.api.openstack import fakes
-from nova import volume
+from nova.volume import cinder
FLAGS = flags.FLAGS
@@ -92,14 +92,16 @@ class SnapshotApiTest(test.TestCase):
super(SnapshotApiTest, self).setUp()
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
- self.stubs.Set(volume.api.API, "create_snapshot", stub_snapshot_create)
- self.stubs.Set(volume.api.API, "create_snapshot_force",
+ self.stubs.Set(cinder.API, "create_snapshot",
+ stub_snapshot_create)
+ self.stubs.Set(cinder.API, "create_snapshot_force",
stub_snapshot_create)
- self.stubs.Set(volume.api.API, "delete_snapshot", stub_snapshot_delete)
- self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
- self.stubs.Set(volume.api.API, "get_all_snapshots",
+ self.stubs.Set(cinder.API, "delete_snapshot",
+ stub_snapshot_delete)
+ self.stubs.Set(cinder.API, "get_snapshot", stub_snapshot_get)
+ self.stubs.Set(cinder.API, "get_all_snapshots",
stub_snapshot_get_all)
- self.stubs.Set(volume.api.API, "get", fakes.stub_volume_get)
+ self.stubs.Set(cinder.API, "get", fakes.stub_volume_get)
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.contrib.select_extensions'],
diff --git a/nova/tests/api/openstack/compute/contrib/test_volume_types.py b/nova/tests/api/openstack/compute/contrib/test_volume_types.py
deleted file mode 100644
index af88cf601..000000000
--- a/nova/tests/api/openstack/compute/contrib/test_volume_types.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# Copyright 2011 OpenStack LLC.
-# 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 lxml import etree
-import webob
-
-from nova.api.openstack.compute.contrib import volumetypes
-from nova import exception
-from nova.openstack.common import log as logging
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova.volume import volume_types
-
-
-LOG = logging.getLogger(__name__)
-last_param = {}
-
-
-def stub_volume_type(id):
- specs = {
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- "key4": "value4",
- "key5": "value5"}
- return dict(id=id, name='vol_type_%s' % str(id), extra_specs=specs)
-
-
-def return_volume_types_get_all_types(context):
- return dict(vol_type_1=stub_volume_type(1),
- vol_type_2=stub_volume_type(2),
- vol_type_3=stub_volume_type(3))
-
-
-def return_empty_volume_types_get_all_types(context):
- return {}
-
-
-def return_volume_types_get_volume_type(context, id):
- if id == "777":
- raise exception.VolumeTypeNotFound(volume_type_id=id)
- return stub_volume_type(int(id))
-
-
-def return_volume_types_destroy(context, name):
- if name == "777":
- raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
- pass
-
-
-def return_volume_types_create(context, name, specs):
- pass
-
-
-def return_volume_types_get_by_name(context, name):
- if name == "777":
- raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
- return stub_volume_type(int(name.split("_")[2]))
-
-
-class VolumeTypesApiTest(test.TestCase):
- def setUp(self):
- super(VolumeTypesApiTest, self).setUp()
- fakes.stub_out_key_pair_funcs(self.stubs)
- self.controller = volumetypes.VolumeTypesController()
-
- def test_volume_types_index(self):
- self.stubs.Set(volume_types, 'get_all_types',
- return_volume_types_get_all_types)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types')
- res_dict = self.controller.index(req)
-
- self.assertEqual(3, len(res_dict['volume_types']))
-
- expected_names = ['vol_type_1', 'vol_type_2', 'vol_type_3']
- actual_names = map(lambda e: e['name'], res_dict['volume_types'])
- self.assertEqual(set(actual_names), set(expected_names))
- for entry in res_dict['volume_types']:
- self.assertEqual('value1', entry['extra_specs']['key1'])
-
- def test_volume_types_index_no_data(self):
- self.stubs.Set(volume_types, 'get_all_types',
- return_empty_volume_types_get_all_types)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types')
- res_dict = self.controller.index(req)
-
- self.assertEqual(0, len(res_dict['volume_types']))
-
- def test_volume_types_show(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types/1')
- res_dict = self.controller.show(req, 1)
-
- self.assertEqual(1, len(res_dict))
- self.assertEqual('vol_type_1', res_dict['volume_type']['name'])
-
- def test_volume_types_show_not_found(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types/777')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
- req, '777')
-
- def test_volume_types_delete(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
- self.stubs.Set(volume_types, 'destroy',
- return_volume_types_destroy)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types/1')
- self.controller.delete(req, 1)
-
- def test_volume_types_delete_not_found(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
- self.stubs.Set(volume_types, 'destroy',
- return_volume_types_destroy)
-
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types/777')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
- req, '777')
-
- def test_create(self):
- self.stubs.Set(volume_types, 'create',
- return_volume_types_create)
- self.stubs.Set(volume_types, 'get_volume_type_by_name',
- return_volume_types_get_by_name)
-
- body = {"volume_type": {"name": "vol_type_1",
- "extra_specs": {"key1": "value1"}}}
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types')
- res_dict = self.controller.create(req, body)
-
- self.assertEqual(1, len(res_dict))
- self.assertEqual('vol_type_1', res_dict['volume_type']['name'])
-
-
-class VolumeTypesSerializerTest(test.TestCase):
- def _verify_volume_type(self, vtype, tree):
- self.assertEqual('volume_type', tree.tag)
- self.assertEqual(vtype['name'], tree.get('name'))
- self.assertEqual(str(vtype['id']), tree.get('id'))
- self.assertEqual(1, len(tree))
- extra_specs = tree[0]
- self.assertEqual('extra_specs', extra_specs.tag)
- seen = set(vtype['extra_specs'].keys())
- for child in extra_specs:
- self.assertTrue(child.tag in seen)
- self.assertEqual(vtype['extra_specs'][child.tag], child.text)
- seen.remove(child.tag)
- self.assertEqual(len(seen), 0)
-
- def test_index_serializer(self):
- serializer = volumetypes.VolumeTypesTemplate()
-
- # Just getting some input data
- vtypes = return_volume_types_get_all_types(None)
- text = serializer.serialize({'volume_types': vtypes.values()})
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('volume_types', tree.tag)
- self.assertEqual(len(vtypes), len(tree))
- for child in tree:
- name = child.get('name')
- self.assertTrue(name in vtypes)
- self._verify_volume_type(vtypes[name], child)
-
- def test_voltype_serializer(self):
- serializer = volumetypes.VolumeTypeTemplate()
-
- vtype = stub_volume_type(1)
- text = serializer.serialize(dict(volume_type=vtype))
-
- print text
- tree = etree.fromstring(text)
-
- self._verify_volume_type(vtype, tree)
-
-
-class VolumeTypesUnprocessableEntityTestCase(test.TestCase):
- """
- Tests of places we throw 422 Unprocessable Entity from
- """
-
- def setUp(self):
- super(VolumeTypesUnprocessableEntityTestCase, self).setUp()
- self.controller = volumetypes.VolumeTypesController()
-
- def _unprocessable_volume_type_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/os-volume-types')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.create, req, body)
-
- def test_create_volume_type_no_body(self):
- self._unprocessable_volume_type_create(body=None)
-
- def test_create_volume_type_missing_volume_type(self):
- body = {'foo': {'a': 'b'}}
- self._unprocessable_volume_type_create(body=body)
-
- def test_create_volume_type_malformed_entity(self):
- body = {'volume_type': 'string'}
- self._unprocessable_volume_type_create(body=body)
diff --git a/nova/tests/api/openstack/compute/contrib/test_volume_types_extra_specs.py b/nova/tests/api/openstack/compute/contrib/test_volume_types_extra_specs.py
deleted file mode 100644
index e9c4034f0..000000000
--- a/nova/tests/api/openstack/compute/contrib/test_volume_types_extra_specs.py
+++ /dev/null
@@ -1,198 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Zadara Storage Inc.
-# Copyright (c) 2011 OpenStack LLC.
-# Copyright 2011 University of Southern California
-# 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 lxml import etree
-import webob
-
-from nova.api.openstack.compute.contrib import volumetypes
-from nova import test
-from nova.tests.api.openstack import fakes
-import nova.wsgi
-
-
-def return_create_volume_type_extra_specs(context, volume_type_id,
- extra_specs):
- return stub_volume_type_extra_specs()
-
-
-def return_volume_type_extra_specs(context, volume_type_id):
- return stub_volume_type_extra_specs()
-
-
-def return_empty_volume_type_extra_specs(context, volume_type_id):
- return {}
-
-
-def delete_volume_type_extra_specs(context, volume_type_id, key):
- pass
-
-
-def stub_volume_type_extra_specs():
- specs = {
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- "key4": "value4",
- "key5": "value5"}
- return specs
-
-
-class VolumeTypesExtraSpecsTest(test.TestCase):
-
- def setUp(self):
- super(VolumeTypesExtraSpecsTest, self).setUp()
- fakes.stub_out_key_pair_funcs(self.stubs)
- self.api_path = '/v2/fake/os-volume-types/1/extra_specs'
- self.controller = volumetypes.VolumeTypeExtraSpecsController()
-
- def test_index(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.index(req, 1)
-
- self.assertEqual('value1', res_dict['extra_specs']['key1'])
-
- def test_index_no_data(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_empty_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.index(req, 1)
-
- self.assertEqual(0, len(res_dict['extra_specs']))
-
- def test_show(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key5')
- res_dict = self.controller.show(req, 1, 'key5')
-
- self.assertEqual('value5', res_dict['key5'])
-
- def test_show_spec_not_found(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_empty_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key6')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
- req, 1, 'key6')
-
- def test_delete(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_delete',
- delete_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key5')
- self.controller.delete(req, 1, 'key5')
-
- def test_create(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"extra_specs": {"key1": "value1"}}
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.create(req, 1, body)
-
- self.assertEqual('value1', res_dict['extra_specs']['key1'])
-
- def test_create_empty_body(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path)
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
- req, 1, '')
-
- def test_update_item(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key1')
- res_dict = self.controller.update(req, 1, 'key1', body)
-
- self.assertEqual('value1', res_dict['key1'])
-
- def test_update_item_empty_body(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key1')
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
- req, 1, 'key1', '')
-
- def test_update_item_too_many_keys(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1", "key2": "value2"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key1')
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
- req, 1, 'key1', body)
-
- def test_update_item_body_uri_mismatch(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/bad')
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
- req, 1, 'bad', body)
-
-
-class VolumeTypeExtraSpecsSerializerTest(test.TestCase):
- def test_index_create_serializer(self):
- serializer = volumetypes.VolumeTypeExtraSpecsTemplate()
-
- # Just getting some input data
- extra_specs = stub_volume_type_extra_specs()
- text = serializer.serialize(dict(extra_specs=extra_specs))
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('extra_specs', tree.tag)
- self.assertEqual(len(extra_specs), len(tree))
- seen = set(extra_specs.keys())
- for child in tree:
- self.assertTrue(child.tag in seen)
- self.assertEqual(extra_specs[child.tag], child.text)
- seen.remove(child.tag)
- self.assertEqual(len(seen), 0)
-
- def test_update_show_serializer(self):
- serializer = volumetypes.VolumeTypeExtraSpecTemplate()
-
- exemplar = dict(key1='value1')
- text = serializer.serialize(exemplar)
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('key1', tree.tag)
- self.assertEqual('value1', tree.text)
- self.assertEqual(0, len(tree))
diff --git a/nova/tests/api/openstack/compute/contrib/test_volumes.py b/nova/tests/api/openstack/compute/contrib/test_volumes.py
index a07c3fa74..6c092cbd4 100644
--- a/nova/tests/api/openstack/compute/contrib/test_volumes.py
+++ b/nova/tests/api/openstack/compute/contrib/test_volumes.py
@@ -18,7 +18,6 @@ import datetime
from lxml import etree
import webob
-import nova
from nova.api.openstack.compute.contrib import volumes
from nova.compute import api as compute_api
from nova.compute import instance_types
@@ -29,7 +28,7 @@ from nova.openstack.common import jsonutils
from nova.openstack.common import timeutils
from nova import test
from nova.tests.api.openstack import fakes
-from nova.volume import api as volume_api
+from nova.volume import cinder
from webob import exc
@@ -148,9 +147,9 @@ class VolumeApiTest(test.TestCase):
fakes.stub_out_rate_limiting(self.stubs)
self.stubs.Set(db, 'volume_get', return_volume)
- self.stubs.Set(volume_api.API, "delete", fakes.stub_volume_delete)
- self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get)
- self.stubs.Set(volume_api.API, "get_all", fakes.stub_volume_get_all)
+ self.stubs.Set(cinder.API, "delete", fakes.stub_volume_delete)
+ self.stubs.Set(cinder.API, "get", fakes.stub_volume_get)
+ self.stubs.Set(cinder.API, "get_all", fakes.stub_volume_get_all)
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.contrib.select_extensions'],
@@ -160,7 +159,7 @@ class VolumeApiTest(test.TestCase):
self.app = fakes.wsgi_app(init_only=('os-volumes',))
def test_volume_create(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
+ self.stubs.Set(cinder.API, "create", fakes.stub_volume_create)
vol = {"size": 100,
"display_name": "Volume Test Name",
@@ -202,7 +201,7 @@ class VolumeApiTest(test.TestCase):
self.assertEqual(resp.status_int, 200)
def test_volume_show_no_volume(self):
- self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get_notfound)
+ self.stubs.Set(cinder.API, "get", fakes.stub_volume_get_notfound)
req = webob.Request.blank('/v2/fake/os-volumes/456')
resp = req.get_response(self.app)
@@ -215,7 +214,7 @@ class VolumeApiTest(test.TestCase):
self.assertEqual(resp.status_int, 202)
def test_volume_delete_no_volume(self):
- self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get_notfound)
+ self.stubs.Set(cinder.API, "get", fakes.stub_volume_get_notfound)
req = webob.Request.blank('/v2/fake/os-volumes/456')
req.method = 'DELETE'
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index e07db3519..466fd3636 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -194,7 +194,6 @@ class ExtensionControllerTest(ExtensionTestCase):
"UserData",
"VirtualInterfaces",
"Volumes",
- "VolumeTypes",
]
self.ext_list.sort()
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index 58dc2df45..4f39e569e 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -30,7 +30,6 @@ from nova.api.openstack import compute
from nova.api.openstack.compute import limits
from nova.api.openstack.compute import versions
from nova.api.openstack import urlmap
-from nova.api.openstack import volume
from nova.api.openstack import wsgi as os_wsgi
from nova.compute import api as compute_api
from nova.compute import instance_types
diff --git a/nova/tests/api/openstack/volume/__init__.py b/nova/tests/api/openstack/volume/__init__.py
deleted file mode 100644
index 7e04e7c73..000000000
--- a/nova/tests/api/openstack/volume/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
-from nova.tests import *
diff --git a/nova/tests/api/openstack/volume/contrib/__init__.py b/nova/tests/api/openstack/volume/contrib/__init__.py
deleted file mode 100644
index 7e04e7c73..000000000
--- a/nova/tests/api/openstack/volume/contrib/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
-from nova.tests import *
diff --git a/nova/tests/api/openstack/volume/contrib/test_admin_actions.py b/nova/tests/api/openstack/volume/contrib/test_admin_actions.py
deleted file mode 100644
index 4ade54779..000000000
--- a/nova/tests/api/openstack/volume/contrib/test_admin_actions.py
+++ /dev/null
@@ -1,184 +0,0 @@
-import webob
-
-from nova import context
-from nova import db
-from nova import exception
-from nova.openstack.common import jsonutils
-from nova import test
-from nova.tests.api.openstack import fakes
-
-
-def app():
- # no auth, just let environ['nova.context'] pass through
- api = fakes.volume.APIRouter(init_only=('volumes', 'snapshots'))
- mapper = fakes.urlmap.URLMap()
- mapper['/v1'] = api
- return mapper
-
-
-class AdminActionsTest(test.TestCase):
-
- def test_reset_status_as_admin(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # current status is available
- volume = db.volume_create(ctx, {'status': 'available'})
- req = webob.Request.blank('/v1/fake/volumes/%s/action' % volume['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # request status of 'error'
- req.body = jsonutils.dumps({'os-reset_status': {'status': 'error'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # request is accepted
- self.assertEquals(resp.status_int, 202)
- volume = db.volume_get(ctx, volume['id'])
- # status changed to 'error'
- self.assertEquals(volume['status'], 'error')
-
- def test_reset_status_as_non_admin(self):
- # current status is 'error'
- volume = db.volume_create(context.get_admin_context(),
- {'status': 'error'})
- req = webob.Request.blank('/v1/fake/volumes/%s/action' % volume['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # request changing status to available
- req.body = jsonutils.dumps({'os-reset_status': {'status':
- 'available'}})
- # non-admin context
- req.environ['nova.context'] = context.RequestContext('fake', 'fake')
- resp = req.get_response(app())
- # request is not authorized
- self.assertEquals(resp.status_int, 403)
- volume = db.volume_get(context.get_admin_context(), volume['id'])
- # status is still 'error'
- self.assertEquals(volume['status'], 'error')
-
- def test_malformed_reset_status_body(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # current status is available
- volume = db.volume_create(ctx, {'status': 'available'})
- req = webob.Request.blank('/v1/fake/volumes/%s/action' % volume['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # malformed request body
- req.body = jsonutils.dumps({'os-reset_status': {'x-status': 'bad'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # bad request
- self.assertEquals(resp.status_int, 400)
- volume = db.volume_get(ctx, volume['id'])
- # status is still 'available'
- self.assertEquals(volume['status'], 'available')
-
- def test_invalid_status_for_volume(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # current status is available
- volume = db.volume_create(ctx, {'status': 'available'})
- req = webob.Request.blank('/v1/fake/volumes/%s/action' % volume['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # 'invalid' is not a valid status
- req.body = jsonutils.dumps({'os-reset_status': {'status': 'invalid'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # bad request
- self.assertEquals(resp.status_int, 400)
- volume = db.volume_get(ctx, volume['id'])
- # status is still 'available'
- self.assertEquals(volume['status'], 'available')
-
- def test_reset_status_for_missing_volume(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # missing-volume-id
- req = webob.Request.blank('/v1/fake/volumes/%s/action' %
- 'missing-volume-id')
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # malformed request body
- req.body = jsonutils.dumps({'os-reset_status': {'status':
- 'available'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # not found
- self.assertEquals(resp.status_int, 404)
- self.assertRaises(exception.NotFound, db.volume_get, ctx,
- 'missing-volume-id')
-
- def test_snapshot_reset_status(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # snapshot in 'error_deleting'
- volume = db.volume_create(ctx, {})
- snapshot = db.snapshot_create(ctx, {'status': 'error_deleting',
- 'volume_id': volume['id']})
- req = webob.Request.blank('/v1/fake/snapshots/%s/action' %
- snapshot['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # request status of 'error'
- req.body = jsonutils.dumps({'os-reset_status': {'status': 'error'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # request is accepted
- self.assertEquals(resp.status_int, 202)
- snapshot = db.snapshot_get(ctx, snapshot['id'])
- # status changed to 'error'
- self.assertEquals(snapshot['status'], 'error')
-
- def test_invalid_status_for_snapshot(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # snapshot in 'available'
- volume = db.volume_create(ctx, {})
- snapshot = db.snapshot_create(ctx, {'status': 'available',
- 'volume_id': volume['id']})
- req = webob.Request.blank('/v1/fake/snapshots/%s/action' %
- snapshot['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- # 'attaching' is not a valid status for snapshots
- req.body = jsonutils.dumps({'os-reset_status': {'status':
- 'attaching'}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # request is accepted
- print resp
- self.assertEquals(resp.status_int, 400)
- snapshot = db.snapshot_get(ctx, snapshot['id'])
- # status is still 'available'
- self.assertEquals(snapshot['status'], 'available')
-
- def test_force_delete(self):
- # admin context
- ctx = context.RequestContext('admin', 'fake', is_admin=True)
- ctx.elevated() # add roles
- # current status is creating
- volume = db.volume_create(ctx, {'status': 'creating'})
- req = webob.Request.blank('/v1/fake/volumes/%s/action' % volume['id'])
- req.method = 'POST'
- req.headers['content-type'] = 'application/json'
- req.body = jsonutils.dumps({'os-force_delete': {}})
- # attach admin context to request
- req.environ['nova.context'] = ctx
- resp = req.get_response(app())
- # request is accepted
- self.assertEquals(resp.status_int, 202)
- # volume is deleted
- self.assertRaises(exception.NotFound, db.volume_get, ctx, volume['id'])
diff --git a/nova/tests/api/openstack/volume/contrib/test_types_extra_specs.py b/nova/tests/api/openstack/volume/contrib/test_types_extra_specs.py
deleted file mode 100644
index edc127b8a..000000000
--- a/nova/tests/api/openstack/volume/contrib/test_types_extra_specs.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Zadara Storage Inc.
-# Copyright (c) 2011 OpenStack LLC.
-# Copyright 2011 University of Southern California
-# 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 lxml import etree
-import webob
-
-from nova.api.openstack.volume.contrib import types_extra_specs
-from nova import test
-from nova.tests.api.openstack import fakes
-import nova.wsgi
-
-
-def return_create_volume_type_extra_specs(context, volume_type_id,
- extra_specs):
- return stub_volume_type_extra_specs()
-
-
-def return_volume_type_extra_specs(context, volume_type_id):
- return stub_volume_type_extra_specs()
-
-
-def return_empty_volume_type_extra_specs(context, volume_type_id):
- return {}
-
-
-def delete_volume_type_extra_specs(context, volume_type_id, key):
- pass
-
-
-def stub_volume_type_extra_specs():
- specs = {
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- "key4": "value4",
- "key5": "value5"}
- return specs
-
-
-def volume_type_get(context, volume_type_id):
- pass
-
-
-class VolumeTypesExtraSpecsTest(test.TestCase):
-
- def setUp(self):
- super(VolumeTypesExtraSpecsTest, self).setUp()
- self.stubs.Set(nova.db, 'volume_type_get', volume_type_get)
- self.api_path = '/v1/fake/os-volume-types/1/extra_specs'
- self.controller = types_extra_specs.VolumeTypeExtraSpecsController()
-
- def test_index(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.index(req, 1)
-
- self.assertEqual('value1', res_dict['extra_specs']['key1'])
-
- def test_index_no_data(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_empty_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.index(req, 1)
-
- self.assertEqual(0, len(res_dict['extra_specs']))
-
- def test_show(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key5')
- res_dict = self.controller.show(req, 1, 'key5')
-
- self.assertEqual('value5', res_dict['key5'])
-
- def test_show_spec_not_found(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_get',
- return_empty_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key6')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
- req, 1, 'key6')
-
- def test_delete(self):
- self.stubs.Set(nova.db, 'volume_type_extra_specs_delete',
- delete_volume_type_extra_specs)
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key5')
- self.controller.delete(req, 1, 'key5')
-
- def test_create(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"extra_specs": {"key1": "value1"}}
-
- req = fakes.HTTPRequest.blank(self.api_path)
- res_dict = self.controller.create(req, 1, body)
-
- self.assertEqual('value1', res_dict['extra_specs']['key1'])
-
- def test_update_item(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key1')
- res_dict = self.controller.update(req, 1, 'key1', body)
-
- self.assertEqual('value1', res_dict['key1'])
-
- def test_update_item_too_many_keys(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1", "key2": "value2"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/key1')
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
- req, 1, 'key1', body)
-
- def test_update_item_body_uri_mismatch(self):
- self.stubs.Set(nova.db,
- 'volume_type_extra_specs_update_or_create',
- return_create_volume_type_extra_specs)
- body = {"key1": "value1"}
-
- req = fakes.HTTPRequest.blank(self.api_path + '/bad')
- self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
- req, 1, 'bad', body)
-
-
-class VolumeTypeExtraSpecsSerializerTest(test.TestCase):
- def test_index_create_serializer(self):
- serializer = types_extra_specs.VolumeTypeExtraSpecsTemplate()
-
- # Just getting some input data
- extra_specs = stub_volume_type_extra_specs()
- text = serializer.serialize(dict(extra_specs=extra_specs))
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('extra_specs', tree.tag)
- self.assertEqual(len(extra_specs), len(tree))
- seen = set(extra_specs.keys())
- for child in tree:
- self.assertTrue(child.tag in seen)
- self.assertEqual(extra_specs[child.tag], child.text)
- seen.remove(child.tag)
- self.assertEqual(len(seen), 0)
-
- def test_update_show_serializer(self):
- serializer = types_extra_specs.VolumeTypeExtraSpecTemplate()
-
- exemplar = dict(key1='value1')
- text = serializer.serialize(exemplar)
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('key1', tree.tag)
- self.assertEqual('value1', tree.text)
- self.assertEqual(0, len(tree))
-
-
-class VolumeTypeExtraSpecsUnprocessableEntityTestCase(test.TestCase):
-
- """
- Tests of places we throw 422 Unprocessable Entity from
- """
-
- def setUp(self):
- super(VolumeTypeExtraSpecsUnprocessableEntityTestCase, self).setUp()
- self.controller = types_extra_specs.VolumeTypeExtraSpecsController()
-
- def _unprocessable_extra_specs_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/types/1/extra_specs')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.create, req, '1', body)
-
- def test_create_no_body(self):
- self._unprocessable_extra_specs_create(body=None)
-
- def test_create_missing_volume(self):
- body = {'foo': {'a': 'b'}}
- self._unprocessable_extra_specs_create(body=body)
-
- def test_create_malformed_entity(self):
- body = {'extra_specs': 'string'}
- self._unprocessable_extra_specs_create(body=body)
-
- def _unprocessable_extra_specs_update(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/types/1/extra_specs')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.update, req, '1', body)
-
- def test_update_no_body(self):
- self._unprocessable_extra_specs_update(body=None)
-
- def test_update_empty_body(self):
- self._unprocessable_extra_specs_update(body={})
diff --git a/nova/tests/api/openstack/volume/contrib/test_types_manage.py b/nova/tests/api/openstack/volume/contrib/test_types_manage.py
deleted file mode 100644
index f69038144..000000000
--- a/nova/tests/api/openstack/volume/contrib/test_types_manage.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-import webob
-
-from nova.api.openstack.volume.contrib import types_manage
-from nova import exception
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova.volume import volume_types
-
-
-def stub_volume_type(id):
- specs = {
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- "key4": "value4",
- "key5": "value5"}
- return dict(id=id, name='vol_type_%s' % str(id), extra_specs=specs)
-
-
-def return_volume_types_get_volume_type(context, id):
- if id == "777":
- raise exception.VolumeTypeNotFound(volume_type_id=id)
- return stub_volume_type(int(id))
-
-
-def return_volume_types_destroy(context, name):
- if name == "777":
- raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
- pass
-
-
-def return_volume_types_create(context, name, specs):
- pass
-
-
-def return_volume_types_get_by_name(context, name):
- if name == "777":
- raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
- return stub_volume_type(int(name.split("_")[2]))
-
-
-class VolumeTypesManageApiTest(test.TestCase):
- def setUp(self):
- super(VolumeTypesManageApiTest, self).setUp()
- self.controller = types_manage.VolumeTypesManageController()
-
- def test_volume_types_delete(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
- self.stubs.Set(volume_types, 'destroy',
- return_volume_types_destroy)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types/1')
- self.controller._delete(req, 1)
-
- def test_volume_types_delete_not_found(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
- self.stubs.Set(volume_types, 'destroy',
- return_volume_types_destroy)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types/777')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller._delete,
- req, '777')
-
- def test_create(self):
- self.stubs.Set(volume_types, 'create',
- return_volume_types_create)
- self.stubs.Set(volume_types, 'get_volume_type_by_name',
- return_volume_types_get_by_name)
-
- body = {"volume_type": {"name": "vol_type_1",
- "extra_specs": {"key1": "value1"}}}
- req = fakes.HTTPRequest.blank('/v1/fake/types')
- res_dict = self.controller._create(req, body)
-
- self.assertEqual(1, len(res_dict))
- self.assertEqual('vol_type_1', res_dict['volume_type']['name'])
-
-
-class VolumeTypesUnprocessableEntityTestCase(test.TestCase):
-
- """
- Tests of places we throw 422 Unprocessable Entity from
- """
-
- def setUp(self):
- super(VolumeTypesUnprocessableEntityTestCase, self).setUp()
- self.controller = types_manage.VolumeTypesManageController()
-
- def _unprocessable_volume_type_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/types')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller._create, req, body)
-
- def test_create_no_body(self):
- self._unprocessable_volume_type_create(body=None)
-
- def test_create_missing_volume(self):
- body = {'foo': {'a': 'b'}}
- self._unprocessable_volume_type_create(body=body)
-
- def test_create_malformed_entity(self):
- body = {'volume_type': 'string'}
- self._unprocessable_volume_type_create(body=body)
diff --git a/nova/tests/api/openstack/volume/contrib/test_volume_actions.py b/nova/tests/api/openstack/volume/contrib/test_volume_actions.py
deleted file mode 100644
index 4dd79d366..000000000
--- a/nova/tests/api/openstack/volume/contrib/test_volume_actions.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2012 OpenStack LLC.
-#
-# 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
-import webob
-
-from nova.api.openstack.volume.contrib import volume_actions
-from nova import exception
-from nova.openstack.common.rpc import common as rpc_common
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova.volume import api as volume_api
-
-
-def stub_volume_get(self, context, volume_id):
- volume = fakes.stub_volume(volume_id)
- if volume_id == 5:
- volume['status'] = 'in-use'
- else:
- volume['status'] = 'available'
- return volume
-
-
-def stub_upload_volume_to_image_service(self, context, volume, metadata,
- force):
- ret = {"id": volume['id'],
- "updated_at": datetime.datetime(1, 1, 1, 1, 1, 1),
- "status": 'uploading',
- "display_description": volume['display_description'],
- "size": volume['size'],
- "volume_type": volume['volume_type'],
- "image_id": 1,
- "container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name'}
- return ret
-
-
-class VolumeImageActionsTest(test.TestCase):
- def setUp(self):
- super(VolumeImageActionsTest, self).setUp()
- self.controller = volume_actions.VolumeActionsController()
-
- self.stubs.Set(volume_api.API, 'get', stub_volume_get)
-
- def test_copy_volume_to_image(self):
- self.stubs.Set(volume_api.API,
- "copy_volume_to_image",
- stub_upload_volume_to_image_service)
-
- id = 1
- vol = {"container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name',
- "force": True}
- body = {"os-volume_upload_image": vol}
- req = fakes.HTTPRequest.blank('/v1/tenant1/volumes/%s/action' % id)
- res_dict = self.controller._volume_upload_image(req, id, body)
- expected = {'os-volume_upload_image': {'id': id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'status': 'uploading',
- 'display_description': 'displaydesc',
- 'size': 1,
- 'volume_type': {'name': 'vol_type_name'},
- 'image_id': 1,
- 'container_format': 'bare',
- 'disk_format': 'raw',
- 'image_name': 'image_name'}}
- self.assertDictMatch(res_dict, expected)
-
- def test_copy_volume_to_image_volumenotfound(self):
- def stub_volume_get_raise_exc(self, context, volume_id):
- raise exception.VolumeNotFound(volume_id=volume_id)
-
- self.stubs.Set(volume_api.API, 'get', stub_volume_get_raise_exc)
-
- id = 1
- vol = {"container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name',
- "force": True}
- body = {"os-volume_upload_image": vol}
- req = fakes.HTTPRequest.blank('/v1/tenant1/volumes/%s/action' % id)
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller._volume_upload_image,
- req,
- id,
- body)
-
- def test_copy_volume_to_image_invalidvolume(self):
- def stub_upload_volume_to_image_service_raise(self, context, volume,
- metadata, force):
- raise exception.InvalidVolume
- self.stubs.Set(volume_api.API,
- "copy_volume_to_image",
- stub_upload_volume_to_image_service_raise)
-
- id = 1
- vol = {"container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name',
- "force": True}
- body = {"os-volume_upload_image": vol}
- req = fakes.HTTPRequest.blank('/v1/tenant1/volumes/%s/action' % id)
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller._volume_upload_image,
- req,
- id,
- body)
-
- def test_copy_volume_to_image_valueerror(self):
- def stub_upload_volume_to_image_service_raise(self, context, volume,
- metadata, force):
- raise ValueError
- self.stubs.Set(volume_api.API,
- "copy_volume_to_image",
- stub_upload_volume_to_image_service_raise)
-
- id = 1
- vol = {"container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name',
- "force": True}
- body = {"os-volume_upload_image": vol}
- req = fakes.HTTPRequest.blank('/v1/tenant1/volumes/%s/action' % id)
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller._volume_upload_image,
- req,
- id,
- body)
-
- def test_copy_volume_to_image_remoteerror(self):
- def stub_upload_volume_to_image_service_raise(self, context, volume,
- metadata, force):
- raise rpc_common.RemoteError
- self.stubs.Set(volume_api.API,
- "copy_volume_to_image",
- stub_upload_volume_to_image_service_raise)
-
- id = 1
- vol = {"container_format": 'bare',
- "disk_format": 'raw',
- "image_name": 'image_name',
- "force": True}
- body = {"os-volume_upload_image": vol}
- req = fakes.HTTPRequest.blank('/v1/tenant1/volumes/%s/action' % id)
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller._volume_upload_image,
- req,
- id,
- body)
diff --git a/nova/tests/api/openstack/volume/extensions/__init__.py b/nova/tests/api/openstack/volume/extensions/__init__.py
deleted file mode 100644
index 848908a95..000000000
--- a/nova/tests/api/openstack/volume/extensions/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC
-#
-# 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.
diff --git a/nova/tests/api/openstack/volume/extensions/foxinsocks.py b/nova/tests/api/openstack/volume/extensions/foxinsocks.py
deleted file mode 100644
index cf901472c..000000000
--- a/nova/tests/api/openstack/volume/extensions/foxinsocks.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-import webob.exc
-
-from nova.api.openstack import extensions
-from nova.api.openstack import wsgi
-
-
-class FoxInSocksController(object):
-
- def index(self, req):
- return "Try to say this Mr. Knox, sir..."
-
-
-class FoxInSocksServerControllerExtension(wsgi.Controller):
- @wsgi.action('add_tweedle')
- def _add_tweedle(self, req, id, body):
-
- return "Tweedle Beetle Added."
-
- @wsgi.action('delete_tweedle')
- def _delete_tweedle(self, req, id, body):
-
- return "Tweedle Beetle Deleted."
-
- @wsgi.action('fail')
- def _fail(self, req, id, body):
-
- raise webob.exc.HTTPBadRequest(explanation='Tweedle fail')
-
-
-class FoxInSocksFlavorGooseControllerExtension(wsgi.Controller):
- @wsgi.extends
- def show(self, req, resp_obj, id):
- #NOTE: This only handles JSON responses.
- # You can use content type header to test for XML.
- resp_obj.obj['flavor']['googoose'] = req.GET.get('chewing')
-
-
-class FoxInSocksFlavorBandsControllerExtension(wsgi.Controller):
- @wsgi.extends
- def show(self, req, resp_obj, id):
- #NOTE: This only handles JSON responses.
- # You can use content type header to test for XML.
- resp_obj.obj['big_bands'] = 'Pig Bands!'
-
-
-class Foxinsocks(extensions.ExtensionDescriptor):
- """The Fox In Socks Extension"""
-
- name = "Fox In Socks"
- alias = "FOXNSOX"
- namespace = "http://www.fox.in.socks/api/ext/pie/v1.0"
- updated = "2011-01-22T13:25:27-06:00"
-
- def __init__(self, ext_mgr):
- ext_mgr.register(self)
-
- def get_resources(self):
- resources = []
- resource = extensions.ResourceExtension('foxnsocks',
- FoxInSocksController())
- resources.append(resource)
- return resources
-
- def get_controller_extensions(self):
- extension_list = []
-
- extension_set = [
- (FoxInSocksServerControllerExtension, 'servers'),
- (FoxInSocksFlavorGooseControllerExtension, 'flavors'),
- (FoxInSocksFlavorBandsControllerExtension, 'flavors'),
- ]
- for klass, collection in extension_set:
- controller = klass()
- ext = extensions.ControllerExtension(self, collection, controller)
- extension_list.append(ext)
-
- return extension_list
diff --git a/nova/tests/api/openstack/volume/test_extensions.py b/nova/tests/api/openstack/volume/test_extensions.py
deleted file mode 100644
index e291e74dd..000000000
--- a/nova/tests/api/openstack/volume/test_extensions.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-import iso8601
-from lxml import etree
-import webob
-
-from nova.api.openstack import volume
-from nova.api.openstack import xmlutil
-from nova import flags
-from nova.openstack.common import jsonutils
-from nova import test
-
-FLAGS = flags.FLAGS
-NS = "{http://docs.openstack.org/common/api/v1.0}"
-
-
-class ExtensionTestCase(test.TestCase):
- def setUp(self):
- super(ExtensionTestCase, self).setUp()
- ext_list = FLAGS.osapi_volume_extension[:]
- fox = ('nova.tests.api.openstack.volume.extensions.'
- 'foxinsocks.Foxinsocks')
- if fox not in ext_list:
- ext_list.append(fox)
- self.flags(osapi_volume_extension=ext_list)
-
-
-class ExtensionControllerTest(ExtensionTestCase):
-
- def setUp(self):
- super(ExtensionControllerTest, self).setUp()
- self.ext_list = [
- "TypesManage",
- "TypesExtraSpecs",
- ]
- self.ext_list.sort()
-
- def test_list_extensions_json(self):
- app = volume.APIRouter()
- request = webob.Request.blank("/fake/extensions")
- response = request.get_response(app)
- self.assertEqual(200, response.status_int)
-
- # Make sure we have all the extensions, extra extensions being OK.
- data = jsonutils.loads(response.body)
- names = [str(x['name']) for x in data['extensions']
- if str(x['name']) in self.ext_list]
- names.sort()
- self.assertEqual(names, self.ext_list)
-
- # Ensure all the timestamps are valid according to iso8601
- for ext in data['extensions']:
- iso8601.parse_date(ext['updated'])
-
- # Make sure that at least Fox in Sox is correct.
- (fox_ext, ) = [
- x for x in data['extensions'] if x['alias'] == 'FOXNSOX']
- self.assertEqual(fox_ext, {
- 'namespace': 'http://www.fox.in.socks/api/ext/pie/v1.0',
- 'name': 'Fox In Socks',
- 'updated': '2011-01-22T13:25:27-06:00',
- 'description': 'The Fox In Socks Extension',
- 'alias': 'FOXNSOX',
- 'links': []
- },
- )
-
- for ext in data['extensions']:
- url = '/fake/extensions/%s' % ext['alias']
- request = webob.Request.blank(url)
- response = request.get_response(app)
- output = jsonutils.loads(response.body)
- self.assertEqual(output['extension']['alias'], ext['alias'])
-
- def test_get_extension_json(self):
- app = volume.APIRouter()
- request = webob.Request.blank("/fake/extensions/FOXNSOX")
- response = request.get_response(app)
- self.assertEqual(200, response.status_int)
-
- data = jsonutils.loads(response.body)
- self.assertEqual(data['extension'], {
- "namespace": "http://www.fox.in.socks/api/ext/pie/v1.0",
- "name": "Fox In Socks",
- "updated": "2011-01-22T13:25:27-06:00",
- "description": "The Fox In Socks Extension",
- "alias": "FOXNSOX",
- "links": []})
-
- def test_get_non_existing_extension_json(self):
- app = volume.APIRouter()
- request = webob.Request.blank("/fake/extensions/4")
- response = request.get_response(app)
- self.assertEqual(404, response.status_int)
-
- def test_list_extensions_xml(self):
- app = volume.APIRouter()
- request = webob.Request.blank("/fake/extensions")
- request.accept = "application/xml"
- response = request.get_response(app)
- self.assertEqual(200, response.status_int)
-
- root = etree.XML(response.body)
- self.assertEqual(root.tag.split('extensions')[0], NS)
-
- # Make sure we have all the extensions, extras extensions being OK.
- exts = root.findall('{0}extension'.format(NS))
- self.assert_(len(exts) >= len(self.ext_list))
-
- # Make sure that at least Fox in Sox is correct.
- (fox_ext, ) = [x for x in exts if x.get('alias') == 'FOXNSOX']
- self.assertEqual(fox_ext.get('name'), 'Fox In Socks')
- self.assertEqual(fox_ext.get('namespace'),
- 'http://www.fox.in.socks/api/ext/pie/v1.0')
- self.assertEqual(fox_ext.get('updated'), '2011-01-22T13:25:27-06:00')
- self.assertEqual(fox_ext.findtext('{0}description'.format(NS)),
- 'The Fox In Socks Extension')
-
- xmlutil.validate_schema(root, 'extensions')
-
- def test_get_extension_xml(self):
- app = volume.APIRouter()
- request = webob.Request.blank("/fake/extensions/FOXNSOX")
- request.accept = "application/xml"
- response = request.get_response(app)
- self.assertEqual(200, response.status_int)
- xml = response.body
-
- root = etree.XML(xml)
- self.assertEqual(root.tag.split('extension')[0], NS)
- self.assertEqual(root.get('alias'), 'FOXNSOX')
- self.assertEqual(root.get('name'), 'Fox In Socks')
- self.assertEqual(root.get('namespace'),
- 'http://www.fox.in.socks/api/ext/pie/v1.0')
- self.assertEqual(root.get('updated'), '2011-01-22T13:25:27-06:00')
- self.assertEqual(root.findtext('{0}description'.format(NS)),
- 'The Fox In Socks Extension')
-
- xmlutil.validate_schema(root, 'extension')
diff --git a/nova/tests/api/openstack/volume/test_router.py b/nova/tests/api/openstack/volume/test_router.py
deleted file mode 100644
index 5934a21e5..000000000
--- a/nova/tests/api/openstack/volume/test_router.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright 2011 Denali Systems, Inc.
-# 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.api.openstack import volume
-from nova.api.openstack.volume import snapshots
-from nova.api.openstack.volume import versions
-from nova.api.openstack.volume import volumes
-from nova.api.openstack import wsgi
-from nova import flags
-from nova.openstack.common import log as logging
-from nova import test
-from nova.tests.api.openstack import fakes
-
-FLAGS = flags.FLAGS
-
-LOG = logging.getLogger(__name__)
-
-
-class FakeController(object):
- def __init__(self, ext_mgr=None):
- self.ext_mgr = ext_mgr
-
- def index(self, req):
- return {}
-
- def detail(self, req):
- return {}
-
-
-def create_resource(ext_mgr):
- return wsgi.Resource(FakeController(ext_mgr))
-
-
-def create_volume_resource(ext_mgr):
- return wsgi.Resource(FakeController(ext_mgr))
-
-
-class VolumeRouterTestCase(test.TestCase):
- def setUp(self):
- super(VolumeRouterTestCase, self).setUp()
- # NOTE(vish): versions is just returning text so, no need to stub.
- self.stubs.Set(snapshots, 'create_resource', create_resource)
- self.stubs.Set(volumes, 'create_resource', create_volume_resource)
- self.app = volume.APIRouter()
-
- def test_versions(self):
- req = fakes.HTTPRequest.blank('')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(302, response.status_int)
- req = fakes.HTTPRequest.blank('/')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
-
- def test_versions_dispatch(self):
- req = fakes.HTTPRequest.blank('/')
- req.method = 'GET'
- req.content_type = 'application/json'
- resource = versions.Versions()
- result = resource.dispatch(resource.index, req, {})
- self.assertTrue(result)
-
- def test_volumes(self):
- req = fakes.HTTPRequest.blank('/fake/volumes')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
-
- def test_volumes_detail(self):
- req = fakes.HTTPRequest.blank('/fake/volumes/detail')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
-
- def test_types(self):
- req = fakes.HTTPRequest.blank('/fake/types')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
-
- def test_snapshots(self):
- req = fakes.HTTPRequest.blank('/fake/snapshots')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
-
- def test_snapshots_detail(self):
- req = fakes.HTTPRequest.blank('/fake/snapshots/detail')
- req.method = 'GET'
- req.content_type = 'application/json'
- response = req.get_response(self.app)
- self.assertEqual(200, response.status_int)
diff --git a/nova/tests/api/openstack/volume/test_snapshots.py b/nova/tests/api/openstack/volume/test_snapshots.py
deleted file mode 100644
index c6e703f83..000000000
--- a/nova/tests/api/openstack/volume/test_snapshots.py
+++ /dev/null
@@ -1,299 +0,0 @@
-# Copyright 2011 Denali Systems, Inc.
-# 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 lxml import etree
-import webob
-
-from nova.api.openstack.volume import snapshots
-from nova import db
-from nova import exception
-from nova import flags
-from nova.openstack.common import log as logging
-from nova.openstack.common import timeutils
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova import volume
-
-FLAGS = flags.FLAGS
-
-LOG = logging.getLogger(__name__)
-
-
-def _get_default_snapshot_param():
- return {
- 'id': 123,
- 'volume_id': 12,
- 'status': 'available',
- 'volume_size': 100,
- 'created_at': None,
- 'display_name': 'Default name',
- 'display_description': 'Default description',
- }
-
-
-def stub_snapshot_create(self, context, volume_id, name, description):
- snapshot = _get_default_snapshot_param()
- snapshot['volume_id'] = volume_id
- snapshot['display_name'] = name
- snapshot['display_description'] = description
- return snapshot
-
-
-def stub_snapshot_delete(self, context, snapshot):
- if snapshot['id'] != 123:
- raise exception.NotFound
-
-
-def stub_snapshot_get(self, context, snapshot_id):
- if snapshot_id != 123:
- raise exception.NotFound
-
- param = _get_default_snapshot_param()
- return param
-
-
-def stub_snapshot_get_all(self, context, search_opts=None):
- param = _get_default_snapshot_param()
- return [param]
-
-
-class SnapshotApiTest(test.TestCase):
- def setUp(self):
- super(SnapshotApiTest, self).setUp()
- self.controller = snapshots.SnapshotsController()
-
- self.stubs.Set(db, 'snapshot_get_all_by_project',
- fakes.stub_snapshot_get_all_by_project)
- self.stubs.Set(db, 'snapshot_get_all',
- fakes.stub_snapshot_get_all)
-
- def test_snapshot_create(self):
- self.stubs.Set(volume.api.API, "create_snapshot", stub_snapshot_create)
- self.stubs.Set(volume.api.API, 'get', fakes.stub_volume_get)
- snapshot = {"volume_id": '12',
- "force": False,
- "display_name": "Snapshot Test Name",
- "display_description": "Snapshot Test Desc"}
- body = dict(snapshot=snapshot)
- req = fakes.HTTPRequest.blank('/v1/snapshots')
- resp_dict = self.controller.create(req, body)
-
- self.assertTrue('snapshot' in resp_dict)
- self.assertEqual(resp_dict['snapshot']['display_name'],
- snapshot['display_name'])
- self.assertEqual(resp_dict['snapshot']['display_description'],
- snapshot['display_description'])
-
- def test_snapshot_create_force(self):
- self.stubs.Set(volume.api.API, "create_snapshot_force",
- stub_snapshot_create)
- self.stubs.Set(volume.api.API, 'get', fakes.stub_volume_get)
- snapshot = {"volume_id": '12',
- "force": True,
- "display_name": "Snapshot Test Name",
- "display_description": "Snapshot Test Desc"}
- body = dict(snapshot=snapshot)
- req = fakes.HTTPRequest.blank('/v1/snapshots')
- resp_dict = self.controller.create(req, body)
-
- self.assertTrue('snapshot' in resp_dict)
- self.assertEqual(resp_dict['snapshot']['display_name'],
- snapshot['display_name'])
- self.assertEqual(resp_dict['snapshot']['display_description'],
- snapshot['display_description'])
-
- # Test invalid force paramter
- snapshot = {"volume_id": 12,
- "force": '**&&^^%%$$##@@'}
- body = dict(snapshot=snapshot)
- req = fakes.HTTPRequest.blank('/v1/snapshots')
- self.assertRaises(exception.InvalidParameterValue,
- self.controller.create,
- req,
- body)
-
- def test_snapshot_create_nonexistent_volume_id(self):
- self.stubs.Set(volume.api.API, 'get', fakes.stub_volume_get_notfound)
-
- snapshot = {"volume_id": 13,
- "force": False,
- "display_name": "Snapshot Test Name",
- "display_description": "Snapshot Test Desc"}
- body = dict(snapshot=snapshot)
- req = fakes.HTTPRequest.blank('/v1/snapshots')
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.create,
- req,
- body)
-
- def test_snapshot_delete(self):
- self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
- self.stubs.Set(volume.api.API, "delete_snapshot", stub_snapshot_delete)
-
- snapshot_id = 123
- req = fakes.HTTPRequest.blank('/v1/snapshots/%d' % snapshot_id)
- resp = self.controller.delete(req, snapshot_id)
- self.assertEqual(resp.status_int, 202)
-
- def test_snapshot_delete_invalid_id(self):
- self.stubs.Set(volume.api.API, "delete_snapshot", stub_snapshot_delete)
- snapshot_id = 234
- req = fakes.HTTPRequest.blank('/v1/snapshots/%d' % snapshot_id)
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.delete,
- req,
- snapshot_id)
-
- def test_snapshot_show(self):
- self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
- req = fakes.HTTPRequest.blank('/v1/snapshots/123')
- resp_dict = self.controller.show(req, 123)
-
- self.assertTrue('snapshot' in resp_dict)
- self.assertEqual(resp_dict['snapshot']['id'], '123')
-
- def test_snapshot_show_invalid_id(self):
- snapshot_id = 234
- req = fakes.HTTPRequest.blank('/v1/snapshots/%d' % snapshot_id)
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.show,
- req,
- snapshot_id)
-
- def test_snapshot_detail(self):
- self.stubs.Set(volume.api.API, "get_all_snapshots",
- stub_snapshot_get_all)
- req = fakes.HTTPRequest.blank('/v1/snapshots/detail')
- resp_dict = self.controller.detail(req)
-
- self.assertTrue('snapshots' in resp_dict)
- resp_snapshots = resp_dict['snapshots']
- self.assertEqual(len(resp_snapshots), 1)
-
- resp_snapshot = resp_snapshots.pop()
- self.assertEqual(resp_snapshot['id'], '123')
-
- def test_admin_list_snapshots_limited_to_project(self):
- req = fakes.HTTPRequest.blank('/v1/fake/snapshots',
- use_admin_context=True)
- res = self.controller.index(req)
-
- self.assertTrue('snapshots' in res)
- self.assertEqual(1, len(res['snapshots']))
-
- def test_admin_list_snapshots_all_tenants(self):
- req = fakes.HTTPRequest.blank('/v1/fake/snapshots?all_tenants=1',
- use_admin_context=True)
- res = self.controller.index(req)
- self.assertTrue('snapshots' in res)
- self.assertEqual(3, len(res['snapshots']))
-
- def test_all_tenants_non_admin_gets_all_tenants(self):
- req = fakes.HTTPRequest.blank('/v1/fake/snapshots?all_tenants=1')
- res = self.controller.index(req)
- self.assertTrue('snapshots' in res)
- self.assertEqual(1, len(res['snapshots']))
-
- def test_non_admin_get_by_project(self):
- req = fakes.HTTPRequest.blank('/v1/fake/snapshots')
- res = self.controller.index(req)
- self.assertTrue('snapshots' in res)
- self.assertEqual(1, len(res['snapshots']))
-
-
-class SnapshotSerializerTest(test.TestCase):
- def _verify_snapshot(self, snap, tree):
- self.assertEqual(tree.tag, 'snapshot')
-
- for attr in ('id', 'status', 'size', 'created_at',
- 'display_name', 'display_description', 'volume_id'):
- self.assertEqual(str(snap[attr]), tree.get(attr))
-
- def test_snapshot_show_create_serializer(self):
- serializer = snapshots.SnapshotTemplate()
- raw_snapshot = dict(
- id='snap_id',
- status='snap_status',
- size=1024,
- created_at=timeutils.utcnow(),
- display_name='snap_name',
- display_description='snap_desc',
- volume_id='vol_id',
- )
- text = serializer.serialize(dict(snapshot=raw_snapshot))
-
- print text
- tree = etree.fromstring(text)
-
- self._verify_snapshot(raw_snapshot, tree)
-
- def test_snapshot_index_detail_serializer(self):
- serializer = snapshots.SnapshotsTemplate()
- raw_snapshots = [dict(
- id='snap1_id',
- status='snap1_status',
- size=1024,
- created_at=timeutils.utcnow(),
- display_name='snap1_name',
- display_description='snap1_desc',
- volume_id='vol1_id',
- ),
- dict(
- id='snap2_id',
- status='snap2_status',
- size=1024,
- created_at=timeutils.utcnow(),
- display_name='snap2_name',
- display_description='snap2_desc',
- volume_id='vol2_id',
- )]
- text = serializer.serialize(dict(snapshots=raw_snapshots))
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('snapshots', tree.tag)
- self.assertEqual(len(raw_snapshots), len(tree))
- for idx, child in enumerate(tree):
- self._verify_snapshot(raw_snapshots[idx], child)
-
-
-class SnapshotsUnprocessableEntityTestCase(test.TestCase):
-
- """
- Tests of places we throw 422 Unprocessable Entity from
- """
-
- def setUp(self):
- super(SnapshotsUnprocessableEntityTestCase, self).setUp()
- self.controller = snapshots.SnapshotsController()
-
- def _unprocessable_snapshot_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/snapshots')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.create, req, body)
-
- def test_create_no_body(self):
- self._unprocessable_snapshot_create(body=None)
-
- def test_create_missing_snapshot(self):
- body = {'foo': {'a': 'b'}}
- self._unprocessable_snapshot_create(body=body)
-
- def test_create_malformed_entity(self):
- body = {'snapshot': 'string'}
- self._unprocessable_snapshot_create(body=body)
diff --git a/nova/tests/api/openstack/volume/test_types.py b/nova/tests/api/openstack/volume/test_types.py
deleted file mode 100644
index e7aa4cc0a..000000000
--- a/nova/tests/api/openstack/volume/test_types.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2011 OpenStack LLC.
-# 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 lxml import etree
-import webob
-
-from nova.api.openstack.volume import types
-from nova.api.openstack.volume.views import types as views_types
-from nova import exception
-from nova.openstack.common import timeutils
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova.volume import volume_types
-
-
-def stub_volume_type(id):
- specs = {
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- "key4": "value4",
- "key5": "value5"}
- return dict(id=id, name='vol_type_%s' % str(id), extra_specs=specs)
-
-
-def return_volume_types_get_all_types(context):
- return dict(vol_type_1=stub_volume_type(1),
- vol_type_2=stub_volume_type(2),
- vol_type_3=stub_volume_type(3))
-
-
-def return_empty_volume_types_get_all_types(context):
- return {}
-
-
-def return_volume_types_get_volume_type(context, id):
- if id == "777":
- raise exception.VolumeTypeNotFound(volume_type_id=id)
- return stub_volume_type(int(id))
-
-
-def return_volume_types_get_by_name(context, name):
- if name == "777":
- raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
- return stub_volume_type(int(name.split("_")[2]))
-
-
-class VolumeTypesApiTest(test.TestCase):
- def setUp(self):
- super(VolumeTypesApiTest, self).setUp()
- self.controller = types.VolumeTypesController()
-
- def test_volume_types_index(self):
- self.stubs.Set(volume_types, 'get_all_types',
- return_volume_types_get_all_types)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types')
- res_dict = self.controller.index(req)
-
- self.assertEqual(3, len(res_dict['volume_types']))
-
- expected_names = ['vol_type_1', 'vol_type_2', 'vol_type_3']
- actual_names = map(lambda e: e['name'], res_dict['volume_types'])
- self.assertEqual(set(actual_names), set(expected_names))
- for entry in res_dict['volume_types']:
- self.assertEqual('value1', entry['extra_specs']['key1'])
-
- def test_volume_types_index_no_data(self):
- self.stubs.Set(volume_types, 'get_all_types',
- return_empty_volume_types_get_all_types)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types')
- res_dict = self.controller.index(req)
-
- self.assertEqual(0, len(res_dict['volume_types']))
-
- def test_volume_types_show(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types/1')
- res_dict = self.controller.show(req, 1)
-
- self.assertEqual(1, len(res_dict))
- self.assertEqual('1', res_dict['volume_type']['id'])
- self.assertEqual('vol_type_1', res_dict['volume_type']['name'])
-
- def test_volume_types_show_not_found(self):
- self.stubs.Set(volume_types, 'get_volume_type',
- return_volume_types_get_volume_type)
-
- req = fakes.HTTPRequest.blank('/v1/fake/types/777')
- self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
- req, '777')
-
- def test_view_builder_show(self):
- view_builder = views_types.ViewBuilder()
-
- now = timeutils.isotime()
- raw_volume_type = dict(name='new_type',
- deleted=False,
- created_at=now,
- updated_at=now,
- extra_specs={},
- deleted_at=None,
- id=42)
-
- request = fakes.HTTPRequest.blank("/v1")
- output = view_builder.show(request, raw_volume_type)
-
- self.assertTrue('volume_type' in output)
- expected_volume_type = dict(name='new_type',
- extra_specs={},
- id=42)
- self.assertDictMatch(output['volume_type'], expected_volume_type)
-
- def test_view_builder_list(self):
- view_builder = views_types.ViewBuilder()
-
- now = timeutils.isotime()
- raw_volume_types = []
- for i in range(0, 10):
- raw_volume_types.append(dict(name='new_type',
- deleted=False,
- created_at=now,
- updated_at=now,
- extra_specs={},
- deleted_at=None,
- id=42 + i))
-
- request = fakes.HTTPRequest.blank("/v1")
- output = view_builder.index(request, raw_volume_types)
-
- self.assertTrue('volume_types' in output)
- for i in range(0, 10):
- expected_volume_type = dict(name='new_type',
- extra_specs={},
- id=42 + i)
- self.assertDictMatch(output['volume_types'][i],
- expected_volume_type)
-
-
-class VolumeTypesSerializerTest(test.TestCase):
- def _verify_volume_type(self, vtype, tree):
- self.assertEqual('volume_type', tree.tag)
- self.assertEqual(vtype['name'], tree.get('name'))
- self.assertEqual(str(vtype['id']), tree.get('id'))
- self.assertEqual(1, len(tree))
- extra_specs = tree[0]
- self.assertEqual('extra_specs', extra_specs.tag)
- seen = set(vtype['extra_specs'].keys())
- for child in extra_specs:
- self.assertTrue(child.tag in seen)
- self.assertEqual(vtype['extra_specs'][child.tag], child.text)
- seen.remove(child.tag)
- self.assertEqual(len(seen), 0)
-
- def test_index_serializer(self):
- serializer = types.VolumeTypesTemplate()
-
- # Just getting some input data
- vtypes = return_volume_types_get_all_types(None)
- text = serializer.serialize({'volume_types': vtypes.values()})
-
- tree = etree.fromstring(text)
-
- self.assertEqual('volume_types', tree.tag)
- self.assertEqual(len(vtypes), len(tree))
- for child in tree:
- name = child.get('name')
- self.assertTrue(name in vtypes)
- self._verify_volume_type(vtypes[name], child)
-
- def test_voltype_serializer(self):
- serializer = types.VolumeTypeTemplate()
-
- vtype = stub_volume_type(1)
- text = serializer.serialize(dict(volume_type=vtype))
-
- tree = etree.fromstring(text)
-
- self._verify_volume_type(vtype, tree)
diff --git a/nova/tests/api/openstack/volume/test_volumes.py b/nova/tests/api/openstack/volume/test_volumes.py
deleted file mode 100644
index e7a0e66f3..000000000
--- a/nova/tests/api/openstack/volume/test_volumes.py
+++ /dev/null
@@ -1,602 +0,0 @@
-# Copyright 2013 Josh Durgin
-# 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.
-
-import datetime
-
-from lxml import etree
-import webob
-
-from nova.api.openstack.volume import extensions
-from nova.api.openstack.volume import volumes
-from nova import db
-from nova import exception
-from nova import flags
-from nova.openstack.common import timeutils
-from nova import test
-from nova.tests.api.openstack import fakes
-from nova.tests.image import fake as fake_image
-from nova.volume import api as volume_api
-
-
-FLAGS = flags.FLAGS
-
-TEST_SNAPSHOT_UUID = '00000000-0000-0000-0000-000000000001'
-
-
-def stub_snapshot_get(self, context, snapshot_id):
- if snapshot_id != TEST_SNAPSHOT_UUID:
- raise exception.NotFound
-
- return {
- 'id': snapshot_id,
- 'volume_id': 12,
- 'status': 'available',
- 'volume_size': 100,
- 'created_at': None,
- 'display_name': 'Default name',
- 'display_description': 'Default description',
- }
-
-
-class VolumeApiTest(test.TestCase):
- def setUp(self):
- super(VolumeApiTest, self).setUp()
- self.ext_mgr = extensions.ExtensionManager()
- self.ext_mgr.extensions = {}
- self.controller = volumes.VolumeController(self.ext_mgr)
-
- self.stubs.Set(db, 'volume_get_all', fakes.stub_volume_get_all)
- self.stubs.Set(db, 'volume_get_all_by_project',
- fakes.stub_volume_get_all_by_project)
- self.stubs.Set(volume_api.API, 'get', fakes.stub_volume_get)
- self.stubs.Set(volume_api.API, 'delete', fakes.stub_volume_delete)
-
- def test_volume_create(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
-
- vol = {"size": 100,
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "zone1:host1"}
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- res = self.controller.create(req, body)
- expected = {'volume': {'status': 'fakestatus',
- 'display_description': 'Volume Test Desc',
- 'availability_zone': 'zone1:host1',
- 'display_name': 'Volume Test Name',
- 'attachments': [{'device': '/',
- 'server_id': 'fakeuuid',
- 'id': '1',
- 'volume_id': '1'}],
- 'volume_type': 'vol_type_name',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': 100}}
- self.assertEqual(res.obj, expected)
- self.assertEqual(res.code, 200)
- self.assertTrue('location' in res.headers)
-
- def test_volume_creation_fails_with_bad_size(self):
- vol = {"size": '',
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "zone1:host1"}
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- self.assertRaises(exception.InvalidInput,
- self.controller.create,
- req,
- body)
-
- def test_volume_create_no_body(self):
- body = {}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.create,
- req,
- body)
-
- def test_volume_create_with_image_id(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
- self.ext_mgr.extensions = {'os-image-create': 'fake'}
- vol = {"size": '1',
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "nova",
- "imageRef": 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'}
- expected = {'volume': {'status': 'fakestatus',
- 'display_description': 'Volume Test Desc',
- 'availability_zone': 'nova',
- 'display_name': 'Volume Test Name',
- 'attachments': [{'device': '/',
- 'server_id': 'fakeuuid',
- 'id': '1',
- 'volume_id': '1'}],
- 'volume_type': 'vol_type_name',
- 'image_id': 'c905cedb-7281-47e4-8a62-f26bc5fc4c77',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': '1'}
- }
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- res = self.controller.create(req, body)
- self.maxDiff = 4096
- self.assertEqual(res.obj, expected)
-
- def test_volume_create_with_image_id_and_snapshot_id(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
- self.stubs.Set(volume_api.API, "get_snapshot", stub_snapshot_get)
- self.ext_mgr.extensions = {'os-image-create': 'fake'}
- vol = {"size": '1',
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "nova",
- "imageRef": 'c905cedb-7281-47e4-8a62-f26bc5fc4c77',
- "snapshot_id": TEST_SNAPSHOT_UUID}
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller.create,
- req,
- body)
-
- def test_volume_create_with_image_id_is_integer(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
- self.ext_mgr.extensions = {'os-image-create': 'fake'}
- vol = {"size": '1',
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "nova",
- "imageRef": 1234}
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller.create,
- req,
- body)
-
- def test_volume_create_with_image_id_not_uuid_format(self):
- self.stubs.Set(volume_api.API, "create", fakes.stub_volume_create)
- self.ext_mgr.extensions = {'os-image-create': 'fake'}
- vol = {"size": '1',
- "display_name": "Volume Test Name",
- "display_description": "Volume Test Desc",
- "availability_zone": "nova",
- "imageRef": '12345'}
- body = {"volume": vol}
- req = fakes.HTTPRequest.blank('/v1/volumes')
- self.assertRaises(webob.exc.HTTPBadRequest,
- self.controller.create,
- req,
- body)
-
- def test_volume_list(self):
- self.stubs.Set(volume_api.API, 'get_all',
- fakes.stub_volume_get_all_by_project)
-
- req = fakes.HTTPRequest.blank('/v1/volumes')
- res_dict = self.controller.index(req)
- expected = {'volumes': [{'status': 'fakestatus',
- 'display_description': 'displaydesc',
- 'availability_zone': 'fakeaz',
- 'display_name': 'displayname',
- 'attachments': [{'device': '/',
- 'server_id': 'fakeuuid',
- 'id': '1',
- 'volume_id': '1'}],
- 'volume_type': 'vol_type_name',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': 1}]}
- self.maxDiff = None
- self.assertEqual(res_dict, expected)
-
- def test_volume_list_detail(self):
- self.stubs.Set(volume_api.API, 'get_all',
- fakes.stub_volume_get_all_by_project)
-
- req = fakes.HTTPRequest.blank('/v1/volumes/detail')
- res_dict = self.controller.index(req)
- expected = {'volumes': [{'status': 'fakestatus',
- 'display_description': 'displaydesc',
- 'availability_zone': 'fakeaz',
- 'display_name': 'displayname',
- 'attachments': [{'device': '/',
- 'server_id': 'fakeuuid',
- 'id': '1',
- 'volume_id': '1'}],
- 'volume_type': 'vol_type_name',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': 1}]}
- self.assertEqual(res_dict, expected)
-
- def test_volume_show(self):
- req = fakes.HTTPRequest.blank('/v1/volumes/1')
- res_dict = self.controller.show(req, '1')
- expected = {'volume': {'status': 'fakestatus',
- 'display_description': 'displaydesc',
- 'availability_zone': 'fakeaz',
- 'display_name': 'displayname',
- 'attachments': [{'device': '/',
- 'server_id': 'fakeuuid',
- 'id': '1',
- 'volume_id': '1'}],
- 'volume_type': 'vol_type_name',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': 1}}
- self.assertEqual(res_dict, expected)
-
- def test_volume_show_no_attachments(self):
- def stub_volume_get(self, context, volume_id):
- return fakes.stub_volume(volume_id, attach_status='detached')
-
- self.stubs.Set(volume_api.API, 'get', stub_volume_get)
-
- req = fakes.HTTPRequest.blank('/v1/volumes/1')
- res_dict = self.controller.show(req, '1')
- expected = {'volume': {'status': 'fakestatus',
- 'display_description': 'displaydesc',
- 'availability_zone': 'fakeaz',
- 'display_name': 'displayname',
- 'attachments': [],
- 'volume_type': 'vol_type_name',
- 'snapshot_id': None,
- 'metadata': {},
- 'id': '1',
- 'created_at': datetime.datetime(1999, 1, 1,
- 1, 1, 1),
- 'size': 1}}
- self.assertEqual(res_dict, expected)
-
- def test_volume_show_no_volume(self):
- self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get_notfound)
-
- req = fakes.HTTPRequest.blank('/v1/volumes/1')
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.show,
- req,
- 1)
-
- def test_volume_delete(self):
- req = fakes.HTTPRequest.blank('/v1/volumes/1')
- resp = self.controller.delete(req, 1)
- self.assertEqual(resp.status_int, 202)
-
- def test_volume_delete_no_volume(self):
- self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get_notfound)
-
- req = fakes.HTTPRequest.blank('/v1/volumes/1')
- self.assertRaises(webob.exc.HTTPNotFound,
- self.controller.delete,
- req,
- 1)
-
- def test_admin_list_volumes_limited_to_project(self):
- req = fakes.HTTPRequest.blank('/v1/fake/volumes',
- use_admin_context=True)
- res = self.controller.index(req)
-
- self.assertTrue('volumes' in res)
- self.assertEqual(1, len(res['volumes']))
-
- def test_admin_list_volumes_all_tenants(self):
- req = fakes.HTTPRequest.blank('/v1/fake/volumes?all_tenants=1',
- use_admin_context=True)
- res = self.controller.index(req)
- self.assertTrue('volumes' in res)
- self.assertEqual(3, len(res['volumes']))
-
- def test_all_tenants_non_admin_gets_all_tenants(self):
- req = fakes.HTTPRequest.blank('/v1/fake/volumes?all_tenants=1')
- res = self.controller.index(req)
- self.assertTrue('volumes' in res)
- self.assertEqual(1, len(res['volumes']))
-
- def test_non_admin_get_by_project(self):
- req = fakes.HTTPRequest.blank('/v1/fake/volumes')
- res = self.controller.index(req)
- self.assertTrue('volumes' in res)
- self.assertEqual(1, len(res['volumes']))
-
-
-class VolumeSerializerTest(test.TestCase):
- def _verify_volume_attachment(self, attach, tree):
- for attr in ('id', 'volume_id', 'server_id', 'device'):
- self.assertEqual(str(attach[attr]), tree.get(attr))
-
- def _verify_volume(self, vol, tree):
- self.assertEqual(tree.tag, 'volume')
-
- for attr in ('id', 'status', 'size', 'availability_zone', 'created_at',
- 'display_name', 'display_description', 'volume_type',
- 'snapshot_id'):
- self.assertEqual(str(vol[attr]), tree.get(attr))
-
- for child in tree:
- self.assertTrue(child.tag in ('attachments', 'metadata'))
- if child.tag == 'attachments':
- self.assertEqual(1, len(child))
- self.assertEqual('attachment', child[0].tag)
- self._verify_volume_attachment(vol['attachments'][0], child[0])
- elif child.tag == 'metadata':
- not_seen = set(vol['metadata'].keys())
- for gr_child in child:
- self.assertTrue(gr_child.get("key") in not_seen)
- self.assertEqual(str(vol['metadata'][gr_child.get("key")]),
- gr_child.text)
- not_seen.remove(gr_child.get("key"))
- self.assertEqual(0, len(not_seen))
-
- def test_volume_show_create_serializer(self):
- serializer = volumes.VolumeTemplate()
- raw_volume = dict(
- id='vol_id',
- status='vol_status',
- size=1024,
- availability_zone='vol_availability',
- created_at=timeutils.utcnow(),
- attachments=[dict(
- id='vol_id',
- volume_id='vol_id',
- server_id='instance_uuid',
- device='/foo')],
- display_name='vol_name',
- display_description='vol_desc',
- volume_type='vol_type',
- snapshot_id='snap_id',
- metadata=dict(
- foo='bar',
- baz='quux',
- ),
- )
- text = serializer.serialize(dict(volume=raw_volume))
-
- print text
- tree = etree.fromstring(text)
-
- self._verify_volume(raw_volume, tree)
-
- def test_volume_index_detail_serializer(self):
- serializer = volumes.VolumesTemplate()
- raw_volumes = [dict(
- id='vol1_id',
- status='vol1_status',
- size=1024,
- availability_zone='vol1_availability',
- created_at=timeutils.utcnow(),
- attachments=[dict(
- id='vol1_id',
- volume_id='vol1_id',
- server_id='instance_uuid',
- device='/foo1')],
- display_name='vol1_name',
- display_description='vol1_desc',
- volume_type='vol1_type',
- snapshot_id='snap1_id',
- metadata=dict(
- foo='vol1_foo',
- bar='vol1_bar',
- ),
- ),
- dict(
- id='vol2_id',
- status='vol2_status',
- size=1024,
- availability_zone='vol2_availability',
- created_at=timeutils.utcnow(),
- attachments=[dict(
- id='vol2_id',
- volume_id='vol2_id',
- server_id='instance_uuid',
- device='/foo2')],
- display_name='vol2_name',
- display_description='vol2_desc',
- volume_type='vol2_type',
- snapshot_id='snap2_id',
- metadata=dict(
- foo='vol2_foo',
- bar='vol2_bar',
- ),
- )]
- text = serializer.serialize(dict(volumes=raw_volumes))
-
- print text
- tree = etree.fromstring(text)
-
- self.assertEqual('volumes', tree.tag)
- self.assertEqual(len(raw_volumes), len(tree))
- for idx, child in enumerate(tree):
- self._verify_volume(raw_volumes[idx], child)
-
-
-class TestVolumeCreateRequestXMLDeserializer(test.TestCase):
-
- def setUp(self):
- super(TestVolumeCreateRequestXMLDeserializer, self).setUp()
- self.deserializer = volumes.CreateDeserializer()
-
- def test_minimal_volume(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "size": "1",
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_display_name(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"
- display_name="Volume-xml"></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "size": "1",
- "display_name": "Volume-xml",
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_display_description(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"
- display_name="Volume-xml"
- display_description="description"></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "size": "1",
- "display_name": "Volume-xml",
- "display_description": "description",
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_volume_type(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"
- display_name="Volume-xml"
- display_description="description"
- volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "display_name": "Volume-xml",
- "size": "1",
- "display_name": "Volume-xml",
- "display_description": "description",
- "volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_availability_zone(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"
- display_name="Volume-xml"
- display_description="description"
- volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"
- availability_zone="us-east1"></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "size": "1",
- "display_name": "Volume-xml",
- "display_description": "description",
- "volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
- "availability_zone": "us-east1",
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_metadata(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- display_name="Volume-xml"
- size="1">
- <metadata><meta key="Type">work</meta></metadata></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "display_name": "Volume-xml",
- "size": "1",
- "metadata": {
- "Type": "work",
- },
- },
- }
- self.assertEquals(request['body'], expected)
-
- def test_full_volume(self):
- self_request = """
-<volume xmlns="http://docs.openstack.org/compute/api/v1.1"
- size="1"
- display_name="Volume-xml"
- display_description="description"
- volume_type="289da7f8-6440-407c-9fb4-7db01ec49164"
- availability_zone="us-east1">
- <metadata><meta key="Type">work</meta></metadata></volume>"""
- request = self.deserializer.deserialize(self_request)
- expected = {
- "volume": {
- "size": "1",
- "display_name": "Volume-xml",
- "display_description": "description",
- "volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
- "availability_zone": "us-east1",
- "metadata": {
- "Type": "work",
- },
- },
- }
- self.maxDiff = None
- self.assertEquals(request['body'], expected)
-
-
-class VolumesUnprocessableEntityTestCase(test.TestCase):
-
- """
- Tests of places we throw 422 Unprocessable Entity from
- """
-
- def setUp(self):
- super(VolumesUnprocessableEntityTestCase, self).setUp()
- self.ext_mgr = extensions.ExtensionManager()
- self.ext_mgr.extensions = {}
- self.controller = volumes.VolumeController(self.ext_mgr)
-
- def _unprocessable_volume_create(self, body):
- req = fakes.HTTPRequest.blank('/v2/fake/volumes')
- req.method = 'POST'
-
- self.assertRaises(webob.exc.HTTPUnprocessableEntity,
- self.controller.create, req, body)
-
- def test_create_no_body(self):
- self._unprocessable_volume_create(body=None)
-
- def test_create_missing_volume(self):
- body = {'foo': {'a': 'b'}}
- self._unprocessable_volume_create(body=body)
-
- def test_create_malformed_entity(self):
- body = {'volume': 'string'}
- self._unprocessable_volume_create(body=body)
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 6a419feea..5d938622b 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -61,7 +61,7 @@ from nova.tests import fake_network
from nova.tests import fake_network_cache_model
from nova.tests.image import fake as fake_image
from nova import utils
-import nova.volume
+from nova.volume import cinder
QUOTAS = quota.QUOTAS
@@ -657,9 +657,9 @@ class ComputeTestCase(BaseTestCase):
def fake_volume_get(self, context, volume_id):
return {'id': volume_id}
- self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
- self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
- self.stubs.Set(nova.volume.api.API, 'reserve_volume',
+ self.stubs.Set(cinder.API, 'get', fake_volume_get)
+ self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
+ self.stubs.Set(cinder.API, 'reserve_volume',
fake_reserve_volume)
self.compute_api.attach_volume(self.context, instance, 1,
@@ -2222,11 +2222,16 @@ class ComputeTestCase(BaseTestCase):
topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
# creating volume testdata
- volume_id = db.volume_create(c, {'size': 1})['id']
+ volume_id = 'fake'
values = {'instance_uuid': inst_uuid, 'device_name': '/dev/vdc',
'delete_on_termination': False, 'volume_id': volume_id}
db.block_device_mapping_create(c, values)
+ def fake_volume_get(self, context, volume_id):
+ return {'id': volume_id}
+
+ self.stubs.Set(cinder.API, 'get', fake_volume_get)
+
# creating mocks
self.mox.StubOutWithMock(rpc, 'call')
@@ -2272,7 +2277,6 @@ class ComputeTestCase(BaseTestCase):
for bdms in db.block_device_mapping_get_all_by_instance(
c, inst_uuid):
db.block_device_mapping_destroy(c, bdms['id'])
- db.volume_destroy(c, volume_id)
db.instance_destroy(c, inst_uuid)
def test_live_migration_works_correctly(self):
@@ -2321,7 +2325,6 @@ class ComputeTestCase(BaseTestCase):
db.instance_update(c, inst_uuid,
{'task_state': task_states.MIGRATING,
'power_state': power_state.PAUSED})
- v_ref = db.volume_create(c, {'size': 1, 'instance_id': inst_id})
fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
'instance_uuid': inst_ref['uuid']})
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
@@ -2356,7 +2359,6 @@ class ComputeTestCase(BaseTestCase):
# cleanup
db.instance_destroy(c, inst_uuid)
- db.volume_destroy(c, v_ref['id'])
db.floating_ip_destroy(c, flo_addr)
def test_run_kill_vm(self):
@@ -3406,8 +3408,7 @@ class ComputeAPITestCase(BaseTestCase):
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
- volume_id = db.volume_create(context.get_admin_context(),
- {'size': 1})['id']
+ volume_id = 'fake'
volume = {'instance_uuid': instance['uuid'],
'device_name': '/dev/vdc',
'delete_on_termination': False,
@@ -3432,8 +3433,7 @@ class ComputeAPITestCase(BaseTestCase):
instance = jsonutils.to_primitive(self._create_fake_instance())
self.compute.run_instance(self.context, instance=instance)
- volume_id = db.volume_create(context.get_admin_context(),
- {'size': 1})['id']
+ volume_id = 'fake'
volume = {'instance_uuid': instance['uuid'],
'device_name': '/dev/vdc',
'delete_on_termination': False,
@@ -4616,9 +4616,9 @@ class ComputeAPITestCase(BaseTestCase):
def fake_rpc_attach_volume(self, context, **kwargs):
called['fake_rpc_attach_volume'] = True
- self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
- self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
- self.stubs.Set(nova.volume.api.API, 'reserve_volume',
+ self.stubs.Set(cinder.API, 'get', fake_volume_get)
+ self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
+ self.stubs.Set(cinder.API, 'reserve_volume',
fake_reserve_volume)
self.stubs.Set(compute_rpcapi.ComputeAPI, 'attach_volume',
fake_rpc_attach_volume)
@@ -4647,9 +4647,9 @@ class ComputeAPITestCase(BaseTestCase):
def fake_rpc_attach_volume(self, context, **kwargs):
called['fake_rpc_attach_volume'] = True
- self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
- self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
- self.stubs.Set(nova.volume.api.API, 'reserve_volume',
+ self.stubs.Set(cinder.API, 'get', fake_volume_get)
+ self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
+ self.stubs.Set(cinder.API, 'reserve_volume',
fake_reserve_volume)
self.stubs.Set(compute_rpcapi.ComputeAPI, 'attach_volume',
fake_rpc_attach_volume)
@@ -4659,37 +4659,35 @@ class ComputeAPITestCase(BaseTestCase):
admin = context.get_admin_context()
instance = self._create_fake_instance()
- # Create a volume and attach it to our instance
- volume_id = db.volume_create(admin, {'size': 1})['id']
+ volume_id = 'fake'
values = {'instance_uuid': instance['uuid'],
'device_name': '/dev/vdc',
'delete_on_termination': False,
'volume_id': volume_id,
}
db.block_device_mapping_create(admin, values)
- db.volume_attached(admin, volume_id, instance["uuid"],
- "/dev/vdc")
+
+ def fake_volume_get(self, context, volume):
+ return {'id': volume_id}
+ self.stubs.Set(cinder.API, "get", fake_volume_get)
# Stub out and record whether it gets detached
result = {"detached": False}
def fake_detach(self, context, volume):
result["detached"] = volume["id"] == volume_id
- self.stubs.Set(nova.volume.api.API, "detach", fake_detach)
+ self.stubs.Set(cinder.API, "detach", fake_detach)
+
+ def fake_terminate_connection(self, context, volume, connector):
+ return {}
+ self.stubs.Set(cinder.API, "terminate_connection",
+ fake_terminate_connection)
# Kill the instance and check that it was detached
self.compute.terminate_instance(admin, instance=instance)
self.assertTrue(result["detached"])
def test_inject_network_info(self):
- instance = self._create_fake_instance()
- self.compute_api.attach_volume(self.context, instance, 1, device=None)
- self.assertTrue(called.get('fake_check_attach'))
- self.assertTrue(called.get('fake_reserve_volume'))
- self.assertTrue(called.get('fake_reserve_volume'))
- self.assertTrue(called.get('fake_rpc_attach_volume'))
-
- def test_inject_network_info(self):
instance = self._create_fake_instance(params={'host': FLAGS.host})
self.compute.run_instance(self.context,
instance=jsonutils.to_primitive(instance))
diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py
index 32f34b3e7..0b50d45e2 100644
--- a/nova/tests/fake_flags.py
+++ b/nova/tests/fake_flags.py
@@ -26,7 +26,6 @@ flags.DECLARE('iscsi_num_targets', 'nova.volume.driver')
flags.DECLARE('network_size', 'nova.network.manager')
flags.DECLARE('num_networks', 'nova.network.manager')
flags.DECLARE('policy_file', 'nova.policy')
-flags.DECLARE('volume_driver', 'nova.volume.manager')
def set_defaults(conf):
@@ -44,7 +43,6 @@ def set_defaults(conf):
conf.set_default('sqlite_synchronous', False)
conf.set_default('use_ipv6', True)
conf.set_default('verbose', True)
- conf.set_default('volume_driver', 'nova.volume.driver.FakeISCSIDriver')
conf.set_default('api_paste_config', '$state_path/etc/nova/api-paste.ini')
conf.set_default('rpc_response_timeout', 5)
conf.set_default('rpc_cast_timeout', 5)
diff --git a/nova/tests/fake_volume.py b/nova/tests/fake_volume.py
index 37aaa83b4..54fd85fe5 100644
--- a/nova/tests/fake_volume.py
+++ b/nova/tests/fake_volume.py
@@ -27,21 +27,21 @@ class fake_volume():
instance_uuid = '4a3cd441-b9c2-11e1-afa6-0800200c9a66'
def __init__(self, size, name,
- description, id, snapshot,
+ description, volume_id, snapshot,
volume_type, metadata,
availability_zone):
snapshot_id = None
if snapshot is not None:
snapshot_id = snapshot['id']
- if id is None:
- id = str(utils.gen_uuid())
+ if volume_id is None:
+ volume_id = str(utils.gen_uuid())
self.vol = {
'created_at': timeutils.utcnow(),
'deleted_at': None,
'updated_at': timeutils.utcnow(),
'uuid': 'WTF',
'deleted': False,
- 'id': id,
+ 'id': volume_id,
'user_id': self.user_uuid,
'project_id': 'fake-project-id',
'snapshot_id': snapshot_id,
@@ -133,14 +133,17 @@ class API(object):
return v.vol
def create_with_kwargs(self, context, **kwargs):
+ volume_id = kwargs.get('volume_id', None)
+ print volume_id
v = fake_volume(kwargs['size'],
kwargs['name'],
kwargs['description'],
- str(kwargs.get('volume_id', None)),
+ str(volume_id),
None,
None,
None,
None)
+ print v.vol['id']
if kwargs.get('status', None) is not None:
v.vol['status'] = kwargs['status']
if kwargs['host'] is not None:
@@ -175,6 +178,7 @@ class API(object):
def check_attach(self, context, volume):
if volume['status'] != 'available':
msg = _("status must be available")
+ msg = "%s" % volume
raise exception.InvalidVolume(reason=msg)
if volume['attach_status'] == 'attached':
msg = _("already attached")
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
index f566a5020..9581a0e7e 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
@@ -329,14 +329,6 @@
"updated": "%(timestamp)s"
},
{
- "alias": "os-volume-types",
- "description": "%(text)s",
- "links": [],
- "name": "VolumeTypes",
- "namespace": "http://docs.openstack.org/compute/ext/volume_types/api/v1.1",
- "updated": "%(timestamp)s"
- },
- {
"alias": "os-volumes",
"description": "%(text)s",
"links": [],
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
index 20e650d7c..e8246aad8 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
@@ -123,9 +123,6 @@
<extension alias="os-virtual-interfaces" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1" name="VirtualInterfaces">
<description>%(text)s</description>
</extension>
- <extension alias="os-volume-types" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/volume_types/api/v1.1" name="VolumeTypes">
- <description>%(text)s</description>
- </extension>
<extension alias="os-volumes" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/volumes/api/v1.1" name="Volumes">
<description>%(text)s</description>
</extension>
diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py
index d81013920..f3bd944da 100644
--- a/nova/tests/integrated/integrated_helpers.py
+++ b/nova/tests/integrated/integrated_helpers.py
@@ -75,7 +75,6 @@ class _IntegratedTestBase(test.TestCase):
# set up services
self.compute = self.start_service('compute')
self.scheduler = self.start_service('cert')
- self.volume = self.start_service('volume')
self.network = self.start_service('network')
self.scheduler = self.start_service('scheduler')
@@ -101,13 +100,11 @@ class _IntegratedTestBase(test.TestCase):
# Ensure tests only listen on localhost
f['ec2_listen'] = '127.0.0.1'
f['osapi_compute_listen'] = '127.0.0.1'
- f['osapi_volume_listen'] = '127.0.0.1'
f['metadata_listen'] = '127.0.0.1'
# Auto-assign ports to allow concurrent tests
f['ec2_listen_port'] = 0
f['osapi_compute_listen_port'] = 0
- f['osapi_volume_listen_port'] = 0
f['metadata_listen_port'] = 0
f['fake_network'] = True
diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py
deleted file mode 100644
index fe70c3ce8..000000000
--- a/nova/tests/integrated/test_volumes.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 Justin Santa Barbara
-# 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.
-
-import time
-import unittest
-
-from nova.openstack.common.log import logging
-from nova import service
-from nova.tests.integrated.api import client
-from nova.tests.integrated import integrated_helpers
-from nova.volume import driver
-
-
-LOG = logging.getLogger(__name__)
-
-
-class VolumesTest(integrated_helpers._IntegratedTestBase):
- def setUp(self):
- super(VolumesTest, self).setUp()
- driver.LoggingVolumeDriver.clear_logs()
-
- def _start_api_service(self):
- self.osapi = service.WSGIService("osapi_volume")
- self.osapi.start()
- self.auth_url = 'http://%s:%s/v1' % (self.osapi.host, self.osapi.port)
- LOG.warn(self.auth_url)
-
- def _get_flags(self):
- f = super(VolumesTest, self)._get_flags()
- f['use_local_volumes'] = False # Avoids calling local_path
- f['volume_driver'] = 'nova.volume.driver.LoggingVolumeDriver'
- return f
-
- def test_get_volumes_summary(self):
- """Simple check that listing volumes works."""
- volumes = self.api.get_volumes(False)
- for volume in volumes:
- LOG.debug("volume: %s" % volume)
-
- def test_get_volumes(self):
- """Simple check that listing volumes works."""
- volumes = self.api.get_volumes()
- for volume in volumes:
- LOG.debug("volume: %s" % volume)
-
- def _poll_while(self, volume_id, continue_states, max_retries=5):
- """Poll (briefly) while the state is in continue_states."""
- retries = 0
- while True:
- try:
- found_volume = self.api.get_volume(volume_id)
- except client.OpenStackApiNotFoundException:
- found_volume = None
- LOG.debug("Got 404, proceeding")
- break
-
- LOG.debug("Found %s" % found_volume)
-
- self.assertEqual(volume_id, found_volume['id'])
-
- if not found_volume['status'] in continue_states:
- break
-
- time.sleep(1)
- retries = retries + 1
- if retries > max_retries:
- break
- return found_volume
-
- def test_create_and_delete_volume(self):
- """Creates and deletes a volume."""
-
- # Create volume
- created_volume = self.api.post_volume({'volume': {'size': 1}})
- LOG.debug("created_volume: %s" % created_volume)
- self.assertTrue(created_volume['id'])
- created_volume_id = created_volume['id']
-
- # Check it's there
- found_volume = self.api.get_volume(created_volume_id)
- self.assertEqual(created_volume_id, found_volume['id'])
-
- # It should also be in the all-volume list
- volumes = self.api.get_volumes()
- volume_names = [volume['id'] for volume in volumes]
- self.assertTrue(created_volume_id in volume_names)
-
- # Wait (briefly) for creation. Delay is due to the 'message queue'
- found_volume = self._poll_while(created_volume_id, ['creating'])
-
- # It should be available...
- self.assertEqual('available', found_volume['status'])
-
- # Delete the volume
- self.api.delete_volume(created_volume_id)
-
- # Wait (briefly) for deletion. Delay is due to the 'message queue'
- found_volume = self._poll_while(created_volume_id, ['deleting'])
-
- # Should be gone
- self.assertFalse(found_volume)
-
- LOG.debug("Logs: %s" % driver.LoggingVolumeDriver.all_logs())
-
- create_actions = driver.LoggingVolumeDriver.logs_like(
- 'create_volume',
- id=created_volume_id)
- LOG.debug("Create_Actions: %s" % create_actions)
-
- self.assertEquals(1, len(create_actions))
- create_action = create_actions[0]
- self.assertEquals(create_action['id'], created_volume_id)
- self.assertEquals(create_action['availability_zone'], 'nova')
- self.assertEquals(create_action['size'], 1)
-
- export_actions = driver.LoggingVolumeDriver.logs_like(
- 'create_export',
- id=created_volume_id)
- self.assertEquals(1, len(export_actions))
- export_action = export_actions[0]
- self.assertEquals(export_action['id'], created_volume_id)
- self.assertEquals(export_action['availability_zone'], 'nova')
-
- delete_actions = driver.LoggingVolumeDriver.logs_like(
- 'delete_volume',
- id=created_volume_id)
- self.assertEquals(1, len(delete_actions))
- delete_action = export_actions[0]
- self.assertEquals(delete_action['id'], created_volume_id)
-
- def test_create_volume_with_metadata(self):
- """Creates a volume with metadata."""
-
- # Create volume
- metadata = {'key1': 'value1',
- 'key2': 'value2'}
- created_volume = self.api.post_volume(
- {'volume': {'size': 1,
- 'metadata': metadata}})
- LOG.debug("created_volume: %s" % created_volume)
- self.assertTrue(created_volume['id'])
- created_volume_id = created_volume['id']
-
- # Check it's there and metadata present
- found_volume = self.api.get_volume(created_volume_id)
- self.assertEqual(created_volume_id, found_volume['id'])
- self.assertEqual(metadata, found_volume['metadata'])
-
- def test_create_volume_in_availability_zone(self):
- """Creates a volume in availability_zone."""
-
- # Create volume
- availability_zone = 'zone1:host1'
- created_volume = self.api.post_volume(
- {'volume': {'size': 1,
- 'availability_zone': availability_zone}})
- LOG.debug("created_volume: %s" % created_volume)
- self.assertTrue(created_volume['id'])
- created_volume_id = created_volume['id']
-
- # Check it's there and availability zone present
- found_volume = self.api.get_volume(created_volume_id)
- self.assertEqual(created_volume_id, found_volume['id'])
- self.assertEqual(availability_zone, found_volume['availability_zone'])
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index c6b2d7dd3..6a0e93b7d 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -175,18 +175,6 @@ class SchedulerManagerTestCase(test.TestCase):
self.manager.run_instance(self.context, request_spec,
None, None, None, None, {})
- def test_create_volume_no_valid_host_puts_volume_in_error(self):
- self._mox_schedule_method_helper('schedule_create_volume')
- self.mox.StubOutWithMock(db, 'volume_update')
-
- self.manager.driver.schedule_create_volume(self.context, '1', '2',
- None).AndRaise(exception.NoValidHost(reason=''))
- db.volume_update(self.context, '1', {'status': 'error'})
-
- self.mox.ReplayAll()
- self.assertRaises(exception.NoValidHost, self.manager.create_volume,
- self.context, '1', '2')
-
def test_prep_resize_no_valid_host_back_in_active_state(self):
fake_instance_uuid = 'fake-instance-id'
inst = {"vm_state": "", "task_state": ""}
@@ -305,13 +293,10 @@ class SchedulerTestCase(test.TestCase):
self.assertEqual(result, ['host2'])
def _live_migration_instance(self):
- volume1 = {'id': 31338}
- volume2 = {'id': 31339}
return {'id': 31337,
'uuid': 'fake_uuid',
'name': 'fake-instance',
'host': 'fake_host1',
- 'volumes': [volume1, volume2],
'power_state': power_state.RUNNING,
'memory_mb': 1024,
'root_gb': 1024,
@@ -656,48 +641,6 @@ class SchedulerDriverModuleTestCase(test.TestCase):
super(SchedulerDriverModuleTestCase, self).setUp()
self.context = context.RequestContext('fake_user', 'fake_project')
- def test_cast_to_volume_host_update_db_with_volume_id(self):
- host = 'fake_host1'
- method = 'fake_method'
- fake_kwargs = {'volume_id': 31337,
- 'extra_arg': 'meow'}
- queue = 'fake_queue'
-
- self.mox.StubOutWithMock(timeutils, 'utcnow')
- self.mox.StubOutWithMock(db, 'volume_update')
- self.mox.StubOutWithMock(rpc, 'queue_get_for')
- self.mox.StubOutWithMock(rpc, 'cast')
-
- timeutils.utcnow().AndReturn('fake-now')
- db.volume_update(self.context, 31337,
- {'host': host, 'scheduled_at': 'fake-now'})
- rpc.queue_get_for(self.context, 'volume', host).AndReturn(queue)
- rpc.cast(self.context, queue,
- {'method': method,
- 'args': fake_kwargs})
-
- self.mox.ReplayAll()
- driver.cast_to_volume_host(self.context, host, method,
- **fake_kwargs)
-
- def test_cast_to_volume_host_update_db_without_volume_id(self):
- host = 'fake_host1'
- method = 'fake_method'
- fake_kwargs = {'extra_arg': 'meow'}
- queue = 'fake_queue'
-
- self.mox.StubOutWithMock(rpc, 'queue_get_for')
- self.mox.StubOutWithMock(rpc, 'cast')
-
- rpc.queue_get_for(self.context, 'volume', host).AndReturn(queue)
- rpc.cast(self.context, queue,
- {'method': method,
- 'args': fake_kwargs})
-
- self.mox.ReplayAll()
- driver.cast_to_volume_host(self.context, host, method,
- **fake_kwargs)
-
def test_cast_to_compute_host_update_db_with_instance_uuid(self):
host = 'fake_host1'
method = 'fake_method'
@@ -753,19 +696,6 @@ class SchedulerDriverModuleTestCase(test.TestCase):
driver.cast_to_host(self.context, 'compute', host, method,
**fake_kwargs)
- def test_cast_to_host_volume_topic(self):
- host = 'fake_host1'
- method = 'fake_method'
- fake_kwargs = {'extra_arg': 'meow'}
-
- self.mox.StubOutWithMock(driver, 'cast_to_volume_host')
- driver.cast_to_volume_host(self.context, host, method,
- **fake_kwargs)
-
- self.mox.ReplayAll()
- driver.cast_to_host(self.context, 'volume', host, method,
- **fake_kwargs)
-
def test_cast_to_host_unknown_topic(self):
host = 'fake_host1'
method = 'fake_method'
diff --git a/nova/tests/test_cinder.py b/nova/tests/test_cinder.py
index 18532d642..3302aedb8 100644
--- a/nova/tests/test_cinder.py
+++ b/nova/tests/test_cinder.py
@@ -118,9 +118,6 @@ class CinderTestCase(test.TestCase):
self.fake_client_factory = FakeClientFactory()
self.stubs.Set(cinder.cinder_client, "Client",
self.fake_client_factory)
- self.flags(
- volume_api_class='nova.volume.cinder.API',
- )
self.api = cinder.API()
catalog = [{
"type": "volume",
diff --git a/nova/tests/test_iscsi.py b/nova/tests/test_iscsi.py
deleted file mode 100644
index 09a6e9e89..000000000
--- a/nova/tests/test_iscsi.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 Red Hat, Inc.
-#
-# 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 os.path
-import shutil
-import string
-import tempfile
-
-from nova import test
-from nova.volume import iscsi
-
-
-class TargetAdminTestCase(object):
-
- def setUp(self):
- self.cmds = []
-
- self.tid = 1
- self.target_name = 'iqn.2011-09.org.foo.bar:blaa'
- self.lun = 10
- self.path = '/foo'
- self.vol_id = 'blaa'
-
- self.script_template = None
- self.stubs.Set(os.path, 'isfile', lambda _: True)
- self.stubs.Set(os, 'unlink', lambda _: '')
- self.stubs.Set(iscsi.TgtAdm, '_get_target', self.fake_get_target)
-
- def fake_get_target(obj, iqn):
- return 1
-
- def get_script_params(self):
- return {'tid': self.tid,
- 'target_name': self.target_name,
- 'lun': self.lun,
- 'path': self.path}
-
- def get_script(self):
- return self.script_template % self.get_script_params()
-
- def fake_execute(self, *cmd, **kwargs):
- self.cmds.append(string.join(cmd))
- return "", None
-
- def clear_cmds(self):
- cmds = []
-
- def verify_cmds(self, cmds):
- self.assertEqual(len(cmds), len(self.cmds))
- for a, b in zip(cmds, self.cmds):
- self.assertEqual(a, b)
-
- def verify(self):
- script = self.get_script()
- cmds = []
- for line in script.split('\n'):
- if not line.strip():
- continue
- cmds.append(line)
- self.verify_cmds(cmds)
-
- def run_commands(self):
- tgtadm = iscsi.get_target_admin()
- tgtadm.set_execute(self.fake_execute)
- tgtadm.create_iscsi_target(self.target_name, self.tid,
- self.lun, self.path)
- tgtadm.show_target(self.tid, iqn=self.target_name)
- tgtadm.remove_iscsi_target(self.tid, self.lun, self.vol_id)
-
- def test_target_admin(self):
- self.clear_cmds()
- self.run_commands()
- self.verify()
-
-
-class TgtAdmTestCase(test.TestCase, TargetAdminTestCase):
-
- def setUp(self):
- super(TgtAdmTestCase, self).setUp()
- TargetAdminTestCase.setUp(self)
- self.persist_tempdir = tempfile.mkdtemp()
- self.flags(iscsi_helper='tgtadm')
- self.flags(volumes_dir=self.persist_tempdir)
- self.script_template = "\n".join([
- 'tgt-admin --update iqn.2011-09.org.foo.bar:blaa',
- 'tgt-admin --delete iqn.2010-10.org.openstack:volume-blaa'])
-
- def tearDown(self):
- try:
- shutil.rmtree(self.persist_tempdir)
- except OSError:
- pass
- super(TgtAdmTestCase, self).tearDown()
-
-
-class IetAdmTestCase(test.TestCase, TargetAdminTestCase):
-
- def setUp(self):
- super(IetAdmTestCase, self).setUp()
- TargetAdminTestCase.setUp(self)
- self.flags(iscsi_helper='ietadm')
- self.script_template = "\n".join([
- 'ietadm --op new --tid=%(tid)s --params Name=%(target_name)s',
- 'ietadm --op new --tid=%(tid)s --lun=%(lun)s '
- '--params Path=%(path)s,Type=fileio',
- 'ietadm --op show --tid=%(tid)s',
- 'ietadm --op delete --tid=%(tid)s --lun=%(lun)s',
- 'ietadm --op delete --tid=%(tid)s'])
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index c84440e58..f8bc3c339 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -155,7 +155,6 @@ class LibvirtVolumeTestCase(test.TestCase):
}
def test_libvirt_volume_driver_serial(self):
- vol_driver = volume_driver.VolumeDriver()
libvirt_driver = volume.LibvirtVolumeDriver(self.fake_conn)
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
diff --git a/nova/tests/test_netapp.py b/nova/tests/test_netapp.py
deleted file mode 100644
index 79a8526ee..000000000
--- a/nova/tests/test_netapp.py
+++ /dev/null
@@ -1,1380 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2012 NetApp, Inc.
-# 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.
-"""
-Tests for NetApp volume driver
-
-"""
-
-import BaseHTTPServer
-import httplib
-import StringIO
-
-from lxml import etree
-
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume import netapp
-
-
-LOG = logging.getLogger(__name__)
-
-
-WSDL_HEADER = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
- xmlns:na="http://www.netapp.com/management/v1"
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NetAppDfm"
- targetNamespace="http://www.netapp.com/management/v1">"""
-
-WSDL_TYPES = """<types>
-<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
- targetNamespace="http://www.netapp.com/management/v1">
-<xsd:element name="ApiProxy">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Request" type="na:Request"/>
- <xsd:element name="Target" type="xsd:string"/>
- <xsd:element minOccurs="0" name="Timeout" type="xsd:integer"/>
- <xsd:element minOccurs="0" name="Username" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="ApiProxyResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Response" type="na:Response"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditBegin">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="Force" type="xsd:boolean"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditBeginResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditCommit">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="AssumeConfirmation"
- type="xsd:boolean"/>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditCommitResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="IsProvisioningFailure"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="JobIds" type="na:ArrayOfJobInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditRollback">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditRollbackResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Datasets" type="na:ArrayOfDatasetInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetMembers"
- type="na:ArrayOfDatasetMemberInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="IncludeExportsInfo"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="IncludeIndirect"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="MemberType" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetProvisionMember">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- <xsd:element name="ProvisionMemberRequestInfo"
- type="na:ProvisionMemberRequestInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetProvisionMemberResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetRemoveMember">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetMemberParameters"
- type="na:ArrayOfDatasetMemberParameter"/>
- <xsd:element minOccurs="0" name="Destroy" type="xsd:boolean"/>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetRemoveMemberResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="ProgressEvents"
- type="na:ArrayOfDpJobProgressEventInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="JobId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DfmAbout">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="IncludeDirectorySizeInfo"
- type="xsd:boolean"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DfmAboutResult">
- <xsd:complexType>
- <xsd:all/>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="HostListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Hosts" type="na:ArrayOfHostInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="LunListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Luns" type="na:ArrayOfLunInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="StorageServiceDatasetProvision">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="AssumeConfirmation"
- type="xsd:boolean"/>
- <xsd:element name="DatasetName" type="na:ObjName"/>
- <xsd:element name="StorageServiceNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="StorageSetDetails"
- type="na:ArrayOfStorageSetInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="StorageServiceDatasetProvisionResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ConformanceAlerts"
- type="na:ArrayOfConformanceAlert"/>
- <xsd:element name="DatasetId" type="na:ObjId"/>
- <xsd:element minOccurs="0" name="DryRunResults"
- type="na:ArrayOfDryRunResult"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:complexType name="ArrayOfDatasetInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetInfo"
- type="na:DatasetInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDatasetMemberInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetMemberInfo"
- type="na:DatasetMemberInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDatasetMemberParameter">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetMemberParameter"
- type="na:DatasetMemberParameter"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDfmMetadataField">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DfmMetadataField"
- type="na:DfmMetadataField"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDpJobProgressEventInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DpJobProgressEventInfo"
- type="na:DpJobProgressEventInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfHostInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="HostInfo" type="na:HostInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfJobInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="JobInfo" type="na:JobInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfLunInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="LunInfo" type="na:LunInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfStorageSetInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="StorageSetInfo"
- type="na:StorageSetInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="DatasetExportInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="DatasetExportProtocol"
- type="na:DatasetExportProtocol"/>
- <xsd:element minOccurs="0" name="DatasetLunMappingInfo"
- type="na:DatasetLunMappingInfo"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="DatasetExportProtocol">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:complexType name="DatasetInfo">
- <xsd:all>
- <xsd:element name="DatasetId" type="na:ObjId"/>
- <xsd:element name="DatasetName" type="na:ObjName"/>
- <xsd:element name="DatasetMetadata" type="na:ArrayOfDfmMetadataField"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetLunMappingInfo">
- <xsd:all>
- <xsd:element name="IgroupOsType" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetMemberInfo">
- <xsd:all>
- <xsd:element name="MemberId" type="na:ObjId"/>
- <xsd:element name="MemberName" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetMemberParameter">
- <xsd:all>
- <xsd:element name="ObjectNameOrId" type="na:ObjNameOrId"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DfmMetadataField">
- <xsd:all>
- <xsd:element name="FieldName" type="xsd:string"/>
- <xsd:element name="FieldValue" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DpJobProgressEventInfo">
- <xsd:all>
- <xsd:element name="EventStatus" type="na:ObjStatus"/>
- <xsd:element name="EventType" type="xsd:string"/>
- <xsd:element minOccurs="0" name="ProgressLunInfo"
- type="na:ProgressLunInfo"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="DpPolicyNodeName">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="HostId">
- <xsd:restriction base="xsd:integer"/>
-</xsd:simpleType>
-<xsd:complexType name="HostInfo">
- <xsd:all>
- <xsd:element name="HostAddress" type="xsd:string"/>
- <xsd:element name="HostId" type="na:HostId"/>
- <xsd:element name="HostName" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="JobInfo">
- <xsd:all>
- <xsd:element name="JobId" type="xsd:integer"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="LunInfo">
- <xsd:all>
- <xsd:element name="HostId" type="na:ObjId"/>
- <xsd:element name="LunPath" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="ObjId">
- <xsd:restriction base="xsd:integer"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjName">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjNameOrId">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjStatus">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:complexType name="ProgressLunInfo">
- <xsd:all>
- <xsd:element name="LunPathId" type="na:ObjId"/>
- <xsd:element name="LunName" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="ProvisionMemberRequestInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="Description" type="xsd:string"/>
- <xsd:element minOccurs="0" name="MaximumSnapshotSpace"
- type="xsd:integer"/>
- <xsd:element name="Name" type="xsd:string"/>
- <xsd:element name="Size" type="xsd:integer"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="Request">
- <xsd:all>
- <xsd:element minOccurs="0" name="Args">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any maxOccurs="unbounded" minOccurs="0"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Name" type="xsd:string">
- </xsd:element>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="Response">
- <xsd:all>
- <xsd:element minOccurs="0" name="Errno" type="xsd:integer"/>
- <xsd:element minOccurs="0" name="Reason" type="xsd:string"/>
- <xsd:element minOccurs="0" name="Results">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any maxOccurs="unbounded" minOccurs="0"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Status" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="StorageSetInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="DatasetExportInfo"
- type="na:DatasetExportInfo"/>
- <xsd:element minOccurs="0" name="DpNodeName"
- type="na:DpPolicyNodeName"/>
- <xsd:element minOccurs="0" name="ServerNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
-</xsd:complexType>
-</xsd:schema></types>"""
-
-WSDL_TRAILER = """<service name="DfmService">
-<port binding="na:DfmBinding" name="DfmPort">
-<soap:address location="https://HOST_NAME:8488/apis/soap/v1"/>
-</port></service></definitions>"""
-
-RESPONSE_PREFIX = """<?xml version="1.0" encoding="UTF-8"?>
-<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
- xmlns:na="http://www.netapp.com/management/v1"><env:Header/><env:Body>"""
-
-RESPONSE_SUFFIX = """</env:Body></env:Envelope>"""
-
-APIS = ['ApiProxy', 'DatasetListInfoIterStart', 'DatasetListInfoIterNext',
- 'DatasetListInfoIterEnd', 'DatasetEditBegin', 'DatasetEditCommit',
- 'DatasetProvisionMember', 'DatasetRemoveMember', 'DfmAbout',
- 'DpJobProgressEventListIterStart', 'DpJobProgressEventListIterNext',
- 'DpJobProgressEventListIterEnd', 'DatasetMemberListInfoIterStart',
- 'DatasetMemberListInfoIterNext', 'DatasetMemberListInfoIterEnd',
- 'HostListInfoIterStart', 'HostListInfoIterNext', 'HostListInfoIterEnd',
- 'LunListInfoIterStart', 'LunListInfoIterNext', 'LunListInfoIterEnd',
- 'StorageServiceDatasetProvision']
-
-iter_count = 0
-iter_table = {}
-
-
-class FakeDfmServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- """HTTP handler that fakes enough stuff to allow the driver to run"""
-
- def do_GET(s):
- """Respond to a GET request."""
- if '/dfm.wsdl' != s.path:
- s.send_response(404)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "application/wsdl+xml")
- s.end_headers()
- out = s.wfile
- out.write(WSDL_HEADER)
- out.write(WSDL_TYPES)
- for api in APIS:
- out.write('<message name="%sRequest">' % api)
- out.write('<part element="na:%s" name="parameters"/>' % api)
- out.write('</message>')
- out.write('<message name="%sResponse">' % api)
- out.write('<part element="na:%sResult" name="results"/>' % api)
- out.write('</message>')
- out.write('<portType name="DfmInterface">')
- for api in APIS:
- out.write('<operation name="%s">' % api)
- out.write('<input message="na:%sRequest"/>' % api)
- out.write('<output message="na:%sResponse"/>' % api)
- out.write('</operation>')
- out.write('</portType>')
- out.write('<binding name="DfmBinding" type="na:DfmInterface">')
- out.write('<soap:binding style="document" ' +
- 'transport="http://schemas.xmlsoap.org/soap/http"/>')
- for api in APIS:
- out.write('<operation name="%s">' % api)
- out.write('<soap:operation soapAction="urn:%s"/>' % api)
- out.write('<input><soap:body use="literal"/></input>')
- out.write('<output><soap:body use="literal"/></output>')
- out.write('</operation>')
- out.write('</binding>')
- out.write(WSDL_TRAILER)
-
- def do_POST(s):
- """Respond to a POST request."""
- if '/apis/soap/v1' != s.path:
- s.send_response(404)
- s.end_headers
- return
- request_xml = s.rfile.read(int(s.headers['Content-Length']))
- ntap_ns = 'http://www.netapp.com/management/v1'
- nsmap = {'env': 'http://schemas.xmlsoap.org/soap/envelope/',
- 'na': ntap_ns}
- root = etree.fromstring(request_xml)
-
- body = root.xpath('/env:Envelope/env:Body', namespaces=nsmap)[0]
- request = body.getchildren()[0]
- tag = request.tag
- if not tag.startswith('{' + ntap_ns + '}'):
- s.send_response(500)
- s.end_headers
- return
- api = tag[(2 + len(ntap_ns)):]
- global iter_count
- global iter_table
- if 'DatasetListInfoIterStart' == api:
- iter_name = 'dataset_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DatasetListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DatasetListInfoIterStartResult>""" % iter_name
- elif 'DatasetListInfoIterNext' == api:
- tags = body.xpath('na:DatasetListInfoIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DatasetListInfoIterNextResult>
- <na:Datasets></na:Datasets>
- <na:Records>0</na:Records>
- </na:DatasetListInfoIterNextResult>"""
- else:
- iter_table[iter_name] = 1
- body = """<na:DatasetListInfoIterNextResult>
- <na:Datasets>
- <na:DatasetInfo>
- <na:DatasetId>0</na:DatasetId>
- <na:DatasetMetadata>
- <na:DfmMetadataField>
- <na:FieldName>OpenStackProject</na:FieldName>
- <na:FieldValue>testproj</na:FieldValue>
- </na:DfmMetadataField>
- <na:DfmMetadataField>
- <na:FieldName>OpenStackVolType</na:FieldName>
- <na:FieldValue></na:FieldValue>
- </na:DfmMetadataField>
- </na:DatasetMetadata>
- <na:DatasetName>OpenStack_testproj</na:DatasetName>
- </na:DatasetInfo>
- </na:Datasets>
- <na:Records>1</na:Records>
- </na:DatasetListInfoIterNextResult>"""
- elif 'DatasetListInfoIterEnd' == api:
- body = """<na:DatasetListInfoIterEndResult/>"""
- elif 'DatasetEditBegin' == api:
- body = """<na:DatasetEditBeginResult>
- <na:EditLockId>0</na:EditLockId>
- </na:DatasetEditBeginResult>"""
- elif 'DatasetEditCommit' == api:
- body = """<na:DatasetEditCommitResult>
- <na:IsProvisioningFailure>false</na:IsProvisioningFailure>
- <na:JobIds>
- <na:JobInfo>
- <na:JobId>0</na:JobId>
- </na:JobInfo>
- </na:JobIds>
- </na:DatasetEditCommitResult>"""
- elif 'DatasetProvisionMember' == api:
- body = """<na:DatasetProvisionMemberResult/>"""
- elif 'DatasetRemoveMember' == api:
- body = """<na:DatasetRemoveMemberResult/>"""
- elif 'DfmAbout' == api:
- body = """<na:DfmAboutResult/>"""
- elif 'DpJobProgressEventListIterStart' == api:
- iter_name = 'dpjobprogress_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DpJobProgressEventListIterStartResult>
- <na:Records>2</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DpJobProgressEventListIterStartResult>""" % iter_name
- elif 'DpJobProgressEventListIterNext' == api:
- tags = body.xpath('na:DpJobProgressEventListIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DpJobProgressEventListIterNextResult/>"""
- else:
- iter_table[iter_name] = 1
- name = ('filer:/OpenStack_testproj/volume-00000001/'
- 'volume-00000001')
- body = """<na:DpJobProgressEventListIterNextResult>
- <na:ProgressEvents>
- <na:DpJobProgressEventInfo>
- <na:EventStatus>normal</na:EventStatus>
- <na:EventType>lun-create</na:EventType>
- <na:ProgressLunInfo>
- <na:LunPathId>0</na:LunPathId>
- <na:LunName>%s</na:LunName>
- </na:ProgressLunInfo>
- </na:DpJobProgressEventInfo>
- <na:DpJobProgressEventInfo>
- <na:EventStatus>normal</na:EventStatus>
- <na:EventType>job-end</na:EventType>
- </na:DpJobProgressEventInfo>
- </na:ProgressEvents>
- <na:Records>2</na:Records>
- </na:DpJobProgressEventListIterNextResult>""" % name
- elif 'DpJobProgressEventListIterEnd' == api:
- body = """<na:DpJobProgressEventListIterEndResult/>"""
- elif 'DatasetMemberListInfoIterStart' == api:
- iter_name = 'datasetmember_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DatasetMemberListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DatasetMemberListInfoIterStartResult>""" % iter_name
- elif 'DatasetMemberListInfoIterNext' == api:
- tags = body.xpath('na:DatasetMemberListInfoIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DatasetMemberListInfoIterNextResult>
- <na:DatasetMembers></na:DatasetMembers>
- <na:Records>0</na:Records>
- </na:DatasetMemberListInfoIterNextResult>"""
- else:
- iter_table[iter_name] = 1
- name = ('filer:/OpenStack_testproj/volume-00000001/'
- 'volume-00000001')
- body = """<na:DatasetMemberListInfoIterNextResult>
- <na:DatasetMembers>
- <na:DatasetMemberInfo>
- <na:MemberId>0</na:MemberId>
- <na:MemberName>%s</na:MemberName>
- </na:DatasetMemberInfo>
- </na:DatasetMembers>
- <na:Records>1</na:Records>
- </na:DatasetMemberListInfoIterNextResult>""" % name
- elif 'DatasetMemberListInfoIterEnd' == api:
- body = """<na:DatasetMemberListInfoIterEndResult/>"""
- elif 'HostListInfoIterStart' == api:
- body = """<na:HostListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>host</na:Tag>
- </na:HostListInfoIterStartResult>"""
- elif 'HostListInfoIterNext' == api:
- body = """<na:HostListInfoIterNextResult>
- <na:Hosts>
- <na:HostInfo>
- <na:HostAddress>1.2.3.4</na:HostAddress>
- <na:HostId>0</na:HostId>
- <na:HostName>filer</na:HostName>
- </na:HostInfo>
- </na:Hosts>
- <na:Records>1</na:Records>
- </na:HostListInfoIterNextResult>"""
- elif 'HostListInfoIterEnd' == api:
- body = """<na:HostListInfoIterEndResult/>"""
- elif 'LunListInfoIterStart' == api:
- body = """<na:LunListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>lun</na:Tag>
- </na:LunListInfoIterStartResult>"""
- elif 'LunListInfoIterNext' == api:
- path = 'OpenStack_testproj/volume-00000001/volume-00000001'
- body = """<na:LunListInfoIterNextResult>
- <na:Luns>
- <na:LunInfo>
- <na:HostId>0</na:HostId>
- <na:LunPath>%s</na:LunPath>
- </na:LunInfo>
- </na:Luns>
- <na:Records>1</na:Records>
- </na:LunListInfoIterNextResult>""" % path
- elif 'LunListInfoIterEnd' == api:
- body = """<na:LunListInfoIterEndResult/>"""
- elif 'ApiProxy' == api:
- names = body.xpath('na:ApiProxy/na:Request/na:Name',
- namespaces=nsmap)
- proxy = names[0].text
- if 'igroup-list-info' == proxy:
- igroup = 'openstack-iqn.1993-08.org.debian:01:23456789'
- initiator = 'iqn.1993-08.org.debian:01:23456789'
- proxy_body = """<initiator-groups>
- <initiator-group-info>
- <initiator-group-name>%s</initiator-group-name>
- <initiator-group-type>iscsi</initiator-group-type>
- <initiator-group-os-type>linux</initiator-group-os-type>
- <initiators>
- <initiator-info>
- <initiator-name>%s</initiator-name>
- </initiator-info>
- </initiators>
- </initiator-group-info>
- </initiator-groups>""" % (igroup, initiator)
- elif 'igroup-create' == proxy:
- proxy_body = ''
- elif 'igroup-add' == proxy:
- proxy_body = ''
- elif 'lun-map-list-info' == proxy:
- proxy_body = '<initiator-groups/>'
- elif 'lun-map' == proxy:
- proxy_body = '<lun-id-assigned>0</lun-id-assigned>'
- elif 'lun-unmap' == proxy:
- proxy_body = ''
- elif 'iscsi-portal-list-info' == proxy:
- proxy_body = """<iscsi-portal-list-entries>
- <iscsi-portal-list-entry-info>
- <ip-address>1.2.3.4</ip-address>
- <ip-port>3260</ip-port>
- <tpgroup-tag>1000</tpgroup-tag>
- </iscsi-portal-list-entry-info>
- </iscsi-portal-list-entries>"""
- elif 'iscsi-node-get-name' == proxy:
- target = 'iqn.1992-08.com.netapp:sn.111111111'
- proxy_body = '<node-name>%s</node-name>' % target
- else:
- # Unknown proxy API
- s.send_response(500)
- s.end_headers
- return
- api = api + ':' + proxy
- proxy_header = '<na:ApiProxyResult><na:Response><na:Results>'
- proxy_trailer = """</na:Results><na:Status>passed</na:Status>
- </na:Response></na:ApiProxyResult>"""
- body = proxy_header + proxy_body + proxy_trailer
- else:
- # Unknown API
- s.send_response(500)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "text/xml; charset=utf-8")
- s.end_headers()
- s.wfile.write(RESPONSE_PREFIX)
- s.wfile.write(body)
- s.wfile.write(RESPONSE_SUFFIX)
-
-
-class FakeHttplibSocket(object):
- """A fake socket implementation for httplib.HTTPResponse"""
- def __init__(self, value):
- self._rbuffer = StringIO.StringIO(value)
- self._wbuffer = StringIO.StringIO('')
- oldclose = self._wbuffer.close
-
- def newclose():
- self.result = self._wbuffer.getvalue()
- oldclose()
- self._wbuffer.close = newclose
-
- def makefile(self, mode, _other):
- """Returns the socket's internal buffer"""
- if mode == 'r' or mode == 'rb':
- return self._rbuffer
- if mode == 'w' or mode == 'wb':
- return self._wbuffer
-
-
-class FakeHTTPConnection(object):
- """A fake httplib.HTTPConnection for netapp tests
-
- Requests made via this connection actually get translated and routed into
- the fake Dfm handler above, we then turn the response into
- the httplib.HTTPResponse that the caller expects.
- """
- def __init__(self, host, timeout=None):
- self.host = host
-
- def request(self, method, path, data=None, headers=None):
- if not headers:
- headers = {}
- req_str = '%s %s HTTP/1.1\r\n' % (method, path)
- for key, value in headers.iteritems():
- req_str += "%s: %s\r\n" % (key, value)
- if data:
- req_str += '\r\n%s' % data
-
- # NOTE(vish): normally the http transport normailizes from unicode
- sock = FakeHttplibSocket(req_str.decode("latin-1").encode("utf-8"))
- # NOTE(vish): stop the server from trying to look up address from
- # the fake socket
- FakeDfmServerHandler.address_string = lambda x: '127.0.0.1'
- self.app = FakeDfmServerHandler(sock, '127.0.0.1:8088', None)
-
- self.sock = FakeHttplibSocket(sock.result)
- self.http_response = httplib.HTTPResponse(self.sock)
-
- def set_debuglevel(self, level):
- pass
-
- def getresponse(self):
- self.http_response.begin()
- return self.http_response
-
- def getresponsebody(self):
- return self.sock.result
-
-
-class NetAppDriverTestCase(test.TestCase):
- """Test case for NetAppISCSIDriver"""
- STORAGE_SERVICE = 'Openstack Service'
- STORAGE_SERVICE_PREFIX = 'Openstack Service-'
- PROJECT_ID = 'testproj'
- VOLUME_NAME = 'volume-00000001'
- VOLUME_TYPE = ''
- VOLUME_SIZE = 2147483648L # 2 GB
- INITIATOR = 'iqn.1993-08.org.debian:01:23456789'
-
- def setUp(self):
- super(NetAppDriverTestCase, self).setUp()
- driver = netapp.NetAppISCSIDriver()
- self.stubs.Set(httplib, 'HTTPConnection', FakeHTTPConnection)
- driver._create_client(wsdl_url='http://localhost:8088/dfm.wsdl',
- login='root', password='password',
- hostname='localhost', port=8088, cache=False)
- driver._set_storage_service(self.STORAGE_SERVICE)
- driver._set_storage_service_prefix(self.STORAGE_SERVICE_PREFIX)
- driver._set_vfiler('')
- self.driver = driver
-
- def test_connect(self):
- self.driver.check_for_setup_error()
-
- def test_create_destroy(self):
- self.driver._discover_luns()
- self.driver._provision(self.VOLUME_NAME, None, self.PROJECT_ID,
- self.VOLUME_TYPE, self.VOLUME_SIZE)
- self.driver._remove_destroy(self.VOLUME_NAME, self.PROJECT_ID)
-
- def test_map_unmap(self):
- self.driver._discover_luns()
- self.driver._provision(self.VOLUME_NAME, None, self.PROJECT_ID,
- self.VOLUME_TYPE, self.VOLUME_SIZE)
- volume = {'name': self.VOLUME_NAME, 'project_id': self.PROJECT_ID,
- 'id': 0, 'provider_auth': None}
- updates = self.driver._get_export(volume)
- self.assertTrue(updates['provider_location'])
- volume['provider_location'] = updates['provider_location']
- connector = {'initiator': self.INITIATOR}
- connection_info = self.driver.initialize_connection(volume, connector)
- self.assertEqual(connection_info['driver_volume_type'], 'iscsi')
- properties = connection_info['data']
- self.driver.terminate_connection(volume, connector)
- self.driver._remove_destroy(self.VOLUME_NAME, self.PROJECT_ID)
-
-
-WSDL_HEADER_CMODE = """<?xml version="1.0" encoding="UTF-8"?>
-<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:na="http://cloud.netapp.com/"
-xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-xmlns="http://schemas.xmlsoap.org/wsdl/"
-targetNamespace="http://cloud.netapp.com/" name="CloudStorageService">
-"""
-
-WSDL_TYPES_CMODE = """<types>
-<xs:schema xmlns:na="http://cloud.netapp.com/"
-xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
-targetNamespace="http://cloud.netapp.com/">
-
- <xs:element name="ProvisionLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Name" type="xs:string"/>
- <xs:element name="Size" type="xsd:long"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="ProvisionLunResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="DestroyLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="DestroyLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="CloneLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="NewName" type="xsd:string"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="CloneLunResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="MapLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="MapLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="UnmapLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="UnmapLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="ListLuns">
- <xs:complexType>
- <xs:all>
- <xs:element name="NameFilter" type="xsd:string" minOccurs="0"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="ListLunsResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="GetLunTargetDetails">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="GetLunTargetDetailsResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="TargetDetails" type="na:TargetDetails"
- minOccurs="0" maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:complexType name="Metadata">
- <xs:sequence>
- <xs:element name="Key" type="xs:string"/>
- <xs:element name="Value" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
-
- <xs:complexType name="Lun">
- <xs:sequence>
- <xs:element name="Name" type="xs:string"/>
- <xs:element name="Size" type="xs:long"/>
- <xs:element name="Handle" type="xs:string"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
-
- <xs:complexType name="TargetDetails">
- <xs:sequence>
- <xs:element name="Address" type="xs:string"/>
- <xs:element name="Port" type="xs:int"/>
- <xs:element name="Portal" type="xs:int"/>
- <xs:element name="Iqn" type="xs:string"/>
- <xs:element name="LunNumber" type="xs:int"/>
- </xs:sequence>
- </xs:complexType>
-
- </xs:schema></types>"""
-
-WSDL_TRAILER_CMODE = """<service name="CloudStorageService">
- <port name="CloudStoragePort" binding="na:CloudStorageBinding">
- <soap:address location="http://hostname:8080/ws/ntapcloud"/>
- </port>
- </service>
-</definitions>"""
-
-RESPONSE_PREFIX_CMODE = """<?xml version='1.0' encoding='UTF-8'?>
-<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
-<soapenv:Body>"""
-
-RESPONSE_SUFFIX_CMODE = """</soapenv:Body></soapenv:Envelope>"""
-
-CMODE_APIS = ['ProvisionLun', 'DestroyLun', 'CloneLun', 'MapLun', 'UnmapLun',
- 'ListLuns', 'GetLunTargetDetails']
-
-
-class FakeCMODEServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- """HTTP handler that fakes enough stuff to allow the driver to run"""
-
- def do_GET(s):
- """Respond to a GET request."""
- if '/ntap_cloud.wsdl' != s.path:
- s.send_response(404)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "application/wsdl+xml")
- s.end_headers()
- out = s.wfile
- out.write(WSDL_HEADER_CMODE)
- out.write(WSDL_TYPES_CMODE)
- for api in CMODE_APIS:
- out.write('<message name="%sRequest">' % api)
- out.write('<part element="na:%s" name="req"/>' % api)
- out.write('</message>')
- out.write('<message name="%sResponse">' % api)
- out.write('<part element="na:%sResult" name="res"/>' % api)
- out.write('</message>')
- out.write('<portType name="CloudStorage">')
- for api in CMODE_APIS:
- out.write('<operation name="%s">' % api)
- out.write('<input message="na:%sRequest"/>' % api)
- out.write('<output message="na:%sResponse"/>' % api)
- out.write('</operation>')
- out.write('</portType>')
- out.write('<binding name="CloudStorageBinding" '
- 'type="na:CloudStorage">')
- out.write('<soap:binding style="document" ' +
- 'transport="http://schemas.xmlsoap.org/soap/http"/>')
- for api in CMODE_APIS:
- out.write('<operation name="%s">' % api)
- out.write('<soap:operation soapAction=""/>')
- out.write('<input><soap:body use="literal"/></input>')
- out.write('<output><soap:body use="literal"/></output>')
- out.write('</operation>')
- out.write('</binding>')
- out.write(WSDL_TRAILER_CMODE)
-
- def do_POST(s):
- """Respond to a POST request."""
- if '/ws/ntapcloud' != s.path:
- s.send_response(404)
- s.end_headers
- return
- request_xml = s.rfile.read(int(s.headers['Content-Length']))
- ntap_ns = 'http://cloud.netapp.com/'
- nsmap = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
- 'na': ntap_ns}
- root = etree.fromstring(request_xml)
-
- body = root.xpath('/soapenv:Envelope/soapenv:Body',
- namespaces=nsmap)[0]
- request = body.getchildren()[0]
- tag = request.tag
- if not tag.startswith('{' + ntap_ns + '}'):
- s.send_response(500)
- s.end_headers
- return
- api = tag[(2 + len(ntap_ns)):]
- if 'ProvisionLun' == api:
- body = """<ns:ProvisionLunResult xmlns:ns=
- "http://cloud.netapp.com/">
- <Lun><Name>lun1</Name><Size>20</Size>
- <Handle>1d9c006c-a406-42f6-a23f-5ed7a6dc33e3</Handle>
- <Metadata><Key>OsType</Key>
- <Value>linux</Value></Metadata></Lun>
- </ns:ProvisionLunResult>"""
- elif 'DestroyLun' == api:
- body = """<ns:DestroyLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'CloneLun' == api:
- body = """<ns:CloneLunResult xmlns:ns="http://cloud.netapp.com/">
- <Lun><Name>lun2</Name><Size>2</Size>
- <Handle>98ea1791d228453899d422b4611642c3</Handle>
- <Metadata><Key>OsType</Key>
- <Value>linux</Value></Metadata>
- </Lun></ns:CloneLunResult>"""
- elif 'MapLun' == api:
- body = """<ns1:MapLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'Unmap' == api:
- body = """<ns1:UnmapLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'ListLuns' == api:
- body = """<ns:ListLunsResult xmlns:ns="http://cloud.netapp.com/">
- <Lun>
- <Name>lun1</Name>
- <Size>20</Size>
- <Handle>asdjdnsd</Handle>
- </Lun>
- </ns:ListLunsResult>"""
- elif 'GetLunTargetDetails' == api:
- body = """<ns:GetLunTargetDetailsResult
- xmlns:ns="http://cloud.netapp.com/">
- <TargetDetail>
- <Address>1.2.3.4</Address>
- <Port>3260</Port>
- <Portal>1000</Portal>
- <Iqn>iqn.199208.com.netapp:sn.123456789</Iqn>
- <LunNumber>0</LunNumber>
- </TargetDetail>
- </ns:GetLunTargetDetailsResult>"""
- else:
- # Unknown API
- s.send_response(500)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "text/xml; charset=utf-8")
- s.end_headers()
- s.wfile.write(RESPONSE_PREFIX_CMODE)
- s.wfile.write(body)
- s.wfile.write(RESPONSE_SUFFIX_CMODE)
-
-
-class FakeCmodeHTTPConnection(object):
- """A fake httplib.HTTPConnection for netapp tests
-
- Requests made via this connection actually get translated and routed into
- the fake Dfm handler above, we then turn the response into
- the httplib.HTTPResponse that the caller expects.
- """
- def __init__(self, host, timeout=None):
- self.host = host
-
- def request(self, method, path, data=None, headers=None):
- if not headers:
- headers = {}
- req_str = '%s %s HTTP/1.1\r\n' % (method, path)
- for key, value in headers.iteritems():
- req_str += "%s: %s\r\n" % (key, value)
- if data:
- req_str += '\r\n%s' % data
-
- # NOTE(vish): normally the http transport normailizes from unicode
- sock = FakeHttplibSocket(req_str.decode("latin-1").encode("utf-8"))
- # NOTE(vish): stop the server from trying to look up address from
- # the fake socket
- FakeCMODEServerHandler.address_string = lambda x: '127.0.0.1'
- self.app = FakeCMODEServerHandler(sock, '127.0.0.1:8080', None)
-
- self.sock = FakeHttplibSocket(sock.result)
- self.http_response = httplib.HTTPResponse(self.sock)
-
- def set_debuglevel(self, level):
- pass
-
- def getresponse(self):
- self.http_response.begin()
- return self.http_response
-
- def getresponsebody(self):
- return self.sock.result
-
-
-class NetAppCmodeISCSIDriverTestCase(test.TestCase):
- """Test case for NetAppISCSIDriver"""
- volume = {
- 'name': 'lun1', 'size': 1, 'volume_name': 'lun1',
- 'os_type': 'linux', 'provider_location': 'lun1',
- 'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
- 'display_name': None, 'display_description': 'lun1',
- 'volume_type_id': None
- }
- snapshot = {
- 'name': 'lun2', 'size': 1, 'volume_name': 'lun1',
- 'volume_size': 1, 'project_id': 'project'
- }
- volume_sec = {
- 'name': 'vol_snapshot', 'size': 1, 'volume_name': 'lun1',
- 'os_type': 'linux', 'provider_location': 'lun1',
- 'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
- 'display_name': None, 'display_description': 'lun1',
- 'volume_type_id': None
- }
-
- def setUp(self):
- super(NetAppCmodeISCSIDriverTestCase, self).setUp()
- driver = netapp.NetAppCmodeISCSIDriver()
- self.stubs.Set(httplib, 'HTTPConnection', FakeCmodeHTTPConnection)
- driver._create_client(wsdl_url='http://localhost:8080/ntap_cloud.wsdl',
- login='root', password='password',
- hostname='localhost', port=8080, cache=False)
- self.driver = driver
-
- def test_connect(self):
- self.driver.check_for_setup_error()
-
- def test_create_destroy(self):
- self.driver.create_volume(self.volume)
- self.driver.delete_volume(self.volume)
-
- def test_create_vol_snapshot_destroy(self):
- self.driver.create_volume(self.volume)
- self.driver.create_snapshot(self.snapshot)
- self.driver.create_volume_from_snapshot(self.volume_sec, self.snapshot)
- self.driver.delete_snapshot(self.snapshot)
- self.driver.delete_volume(self.volume)
-
- def test_map_unmap(self):
- self.driver.create_volume(self.volume)
- updates = self.driver.create_export(None, self.volume)
- self.assertTrue(updates['provider_location'])
- self.volume['provider_location'] = updates['provider_location']
- connector = {'initiator': 'init1'}
- connection_info = self.driver.initialize_connection(self.volume,
- connector)
- self.assertEqual(connection_info['driver_volume_type'], 'iscsi')
- properties = connection_info['data']
- self.driver.terminate_connection(self.volume, connector)
- self.driver.delete_volume(self.volume)
diff --git a/nova/tests/test_netapp_nfs.py b/nova/tests/test_netapp_nfs.py
deleted file mode 100644
index 1a8824386..000000000
--- a/nova/tests/test_netapp_nfs.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2012 NetApp, Inc.
-# 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.
-"""Unit tests for the NetApp-specific NFS driver module (netapp_nfs)"""
-
-from nova import context
-from nova import exception
-from nova import test
-
-from nova.volume import netapp
-from nova.volume import netapp_nfs
-from nova.volume import nfs
-
-from mox import IgnoreArg
-from mox import IsA
-from mox import MockObject
-
-import mox
-import suds
-import types
-
-
-class FakeVolume(object):
- def __init__(self, size=0):
- self.size = size
- self.id = hash(self)
- self.name = None
-
- def __getitem__(self, key):
- return self.__dict__[key]
-
-
-class FakeSnapshot(object):
- def __init__(self, volume_size=0):
- self.volume_name = None
- self.name = None
- self.volume_id = None
- self.volume_size = volume_size
- self.user_id = None
- self.status = None
-
- def __getitem__(self, key):
- return self.__dict__[key]
-
-
-class FakeResponce(object):
- def __init__(self, status):
- """
- :param status: Either 'failed' or 'passed'
- """
- self.Status = status
-
- if status == 'failed':
- self.Reason = 'Sample error'
-
-
-class NetappNfsDriverTestCase(test.TestCase):
- """Test case for NetApp specific NFS clone driver"""
-
- def setUp(self):
- self._driver = netapp_nfs.NetAppNFSDriver()
- super(NetappNfsDriverTestCase, self).setUp()
-
- def test_check_for_setup_error(self):
- mox = self.mox
- drv = self._driver
-
- # check exception raises when flags are not set
- self.assertRaises(exception.NovaException,
- drv.check_for_setup_error)
-
- # set required flags
- self.flags(netapp_wsdl_url='val',
- netapp_login='val',
- netapp_password='val',
- netapp_server_hostname='val',
- netapp_server_port='val')
-
- mox.StubOutWithMock(nfs.NfsDriver, 'check_for_setup_error')
- nfs.NfsDriver.check_for_setup_error()
- mox.ReplayAll()
-
- drv.check_for_setup_error()
-
- def test_do_setup(self):
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, 'check_for_setup_error')
- mox.StubOutWithMock(netapp_nfs.NetAppNFSDriver, '_get_client')
-
- drv.check_for_setup_error()
- netapp_nfs.NetAppNFSDriver._get_client()
-
- mox.ReplayAll()
-
- drv.do_setup(IsA(context.RequestContext))
-
- def test_create_snapshot(self):
- """Test snapshot can be created and deleted"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_clone_volume')
- drv._clone_volume(IgnoreArg(), IgnoreArg(), IgnoreArg())
- mox.ReplayAll()
-
- drv.create_snapshot(FakeSnapshot())
-
- def test_create_volume_from_snapshot(self):
- """Tests volume creation from snapshot"""
- drv = self._driver
- mox = self.mox
- volume = FakeVolume(1)
- snapshot = FakeSnapshot(2)
-
- self.assertRaises(exception.NovaException,
- drv.create_volume_from_snapshot,
- volume,
- snapshot)
-
- snapshot = FakeSnapshot(1)
-
- location = '127.0.0.1:/nfs'
- expected_result = {'provider_location': location}
- mox.StubOutWithMock(drv, '_clone_volume')
- mox.StubOutWithMock(drv, '_get_volume_location')
- drv._clone_volume(IgnoreArg(), IgnoreArg(), IgnoreArg())
- drv._get_volume_location(IgnoreArg()).AndReturn(location)
-
- mox.ReplayAll()
-
- loc = drv.create_volume_from_snapshot(volume, snapshot)
-
- self.assertEquals(loc, expected_result)
-
- def _prepare_delete_snapshot_mock(self, snapshot_exists):
- drv = self._driver
- mox = self.mox
-
- mox.StubOutWithMock(drv, '_get_provider_location')
- mox.StubOutWithMock(drv, '_volume_not_present')
-
- if snapshot_exists:
- mox.StubOutWithMock(drv, '_execute')
- mox.StubOutWithMock(drv, '_get_volume_path')
-
- drv._get_provider_location(IgnoreArg())
- drv._volume_not_present(IgnoreArg(), IgnoreArg())\
- .AndReturn(not snapshot_exists)
-
- if snapshot_exists:
- drv._get_volume_path(IgnoreArg(), IgnoreArg())
- drv._execute('rm', None, run_as_root=True)
-
- mox.ReplayAll()
-
- return mox
-
- def test_delete_existing_snapshot(self):
- drv = self._driver
- self._prepare_delete_snapshot_mock(True)
-
- drv.delete_snapshot(FakeSnapshot())
-
- def test_delete_missing_snapshot(self):
- drv = self._driver
- self._prepare_delete_snapshot_mock(False)
-
- drv.delete_snapshot(FakeSnapshot())
-
- def _prepare_clone_mock(self, status):
- drv = self._driver
- mox = self.mox
-
- volume = FakeVolume()
- setattr(volume, 'provider_location', '127.0.0.1:/nfs')
-
- drv._client = MockObject(suds.client.Client)
- drv._client.factory = MockObject(suds.client.Factory)
- drv._client.service = MockObject(suds.client.ServiceSelector)
-
- # ApiProxy() method is generated by ServiceSelector at runtime from the
- # XML, so mocking is impossible.
- setattr(drv._client.service,
- 'ApiProxy',
- types.MethodType(lambda *args, **kwargs: FakeResponce(status),
- suds.client.ServiceSelector))
- mox.StubOutWithMock(drv, '_get_host_id')
- mox.StubOutWithMock(drv, '_get_full_export_path')
-
- drv._get_host_id(IgnoreArg()).AndReturn('10')
- drv._get_full_export_path(IgnoreArg(), IgnoreArg()).AndReturn('/nfs')
-
- return mox
-
- def test_successfull_clone_volume(self):
- drv = self._driver
- mox = self._prepare_clone_mock('passed')
-
- mox.ReplayAll()
-
- volume_name = 'volume_name'
- clone_name = 'clone_name'
- volume_id = volume_name + str(hash(volume_name))
-
- drv._clone_volume(volume_name, clone_name, volume_id)
-
- def test_failed_clone_volume(self):
- drv = self._driver
- mox = self._prepare_clone_mock('failed')
-
- mox.ReplayAll()
-
- volume_name = 'volume_name'
- clone_name = 'clone_name'
- volume_id = volume_name + str(hash(volume_name))
-
- self.assertRaises(exception.NovaException,
- drv._clone_volume,
- volume_name, clone_name, volume_id)
diff --git a/nova/tests/test_nexenta.py b/nova/tests/test_nexenta.py
deleted file mode 100644
index aac877cc1..000000000
--- a/nova/tests/test_nexenta.py
+++ /dev/null
@@ -1,278 +0,0 @@
-#!/usr/bin/env python
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-#
-# Copyright 2011 Nexenta Systems, Inc.
-# 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.
-"""
-Unit tests for OpenStack Nova volume driver
-"""
-
-import base64
-import urllib2
-
-import nova.flags
-import nova.test
-from nova.volume import nexenta
-from nova.volume.nexenta import jsonrpc
-from nova.volume.nexenta import volume
-
-FLAGS = nova.flags.FLAGS
-
-
-class TestNexentaDriver(nova.test.TestCase):
- TEST_VOLUME_NAME = 'volume1'
- TEST_VOLUME_NAME2 = 'volume2'
- TEST_SNAPSHOT_NAME = 'snapshot1'
- TEST_VOLUME_REF = {
- 'name': TEST_VOLUME_NAME,
- 'size': 1,
- }
- TEST_VOLUME_REF2 = {
- 'name': TEST_VOLUME_NAME2,
- 'size': 1,
- }
- TEST_SNAPSHOT_REF = {
- 'name': TEST_SNAPSHOT_NAME,
- 'volume_name': TEST_VOLUME_NAME,
- }
-
- def setUp(self):
- super(TestNexentaDriver, self).setUp()
- self.flags(
- nexenta_host='1.1.1.1',
- nexenta_volume='nova',
- nexenta_target_prefix='iqn:',
- nexenta_target_group_prefix='nova/',
- nexenta_blocksize='8K',
- nexenta_sparse=True,
- )
- self.nms_mock = self.mox.CreateMockAnything()
- for mod in ['volume', 'zvol', 'iscsitarget',
- 'stmf', 'scsidisk', 'snapshot']:
- setattr(self.nms_mock, mod, self.mox.CreateMockAnything())
- self.stubs.Set(jsonrpc, 'NexentaJSONProxy',
- lambda *_, **__: self.nms_mock)
- self.drv = volume.NexentaDriver()
- self.drv.do_setup({})
-
- def test_setup_error(self):
- self.nms_mock.volume.object_exists('nova').AndReturn(True)
- self.mox.ReplayAll()
- self.drv.check_for_setup_error()
-
- def test_setup_error_fail(self):
- self.nms_mock.volume.object_exists('nova').AndReturn(False)
- self.mox.ReplayAll()
- self.assertRaises(LookupError, self.drv.check_for_setup_error)
-
- def test_local_path(self):
- self.assertRaises(NotImplementedError, self.drv.local_path, '')
-
- def test_create_volume(self):
- self.nms_mock.zvol.create('nova/volume1', '1G', '8K', True)
- self.mox.ReplayAll()
- self.drv.create_volume(self.TEST_VOLUME_REF)
-
- def test_delete_volume(self):
- self.nms_mock.zvol.destroy('nova/volume1', '')
- self.mox.ReplayAll()
- self.drv.delete_volume(self.TEST_VOLUME_REF)
-
- def test_create_snapshot(self):
- self.nms_mock.zvol.create_snapshot('nova/volume1', 'snapshot1', '')
- self.mox.ReplayAll()
- self.drv.create_snapshot(self.TEST_SNAPSHOT_REF)
-
- def test_create_volume_from_snapshot(self):
- self.nms_mock.zvol.clone('nova/volume1@snapshot1', 'nova/volume2')
- self.mox.ReplayAll()
- self.drv.create_volume_from_snapshot(self.TEST_VOLUME_REF2,
- self.TEST_SNAPSHOT_REF)
-
- def test_delete_snapshot(self):
- self.nms_mock.snapshot.destroy('nova/volume1@snapshot1', '')
- self.mox.ReplayAll()
- self.drv.delete_snapshot(self.TEST_SNAPSHOT_REF)
-
- _CREATE_EXPORT_METHODS = [
- ('iscsitarget', 'create_target', ({'target_name': 'iqn:volume1'},),
- u'Unable to create iscsi target\n'
- u' iSCSI target iqn.1986-03.com.sun:02:nova-volume1 already'
- u' configured\n'
- u' itadm create-target failed with error 17\n',
- ),
- ('stmf', 'create_targetgroup', ('nova/volume1',),
- u'Unable to create targetgroup: stmfadm: nova/volume1:'
- u' already exists\n',
- ),
- ('stmf', 'add_targetgroup_member', ('nova/volume1', 'iqn:volume1'),
- u'Unable to add member to targetgroup: stmfadm:'
- u' iqn.1986-03.com.sun:02:nova-volume1: already exists\n',
- ),
- ('scsidisk', 'create_lu', ('nova/volume1', {}),
- u"Unable to create lu with zvol 'nova/volume1':\n"
- u" sbdadm: filename /dev/zvol/rdsk/nova/volume1: in use\n",
- ),
- ('scsidisk', 'add_lun_mapping_entry', ('nova/volume1', {
- 'target_group': 'nova/volume1', 'lun': '0'}),
- u"Unable to add view to zvol 'nova/volume1' (LUNs in use: ):\n"
- u" stmfadm: view entry exists\n",
- ),
- ]
-
- def _stub_export_method(self, module, method, args, error, fail=False):
- m = getattr(self.nms_mock, module)
- m = getattr(m, method)
- mock = m(*args)
- if fail:
- mock.AndRaise(nexenta.NexentaException(error))
-
- def _stub_all_export_methods(self, fail=False):
- for params in self._CREATE_EXPORT_METHODS:
- self._stub_export_method(*params, fail=fail)
-
- def test_create_export(self):
- self._stub_all_export_methods()
- self.mox.ReplayAll()
- retval = self.drv.create_export({}, self.TEST_VOLUME_REF)
- self.assertEquals(retval,
- {'provider_location':
- '%s:%s,1 %s%s' % (FLAGS.nexenta_host,
- FLAGS.nexenta_iscsi_target_portal_port,
- FLAGS.nexenta_target_prefix,
- self.TEST_VOLUME_NAME)})
-
- def __get_test(i):
- def _test_create_export_fail(self):
- for params in self._CREATE_EXPORT_METHODS[:i]:
- self._stub_export_method(*params)
- self._stub_export_method(*self._CREATE_EXPORT_METHODS[i],
- fail=True)
- self.mox.ReplayAll()
- self.assertRaises(nexenta.NexentaException,
- self.drv.create_export, {}, self.TEST_VOLUME_REF)
- return _test_create_export_fail
-
- for i in range(len(_CREATE_EXPORT_METHODS)):
- locals()['test_create_export_fail_%d' % i] = __get_test(i)
-
- def test_ensure_export(self):
- self._stub_all_export_methods(fail=True)
- self.mox.ReplayAll()
- self.drv.ensure_export({}, self.TEST_VOLUME_REF)
-
- def test_remove_export(self):
- self.nms_mock.scsidisk.delete_lu('nova/volume1')
- self.nms_mock.stmf.destroy_targetgroup('nova/volume1')
- self.nms_mock.iscsitarget.delete_target('iqn:volume1')
- self.mox.ReplayAll()
- self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
- def test_remove_export_fail_0(self):
- self.nms_mock.scsidisk.delete_lu('nova/volume1')
- self.nms_mock.stmf.destroy_targetgroup('nova/volume1').AndRaise(
- nexenta.NexentaException())
- self.nms_mock.iscsitarget.delete_target('iqn:volume1')
- self.mox.ReplayAll()
- self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
- def test_remove_export_fail_1(self):
- self.nms_mock.scsidisk.delete_lu('nova/volume1')
- self.nms_mock.stmf.destroy_targetgroup('nova/volume1')
- self.nms_mock.iscsitarget.delete_target('iqn:volume1').AndRaise(
- nexenta.NexentaException())
- self.mox.ReplayAll()
- self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
-
-class TestNexentaJSONRPC(nova.test.TestCase):
- URL = 'http://example.com/'
- URL_S = 'https://example.com/'
- USER = 'user'
- PASSWORD = 'password'
- HEADERS = {'Authorization': 'Basic %s' % (base64.b64encode(
- ':'.join((USER, PASSWORD))),),
- 'Content-Type': 'application/json'}
- REQUEST = 'the request'
-
- def setUp(self):
- super(TestNexentaJSONRPC, self).setUp()
- self.proxy = jsonrpc.NexentaJSONProxy(
- self.URL, self.USER, self.PASSWORD, auto=True)
- self.mox.StubOutWithMock(urllib2, 'Request', True)
- self.mox.StubOutWithMock(urllib2, 'urlopen')
- self.resp_mock = self.mox.CreateMockAnything()
- self.resp_info_mock = self.mox.CreateMockAnything()
- self.resp_mock.info().AndReturn(self.resp_info_mock)
- urllib2.urlopen(self.REQUEST).AndReturn(self.resp_mock)
-
- def test_call(self):
- urllib2.Request(self.URL,
- '{"object": null, "params": ["arg1", "arg2"], "method": null}',
- self.HEADERS).AndReturn(self.REQUEST)
- self.resp_info_mock.status = ''
- self.resp_mock.read().AndReturn(
- '{"error": null, "result": "the result"}')
- self.mox.ReplayAll()
- result = self.proxy('arg1', 'arg2')
- self.assertEquals("the result", result)
-
- def test_call_deep(self):
- urllib2.Request(self.URL,
- '{"object": "obj1.subobj", "params": ["arg1", "arg2"],'
- ' "method": "meth"}',
- self.HEADERS).AndReturn(self.REQUEST)
- self.resp_info_mock.status = ''
- self.resp_mock.read().AndReturn(
- '{"error": null, "result": "the result"}')
- self.mox.ReplayAll()
- result = self.proxy.obj1.subobj.meth('arg1', 'arg2')
- self.assertEquals("the result", result)
-
- def test_call_auto(self):
- urllib2.Request(self.URL,
- '{"object": null, "params": ["arg1", "arg2"], "method": null}',
- self.HEADERS).AndReturn(self.REQUEST)
- urllib2.Request(self.URL_S,
- '{"object": null, "params": ["arg1", "arg2"], "method": null}',
- self.HEADERS).AndReturn(self.REQUEST)
- self.resp_info_mock.status = 'EOF in headers'
- self.resp_mock.read().AndReturn(
- '{"error": null, "result": "the result"}')
- urllib2.urlopen(self.REQUEST).AndReturn(self.resp_mock)
- self.mox.ReplayAll()
- result = self.proxy('arg1', 'arg2')
- self.assertEquals("the result", result)
-
- def test_call_error(self):
- urllib2.Request(self.URL,
- '{"object": null, "params": ["arg1", "arg2"], "method": null}',
- self.HEADERS).AndReturn(self.REQUEST)
- self.resp_info_mock.status = ''
- self.resp_mock.read().AndReturn(
- '{"error": {"message": "the error"}, "result": "the result"}')
- self.mox.ReplayAll()
- self.assertRaises(jsonrpc.NexentaJSONException,
- self.proxy, 'arg1', 'arg2')
-
- def test_call_fail(self):
- urllib2.Request(self.URL,
- '{"object": null, "params": ["arg1", "arg2"], "method": null}',
- self.HEADERS).AndReturn(self.REQUEST)
- self.resp_info_mock.status = 'EOF in headers'
- self.proxy.auto = False
- self.mox.ReplayAll()
- self.assertRaises(jsonrpc.NexentaJSONException,
- self.proxy, 'arg1', 'arg2')
diff --git a/nova/tests/test_nfs.py b/nova/tests/test_nfs.py
deleted file mode 100644
index d0d235b1b..000000000
--- a/nova/tests/test_nfs.py
+++ /dev/null
@@ -1,569 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2012 NetApp, Inc.
-# 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.
-"""Unit tests for the NFS driver module"""
-
-import __builtin__
-import errno
-import os
-
-import mox as mox_lib
-from mox import IgnoreArg
-from mox import IsA
-from mox import stubout
-
-from nova import context
-from nova import exception
-from nova.exception import ProcessExecutionError
-from nova import test
-
-from nova.volume import nfs
-
-
-class DumbVolume(object):
- fields = {}
-
- def __setitem__(self, key, value):
- self.fields[key] = value
-
- def __getitem__(self, item):
- return self.fields[item]
-
-
-class NfsDriverTestCase(test.TestCase):
- """Test case for NFS driver"""
-
- TEST_NFS_EXPORT1 = 'nfs-host1:/export'
- TEST_NFS_EXPORT2 = 'nfs-host2:/export'
- TEST_SIZE_IN_GB = 1
- TEST_MNT_POINT = '/mnt/nfs'
- TEST_MNT_POINT_BASE = '/mnt/test'
- TEST_LOCAL_PATH = '/mnt/nfs/volume-123'
- TEST_FILE_NAME = 'test.txt'
- TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
- ONE_GB_IN_BYTES = 1024 * 1024 * 1024
-
- def setUp(self):
- self._driver = nfs.NfsDriver()
- super(NfsDriverTestCase, self).setUp()
-
- def stub_out_not_replaying(self, obj, attr_name):
- attr_to_replace = getattr(obj, attr_name)
- stub = mox_lib.MockObject(attr_to_replace)
- self.stubs.Set(obj, attr_name, stub)
-
- def test_path_exists_should_return_true(self):
- """_path_exists should return True if stat returns 0"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('stat', self.TEST_FILE_NAME, run_as_root=True)
-
- mox.ReplayAll()
-
- self.assertTrue(drv._path_exists(self.TEST_FILE_NAME))
-
- def test_path_exists_should_return_false(self):
- """_path_exists should return True if stat doesn't return 0"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('stat', self.TEST_FILE_NAME, run_as_root=True).\
- AndRaise(ProcessExecutionError(
- stderr="stat: cannot stat `test.txt': No such file or directory"))
-
- mox.ReplayAll()
-
- self.assertFalse(drv._path_exists(self.TEST_FILE_NAME))
-
- def test_local_path(self):
- """local_path common use case"""
- self.flags(nfs_mount_point_base=self.TEST_MNT_POINT_BASE)
- drv = self._driver
-
- volume = DumbVolume()
- volume['provider_location'] = self.TEST_NFS_EXPORT1
- volume['name'] = 'volume-123'
-
- self.assertEqual(
- '/mnt/test/2f4f60214cf43c595666dd815f0360a4/volume-123',
- drv.local_path(volume))
-
- def test_mount_nfs_should_mount_correctly(self):
- """_mount_nfs common case usage"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_MNT_POINT).AndReturn(True)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('mount', '-t', 'nfs', self.TEST_NFS_EXPORT1,
- self.TEST_MNT_POINT, run_as_root=True)
-
- mox.ReplayAll()
-
- drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
-
- def test_mount_nfs_should_suppress_already_mounted_error(self):
- """_mount_nfs should suppress already mounted error if ensure=True
- """
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_MNT_POINT).AndReturn(True)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('mount', '-t', 'nfs', self.TEST_NFS_EXPORT1,
- self.TEST_MNT_POINT, run_as_root=True).\
- AndRaise(ProcessExecutionError(
- stderr='is busy or already mounted'))
-
- mox.ReplayAll()
-
- drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT, ensure=True)
-
- def test_mount_nfs_should_reraise_already_mounted_error(self):
- """_mount_nfs should not suppress already mounted error if ensure=False
- """
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_MNT_POINT).AndReturn(True)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('mount', '-t', 'nfs', self.TEST_NFS_EXPORT1,
- self.TEST_MNT_POINT, run_as_root=True).\
- AndRaise(ProcessExecutionError(stderr='is busy or already mounted'))
-
- mox.ReplayAll()
-
- self.assertRaises(ProcessExecutionError, drv._mount_nfs,
- self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT,
- ensure=False)
-
- def test_mount_nfs_should_create_mountpoint_if_not_yet(self):
- """_mount_nfs should create mountpoint if it doesn't exist"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_MNT_POINT).AndReturn(False)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
- drv._execute(*([IgnoreArg()] * 5), run_as_root=IgnoreArg())
-
- mox.ReplayAll()
-
- drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
-
- def test_mount_nfs_should_not_create_mountpoint_if_already(self):
- """_mount_nfs should not create mountpoint if it already exists"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_MNT_POINT).AndReturn(True)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute(*([IgnoreArg()] * 5), run_as_root=IgnoreArg())
-
- mox.ReplayAll()
-
- drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
-
- def test_get_hash_str(self):
- """_get_hash_str should calculation correct value"""
- drv = self._driver
-
- self.assertEqual('2f4f60214cf43c595666dd815f0360a4',
- drv._get_hash_str(self.TEST_NFS_EXPORT1))
-
- def test_get_mount_point_for_share(self):
- """_get_mount_point_for_share should calculate correct value"""
- drv = self._driver
-
- self.flags(nfs_mount_point_base=self.TEST_MNT_POINT_BASE)
-
- self.assertEqual('/mnt/test/2f4f60214cf43c595666dd815f0360a4',
- drv._get_mount_point_for_share(self.TEST_NFS_EXPORT1))
-
- def test_get_available_capacity_with_df(self):
- """_get_available_capacity should calculate correct value"""
- mox = self.mox
- drv = self._driver
-
- df_avail = 1490560
- df_head = 'Filesystem 1K-blocks Used Available Use% Mounted on\n'
- df_data = 'nfs-host:/export 2620544 996864 %d 41%% /mnt' % df_avail
- df_output = df_head + df_data
-
- self.flags(nfs_disk_util='df')
-
- mox.StubOutWithMock(drv, '_get_mount_point_for_share')
- drv._get_mount_point_for_share(self.TEST_NFS_EXPORT1).\
- AndReturn(self.TEST_MNT_POINT)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('df', '-P', '-B', '1', self.TEST_MNT_POINT,
- run_as_root=True).AndReturn((df_output, None))
-
- mox.ReplayAll()
-
- self.assertEquals(df_avail,
- drv._get_available_capacity(self.TEST_NFS_EXPORT1))
-
- def test_get_available_capacity_with_du(self):
- """_get_available_capacity should calculate correct value"""
- mox = self.mox
- drv = self._driver
-
- self.flags(nfs_disk_util='du')
-
- df_total_size = 2620544
- df_used_size = 996864
- df_avail_size = 1490560
- df_title = 'Filesystem 1-blocks Used Available Use% Mounted on\n'
- df_mnt_data = 'nfs-host:/export %d %d %d 41%% /mnt' % (df_total_size,
- df_used_size,
- df_avail_size)
- df_output = df_title + df_mnt_data
-
- du_used = 490560
- du_output = '%d /mnt' % du_used
-
- mox.StubOutWithMock(drv, '_get_mount_point_for_share')
- drv._get_mount_point_for_share(self.TEST_NFS_EXPORT1).\
- AndReturn(self.TEST_MNT_POINT)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('df', '-P', '-B', '1', self.TEST_MNT_POINT,
- run_as_root=True).\
- AndReturn((df_output, None))
- drv._execute('du', '-sb', '--apparent-size',
- '--exclude', '*snapshot*',
- self.TEST_MNT_POINT,
- run_as_root=True).AndReturn((du_output, None))
-
- mox.ReplayAll()
-
- self.assertEquals(df_total_size - du_used,
- drv._get_available_capacity(self.TEST_NFS_EXPORT1))
-
- def test_load_shares_config(self):
- mox = self.mox
- drv = self._driver
-
- self.flags(nfs_shares_config=self.TEST_SHARES_CONFIG_FILE)
-
- mox.StubOutWithMock(__builtin__, 'open')
- config_data = []
- config_data.append(self.TEST_NFS_EXPORT1)
- config_data.append('#' + self.TEST_NFS_EXPORT2)
- config_data.append('')
- __builtin__.open(self.TEST_SHARES_CONFIG_FILE).AndReturn(config_data)
- mox.ReplayAll()
-
- shares = drv._load_shares_config()
-
- self.assertEqual([self.TEST_NFS_EXPORT1], shares)
-
- def test_ensure_share_mounted(self):
- """_ensure_share_mounted simple use case"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_get_mount_point_for_share')
- drv._get_mount_point_for_share(self.TEST_NFS_EXPORT1).\
- AndReturn(self.TEST_MNT_POINT)
-
- mox.StubOutWithMock(drv, '_mount_nfs')
- drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT, ensure=True)
-
- mox.ReplayAll()
-
- drv._ensure_share_mounted(self.TEST_NFS_EXPORT1)
-
- def test_ensure_shares_mounted_should_save_mounting_successfully(self):
- """_ensure_shares_mounted should save share if mounted with success"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_load_shares_config')
- drv._load_shares_config().AndReturn([self.TEST_NFS_EXPORT1])
- mox.StubOutWithMock(drv, '_ensure_share_mounted')
- drv._ensure_share_mounted(self.TEST_NFS_EXPORT1)
-
- mox.ReplayAll()
-
- drv._ensure_shares_mounted()
-
- self.assertEqual(1, len(drv._mounted_shares))
- self.assertEqual(self.TEST_NFS_EXPORT1, drv._mounted_shares[0])
-
- def test_ensure_shares_mounted_should_not_save_mounting_with_error(self):
- """_ensure_shares_mounted should not save share if failed to mount"""
- mox = self.mox
- drv = self._driver
-
- mox.StubOutWithMock(drv, '_load_shares_config')
- drv._load_shares_config().AndReturn([self.TEST_NFS_EXPORT1])
- mox.StubOutWithMock(drv, '_ensure_share_mounted')
- drv._ensure_share_mounted(self.TEST_NFS_EXPORT1).AndRaise(Exception())
-
- mox.ReplayAll()
-
- drv._ensure_shares_mounted()
-
- self.assertEqual(0, len(drv._mounted_shares))
-
- def test_setup_should_throw_error_if_shares_config_not_configured(self):
- """do_setup should throw error if shares config is not configured """
- drv = self._driver
-
- self.flags(nfs_shares_config=self.TEST_SHARES_CONFIG_FILE)
-
- self.assertRaises(exception.NfsException,
- drv.do_setup, IsA(context.RequestContext))
-
- def test_setup_should_throw_exception_if_nfs_client_is_not_installed(self):
- """do_setup should throw error if nfs client is not installed """
- mox = self.mox
- drv = self._driver
-
- self.flags(nfs_shares_config=self.TEST_SHARES_CONFIG_FILE)
-
- mox.StubOutWithMock(os.path, 'exists')
- os.path.exists(self.TEST_SHARES_CONFIG_FILE).AndReturn(True)
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('mount.nfs', check_exit_code=False).\
- AndRaise(OSError(errno.ENOENT, 'No such file or directory'))
-
- mox.ReplayAll()
-
- self.assertRaises(exception.NfsException,
- drv.do_setup, IsA(context.RequestContext))
-
- def test_find_share_should_throw_error_if_there_is_no_mounted_shares(self):
- """_find_share should throw error if there is no mounted shares"""
- drv = self._driver
-
- drv._mounted_shares = []
-
- self.assertRaises(exception.NotFound, drv._find_share,
- self.TEST_SIZE_IN_GB)
-
- def test_find_share(self):
- """_find_share simple use case"""
- mox = self.mox
- drv = self._driver
-
- drv._mounted_shares = [self.TEST_NFS_EXPORT1, self.TEST_NFS_EXPORT2]
-
- mox.StubOutWithMock(drv, '_get_available_capacity')
- drv._get_available_capacity(self.TEST_NFS_EXPORT1).\
- AndReturn(2 * self.ONE_GB_IN_BYTES)
- drv._get_available_capacity(self.TEST_NFS_EXPORT2).\
- AndReturn(3 * self.ONE_GB_IN_BYTES)
-
- mox.ReplayAll()
-
- self.assertEqual(self.TEST_NFS_EXPORT2,
- drv._find_share(self.TEST_SIZE_IN_GB))
-
- def test_find_share_should_throw_error_if_there_is_no_enough_place(self):
- """_find_share should throw error if there is no share to host vol"""
- mox = self.mox
- drv = self._driver
-
- drv._mounted_shares = [self.TEST_NFS_EXPORT1, self.TEST_NFS_EXPORT2]
-
- mox.StubOutWithMock(drv, '_get_available_capacity')
- drv._get_available_capacity(self.TEST_NFS_EXPORT1).\
- AndReturn(0)
- drv._get_available_capacity(self.TEST_NFS_EXPORT2).\
- AndReturn(0)
-
- mox.ReplayAll()
-
- self.assertRaises(exception.NfsNoSuitableShareFound, drv._find_share,
- self.TEST_SIZE_IN_GB)
-
- def _simple_volume(self):
- volume = DumbVolume()
- volume['provider_location'] = '127.0.0.1:/mnt'
- volume['name'] = 'volume_name'
- volume['size'] = 10
-
- return volume
-
- def test_create_sparsed_volume(self):
- mox = self.mox
- drv = self._driver
- volume = self._simple_volume()
-
- self.flags(nfs_sparsed_volumes=True)
-
- mox.StubOutWithMock(drv, '_create_sparsed_file')
- mox.StubOutWithMock(drv, '_set_rw_permissions_for_all')
-
- drv._create_sparsed_file(IgnoreArg(), IgnoreArg())
- drv._set_rw_permissions_for_all(IgnoreArg())
-
- mox.ReplayAll()
-
- drv._do_create_volume(volume)
-
- def test_create_nonsparsed_volume(self):
- mox = self.mox
- drv = self._driver
- volume = self._simple_volume()
-
- self.flags(nfs_sparsed_volumes=False)
-
- mox.StubOutWithMock(drv, '_create_regular_file')
- mox.StubOutWithMock(drv, '_set_rw_permissions_for_all')
-
- drv._create_regular_file(IgnoreArg(), IgnoreArg())
- drv._set_rw_permissions_for_all(IgnoreArg())
-
- mox.ReplayAll()
-
- drv._do_create_volume(volume)
-
- def test_create_volume_should_ensure_nfs_mounted(self):
- """create_volume should ensure shares provided in config are mounted"""
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(nfs, 'LOG')
- self.stub_out_not_replaying(drv, '_find_share')
- self.stub_out_not_replaying(drv, '_do_create_volume')
-
- mox.StubOutWithMock(drv, '_ensure_shares_mounted')
- drv._ensure_shares_mounted()
-
- mox.ReplayAll()
-
- volume = DumbVolume()
- volume['size'] = self.TEST_SIZE_IN_GB
- drv.create_volume(volume)
-
- def test_create_volume_should_return_provider_location(self):
- """create_volume should return provider_location with found share """
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(nfs, 'LOG')
- self.stub_out_not_replaying(drv, '_ensure_shares_mounted')
- self.stub_out_not_replaying(drv, '_do_create_volume')
-
- mox.StubOutWithMock(drv, '_find_share')
- drv._find_share(self.TEST_SIZE_IN_GB).AndReturn(self.TEST_NFS_EXPORT1)
-
- mox.ReplayAll()
-
- volume = DumbVolume()
- volume['size'] = self.TEST_SIZE_IN_GB
- result = drv.create_volume(volume)
- self.assertEqual(self.TEST_NFS_EXPORT1, result['provider_location'])
-
- def test_delete_volume(self):
- """delete_volume simple test case"""
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(drv, '_ensure_share_mounted')
-
- volume = DumbVolume()
- volume['name'] = 'volume-123'
- volume['provider_location'] = self.TEST_NFS_EXPORT1
-
- mox.StubOutWithMock(drv, 'local_path')
- drv.local_path(volume).AndReturn(self.TEST_LOCAL_PATH)
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_LOCAL_PATH).AndReturn(True)
-
- mox.StubOutWithMock(drv, '_execute')
- drv._execute('rm', '-f', self.TEST_LOCAL_PATH, run_as_root=True)
-
- mox.ReplayAll()
-
- drv.delete_volume(volume)
-
- def test_delete_should_ensure_share_mounted(self):
- """delete_volume should ensure that corresponding share is mounted"""
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(drv, '_execute')
-
- volume = DumbVolume()
- volume['name'] = 'volume-123'
- volume['provider_location'] = self.TEST_NFS_EXPORT1
-
- mox.StubOutWithMock(drv, '_ensure_share_mounted')
- drv._ensure_share_mounted(self.TEST_NFS_EXPORT1)
-
- mox.ReplayAll()
-
- drv.delete_volume(volume)
-
- def test_delete_should_not_delete_if_provider_location_not_provided(self):
- """delete_volume shouldn't try to delete if provider_location missed"""
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(drv, '_ensure_share_mounted')
-
- volume = DumbVolume()
- volume['name'] = 'volume-123'
- volume['provider_location'] = None
-
- mox.StubOutWithMock(drv, '_execute')
-
- mox.ReplayAll()
-
- drv.delete_volume(volume)
-
- def test_delete_should_not_delete_if_there_is_no_file(self):
- """delete_volume should not try to delete if file missed"""
- mox = self.mox
- drv = self._driver
-
- self.stub_out_not_replaying(drv, '_ensure_share_mounted')
-
- volume = DumbVolume()
- volume['name'] = 'volume-123'
- volume['provider_location'] = self.TEST_NFS_EXPORT1
-
- mox.StubOutWithMock(drv, 'local_path')
- drv.local_path(volume).AndReturn(self.TEST_LOCAL_PATH)
-
- mox.StubOutWithMock(drv, '_path_exists')
- drv._path_exists(self.TEST_LOCAL_PATH).AndReturn(False)
-
- mox.StubOutWithMock(drv, '_execute')
-
- mox.ReplayAll()
-
- drv.delete_volume(volume)
diff --git a/nova/tests/test_plugin_api_extensions.py b/nova/tests/test_plugin_api_extensions.py
index af30c10d1..a40dd3276 100644
--- a/nova/tests/test_plugin_api_extensions.py
+++ b/nova/tests/test_plugin_api_extensions.py
@@ -72,7 +72,6 @@ class APITestCase(test.TestCase):
# Marking out the default extension paths makes this test MUCH faster.
self.flags(osapi_compute_extension=[])
- self.flags(osapi_volume_extension=[])
found = False
mgr = computeextensions.ExtensionManager()
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index dd86c7c03..5ec753efe 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -127,27 +127,6 @@ class QuotaIntegrationTestCase(test.TestCase):
image_href=image_uuid)
db.instance_destroy(self.context, instance['uuid'])
- def test_too_many_volumes(self):
- volume_ids = []
- for i in range(FLAGS.quota_volumes):
- volume_id = self._create_volume()
- volume_ids.append(volume_id)
- self.assertRaises(exception.QuotaError,
- volume.API().create,
- self.context, 10, '', '', None)
- for volume_id in volume_ids:
- db.volume_destroy(self.context, volume_id)
-
- def test_too_many_gigabytes(self):
- volume_ids = []
- volume_id = self._create_volume(size=20)
- volume_ids.append(volume_id)
- self.assertRaises(exception.QuotaError,
- volume.API().create,
- self.context, 10, '', '', None)
- for volume_id in volume_ids:
- db.volume_destroy(self.context, volume_id)
-
def test_too_many_addresses(self):
address = '192.168.0.100'
db.floating_ip_create(context.get_admin_context(),
@@ -720,8 +699,6 @@ class DbQuotaDriverTestCase(test.TestCase):
self.flags(quota_instances=10,
quota_cores=20,
quota_ram=50 * 1024,
- quota_volumes=10,
- quota_gigabytes=1000,
quota_floating_ips=10,
quota_metadata_items=128,
quota_injected_files=5,
diff --git a/nova/tests/test_rbd.py b/nova/tests/test_rbd.py
deleted file mode 100644
index 8e90f3ae8..000000000
--- a/nova/tests/test_rbd.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 Josh Durgin
-# 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 db
-from nova import exception
-from nova.openstack.common import log as logging
-from nova.openstack.common import timeutils
-from nova import test
-from nova.tests.image import fake as fake_image
-from nova.tests.test_volume import DriverTestCase
-from nova.volume.driver import RBDDriver
-
-LOG = logging.getLogger(__name__)
-
-
-class RBDTestCase(test.TestCase):
-
- def setUp(self):
- super(RBDTestCase, self).setUp()
-
- def fake_execute(*args):
- pass
- self.driver = RBDDriver(execute=fake_execute)
-
- def test_good_locations(self):
- locations = [
- 'rbd://fsid/pool/image/snap',
- 'rbd://%2F/%2F/%2F/%2F',
- ]
- map(self.driver._parse_location, locations)
-
- def test_bad_locations(self):
- locations = [
- 'rbd://image',
- 'http://path/to/somewhere/else',
- 'rbd://image/extra',
- 'rbd://image/',
- 'rbd://fsid/pool/image/',
- 'rbd://fsid/pool/image/snap/',
- 'rbd://///',
- ]
- for loc in locations:
- self.assertRaises(exception.ImageUnacceptable,
- self.driver._parse_location,
- loc)
- self.assertFalse(self.driver._is_cloneable(loc))
-
- def test_cloneable(self):
- self.stubs.Set(self.driver, '_get_fsid', lambda: 'abc')
- location = 'rbd://abc/pool/image/snap'
- self.assertTrue(self.driver._is_cloneable(location))
-
- def test_uncloneable_different_fsid(self):
- self.stubs.Set(self.driver, '_get_fsid', lambda: 'abc')
- location = 'rbd://def/pool/image/snap'
- self.assertFalse(self.driver._is_cloneable(location))
-
- def test_uncloneable_unreadable(self):
- def fake_exc(*args):
- raise exception.ProcessExecutionError()
- self.stubs.Set(self.driver, '_get_fsid', lambda: 'abc')
- self.stubs.Set(self.driver, '_execute', fake_exc)
- location = 'rbd://abc/pool/image/snap'
- self.assertFalse(self.driver._is_cloneable(location))
-
-
-class FakeRBDDriver(RBDDriver):
-
- def _clone(self):
- pass
-
- def _resize(self):
- pass
-
-
-class ManagedRBDTestCase(DriverTestCase):
- driver_name = "nova.tests.test_rbd.FakeRBDDriver"
-
- def setUp(self):
- super(ManagedRBDTestCase, self).setUp()
- fake_image.stub_out_image_service(self.stubs)
-
- def _clone_volume_from_image(self, expected_status,
- clone_works=True):
- """Try to clone a volume from an image, and check the status
- afterwards"""
- def fake_clone_image(volume, image_location):
- pass
-
- def fake_clone_error(volume, image_location):
- raise exception.NovaException()
-
- self.stubs.Set(self.volume.driver, '_is_cloneable', lambda x: True)
- if clone_works:
- self.stubs.Set(self.volume.driver, 'clone_image', fake_clone_image)
- else:
- self.stubs.Set(self.volume.driver, 'clone_image', fake_clone_error)
-
- image_id = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
- volume_id = 1
- # creating volume testdata
- db.volume_create(self.context, {'id': volume_id,
- 'updated_at': timeutils.utcnow(),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'creating',
- 'instance_uuid': None,
- 'host': 'dummy'})
- try:
- if clone_works:
- self.volume.create_volume(self.context,
- volume_id,
- image_id=image_id)
- else:
- self.assertRaises(exception.NovaException,
- self.volume.create_volume,
- self.context,
- volume_id,
- image_id=image_id)
-
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], expected_status)
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
-
- def test_clone_image_status_available(self):
- """Verify that before cloning, an image is in the available state."""
- self._clone_volume_from_image('available', True)
-
- def test_clone_image_status_error(self):
- """Verify that before cloning, an image is in the available state."""
- self._clone_volume_from_image('error', False)
-
- def test_clone_success(self):
- self.stubs.Set(self.volume.driver, '_is_cloneable', lambda x: True)
- self.stubs.Set(self.volume.driver, 'clone_image', lambda a, b: True)
- image_id = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
- self.assertTrue(self.volume.driver.clone_image({}, image_id))
-
- def test_clone_bad_image_id(self):
- self.stubs.Set(self.volume.driver, '_is_cloneable', lambda x: True)
- self.assertFalse(self.volume.driver.clone_image({}, None))
-
- def test_clone_uncloneable(self):
- self.stubs.Set(self.volume.driver, '_is_cloneable', lambda x: False)
- self.assertFalse(self.volume.driver.clone_image({}, 'dne'))
diff --git a/nova/tests/test_solidfire.py b/nova/tests/test_solidfire.py
deleted file mode 100644
index 87a211da5..000000000
--- a/nova/tests/test_solidfire.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack LLC.
-# 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 exception
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume.solidfire import SolidFire
-
-LOG = logging.getLogger(__name__)
-
-
-class SolidFireVolumeTestCase(test.TestCase):
- def fake_issue_api_request(obj, method, params):
- if method is 'GetClusterInfo':
- LOG.info('Called Fake GetClusterInfo...')
- results = {'result': {'clusterInfo':
- {'name': 'fake-cluster',
- 'mvip': '1.1.1.1',
- 'svip': '1.1.1.1',
- 'uniqueID': 'unqid',
- 'repCount': 2,
- 'attributes': {}}}}
- return results
-
- elif method is 'AddAccount':
- LOG.info('Called Fake AddAccount...')
- return {'result': {'accountID': 25}, 'id': 1}
-
- elif method is 'GetAccountByName':
- LOG.info('Called Fake GetAccountByName...')
- results = {'result': {'account':
- {'accountID': 25,
- 'username': params['username'],
- 'status': 'active',
- 'initiatorSecret': '123456789012',
- 'targetSecret': '123456789012',
- 'attributes': {},
- 'volumes': [6, 7, 20]}},
- "id": 1}
- return results
-
- elif method is 'CreateVolume':
- LOG.info('Called Fake CreateVolume...')
- return {'result': {'volumeID': 5}, 'id': 1}
-
- elif method is 'DeleteVolume':
- LOG.info('Called Fake DeleteVolume...')
- return {'result': {}, 'id': 1}
-
- elif method is 'ListVolumesForAccount':
- test_name = 'OS-VOLID-a720b3c0-d1f0-11e1-9b23-0800200c9a66'
- LOG.info('Called Fake ListVolumesForAccount...')
- result = {'result': {
- 'volumes': [{'volumeID': 5,
- 'name': test_name,
- 'accountID': 25,
- 'sliceCount': 1,
- 'totalSize': 1048576 * 1024,
- 'enable512e': True,
- 'access': "readWrite",
- 'status': "active",
- 'attributes':None,
- 'qos': None,
- 'iqn': test_name}]}}
- return result
-
- else:
- LOG.error('Crap, unimplemented API call in Fake:%s' % method)
-
- def fake_issue_api_request_no_volume(obj, method, params):
- if method is 'ListVolumesForAccount':
- LOG.info('Called Fake ListVolumesForAccount...')
- return {'result': {'volumes': []}}
- else:
- return obj.fake_issue_api_request(method, params)
-
- def fake_issue_api_request_fails(obj, method, params):
- return {'error': {'code': 000,
- 'name': 'DummyError',
- 'message': 'This is a fake error response'},
- 'id': 1}
-
- def fake_volume_get(obj, key, default=None):
- return {'qos': 'fast'}
-
- def test_create_volume(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
- testvol = {'project_id': 'testprjid',
- 'name': 'testvol',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
- sfv = SolidFire()
- model_update = sfv.create_volume(testvol)
-
- def test_create_volume_with_qos(self):
- preset_qos = {}
- preset_qos['qos'] = 'fast'
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
-
- testvol = {'project_id': 'testprjid',
- 'name': 'testvol',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
- 'metadata': [preset_qos]}
-
- sfv = SolidFire()
- model_update = sfv.create_volume(testvol)
-
- def test_create_volume_fails(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_fails)
- testvol = {'project_id': 'testprjid',
- 'name': 'testvol',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
- sfv = SolidFire()
- self.assertRaises(exception.SolidFireAPIDataException,
- sfv.create_volume, testvol)
-
- def test_create_sfaccount(self):
- sfv = SolidFire()
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
- account = sfv._create_sfaccount('project-id')
- self.assertNotEqual(account, None)
-
- def test_create_sfaccount_fails(self):
- sfv = SolidFire()
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_fails)
- account = sfv._create_sfaccount('project-id')
- self.assertEqual(account, None)
-
- def test_get_sfaccount_by_name(self):
- sfv = SolidFire()
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
- account = sfv._get_sfaccount_by_name('some-name')
- self.assertNotEqual(account, None)
-
- def test_get_sfaccount_by_name_fails(self):
- sfv = SolidFire()
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_fails)
- account = sfv._get_sfaccount_by_name('some-name')
- self.assertEqual(account, None)
-
- def test_delete_volume(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
- testvol = {'project_id': 'testprjid',
- 'name': 'test_volume',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
- sfv = SolidFire()
- model_update = sfv.delete_volume(testvol)
-
- def test_delete_volume_fails_no_volume(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_no_volume)
- testvol = {'project_id': 'testprjid',
- 'name': 'no-name',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
- sfv = SolidFire()
- self.assertRaises(exception.VolumeNotFound,
- sfv.delete_volume, testvol)
-
- def test_delete_volume_fails_account_lookup(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_fails)
- testvol = {'project_id': 'testprjid',
- 'name': 'no-name',
- 'size': 1,
- 'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66'}
- sfv = SolidFire()
- self.assertRaises(exception.SfAccountNotFound,
- sfv.delete_volume,
- testvol)
-
- def test_get_cluster_info(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request)
- sfv = SolidFire()
- sfv._get_cluster_info()
-
- def test_get_cluster_info_fail(self):
- self.stubs.Set(SolidFire, '_issue_api_request',
- self.fake_issue_api_request_fails)
- sfv = SolidFire()
- self.assertRaises(exception.SolidFireAPIException,
- sfv._get_cluster_info)
diff --git a/nova/tests/test_storwize_svc.py b/nova/tests/test_storwize_svc.py
deleted file mode 100644
index 513043256..000000000
--- a/nova/tests/test_storwize_svc.py
+++ /dev/null
@@ -1,1376 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2012 IBM, Inc.
-# Copyright (c) 2012 OpenStack LLC.
-# 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.
-#
-# Authors:
-# Ronen Kat <ronenkat@il.ibm.com>
-# Avishay Traeger <avishay@il.ibm.com>
-
-"""
-Tests for the IBM Storwize V7000 and SVC volume driver.
-"""
-
-import random
-import socket
-
-from nova import exception
-from nova import flags
-from nova.openstack.common import excutils
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume import storwize_svc
-
-FLAGS = flags.FLAGS
-
-LOG = logging.getLogger(__name__)
-
-
-class StorwizeSVCManagementSimulator:
- def __init__(self, pool_name):
- self._flags = {"storwize_svc_volpool_name": pool_name}
- self._volumes_list = {}
- self._hosts_list = {}
- self._mappings_list = {}
- self._fcmappings_list = {}
- self._next_cmd_error = {
- "lsportip": "",
- "lsnodecanister": "",
- "mkvdisk": "",
- "lsvdisk": "",
- "lsfcmap": "",
- "prestartfcmap": "",
- "startfcmap": "",
- "rmfcmap": "",
- }
- self._errors = {
- "CMMVC5701E": ("", "CMMVC5701E No object ID was specified."),
- "CMMVC6035E": ("", "CMMVC6035E The action failed as the " +
- "object already exists."),
- "CMMVC5753E": ("", "CMMVC5753E The specified object does not " +
- "exist or is not a suitable candidate."),
- "CMMVC5707E": ("", "CMMVC5707E Required parameters are missing."),
- "CMMVC6581E": ("", "CMMVC6581E The command has failed because " +
- "the maximum number of allowed iSCSI " +
- "qualified names (IQNs) has been reached, " +
- "or the IQN is already assigned or is not " +
- "valid."),
- "CMMVC5754E": ("", "CMMVC5754E The specified object does not " +
- "exist, or the name supplied does not meet " +
- "the naming rules."),
- "CMMVC6071E": ("", "CMMVC6071E The VDisk-to-host mapping was " +
- "not created because the VDisk is already " +
- "mapped to a host."),
- "CMMVC5879E": ("", "CMMVC5879E The VDisk-to-host mapping was " +
- "not created because a VDisk is already " +
- "mapped to this host with this SCSI LUN."),
- "CMMVC5840E": ("", "CMMVC5840E The virtual disk (VDisk) was " +
- "not deleted because it is mapped to a " +
- "host or because it is part of a FlashCopy " +
- "or Remote Copy mapping, or is involved in " +
- "an image mode migrate."),
- "CMMVC6527E": ("", "CMMVC6527E The name that you have entered " +
- "is not valid. The name can contain letters, " +
- "numbers, spaces, periods, dashes, and " +
- "underscores. The name must begin with a " +
- "letter or an underscore. The name must not " +
- "begin or end with a space."),
- "CMMVC5871E": ("", "CMMVC5871E The action failed because one or " +
- "more of the configured port names is in a " +
- "mapping."),
- "CMMVC5924E": ("", "CMMVC5924E The FlashCopy mapping was not " +
- "created because the source and target " +
- "virtual disks (VDisks) are different sizes."),
- "CMMVC6303E": ("", "CMMVC6303E The create failed because the " +
- "source and target VDisks are the same."),
- "CMMVC7050E": ("", "CMMVC7050E The command failed because at " +
- "least one node in the I/O group does not " +
- "support compressed VDisks."),
- }
-
- # Find an unused ID
- def _find_unused_id(self, d):
- ids = []
- for k, v in d.iteritems():
- ids.append(int(v["id"]))
- ids.sort()
- for index, n in enumerate(ids):
- if n > index:
- return str(index)
- return str(len(ids))
-
- # Check if name is valid
- def _is_invalid_name(self, name):
- if (name[0] == " ") or (name[-1] == " "):
- return True
- for c in name:
- if ((not c.isalnum()) and (c != " ") and (c != ".")
- and (c != "-") and (c != "_")):
- return True
- return False
-
- # Convert argument string to dictionary
- def _cmd_to_dict(self, cmd):
- arg_list = cmd.split()
- no_param_args = [
- "autodelete",
- "autoexpand",
- "bytes",
- "compressed",
- "force",
- "nohdr",
- ]
- one_param_args = [
- "cleanrate",
- "delim",
- "filtervalue",
- "grainsize",
- "host",
- "iogrp",
- "iscsiname",
- "mdiskgrp",
- "name",
- "rsize",
- "scsi",
- "size",
- "source",
- "target",
- "unit",
- "easytier",
- "warning",
- ]
-
- # Handle the special case of lsnode which is a two-word command
- # Use the one word version of the command internally
- if arg_list[0] == "svcinfo" and arg_list[1] == "lsnode":
- ret = {"cmd": "lsnodecanister"}
- arg_list.pop(0)
- else:
- ret = {"cmd": arg_list[0]}
-
- skip = False
- for i in range(1, len(arg_list)):
- if skip:
- skip = False
- continue
- if arg_list[i][0] == "-":
- if arg_list[i][1:] in no_param_args:
- ret[arg_list[i][1:]] = True
- elif arg_list[i][1:] in one_param_args:
- ret[arg_list[i][1:]] = arg_list[i + 1]
- skip = True
- else:
- raise exception.InvalidInput(
- reason=_('unrecognized argument %s') % arg_list[i])
- else:
- ret["obj"] = arg_list[i]
- return ret
-
- # Generic function for printing information
- def _print_info_cmd(self, rows, delim=" ", nohdr=False, **kwargs):
- if nohdr:
- del rows[0]
-
- for index in range(len(rows)):
- rows[index] = delim.join(rows[index])
- return ("%s" % "\n".join(rows), "")
-
- # Print mostly made-up stuff in the correct syntax
- def _cmd_lsmdiskgrp(self, **kwargs):
- rows = [None] * 3
- rows[0] = ["id", "name", "status", "mdisk_count",
- "vdisk_count capacity", "extent_size", "free_capacity",
- "virtual_capacity", "used_capacity", "real_capacity",
- "overallocation", "warning", "easy_tier",
- "easy_tier_status"]
- rows[1] = ["1", self._flags["storwize_svc_volpool_name"], "online",
- "1", str(len(self._volumes_list)), "3.25TB", "256",
- "3.21TB", "1.54TB", "264.97MB", "35.58GB", "47", "80",
- "auto", "inactive"]
- rows[2] = ["2", "volpool2", "online",
- "1", "0", "3.25TB", "256",
- "3.21TB", "1.54TB", "264.97MB", "35.58GB", "47", "80",
- "auto", "inactive"]
- return self._print_info_cmd(rows=rows, **kwargs)
-
- # Print mostly made-up stuff in the correct syntax
- def _cmd_lsnodecanister(self, **kwargs):
- rows = [None] * 3
- rows[0] = ["id", "name", "UPS_serial_number", "WWNN", "status",
- "IO_group_id", "IO_group_name", "config_node",
- "UPS_unique_id", "hardware", "iscsi_name", "iscsi_alias",
- "panel_name", "enclosure_id", "canister_id",
- "enclosure_serial_number"]
- rows[1] = ["5", "node1", "", "123456789ABCDEF0", "online", "0",
- "io_grp0",
- "yes", "123456789ABCDEF0", "100",
- "iqn.1982-01.com.ibm:1234.sim.node1", "", "01-1", "1", "1",
- "0123ABC"]
- rows[2] = ["6", "node2", "", "123456789ABCDEF1", "online", "0",
- "io_grp0",
- "no", "123456789ABCDEF1", "100",
- "iqn.1982-01.com.ibm:1234.sim.node2", "", "01-2", "1", "2",
- "0123ABC"]
-
- if self._next_cmd_error["lsnodecanister"] == "header_mismatch":
- rows[0].pop(2)
- self._next_cmd_error["lsnodecanister"] = ""
- if self._next_cmd_error["lsnodecanister"] == "remove_field":
- for row in rows:
- row.pop(0)
- self._next_cmd_error["lsnodecanister"] = ""
-
- return self._print_info_cmd(rows=rows, **kwargs)
-
- # Print mostly made-up stuff in the correct syntax
- def _cmd_lsportip(self, **kwargs):
- if self._next_cmd_error["lsportip"] == "ip_no_config":
- self._next_cmd_error["lsportip"] = ""
- ip_addr1 = ""
- ip_addr2 = ""
- gw = ""
- else:
- ip_addr1 = "1.234.56.78"
- ip_addr2 = "1.234.56.79"
- gw = "1.234.56.1"
-
- rows = [None] * 17
- rows[0] = ["id", "node_id", "node_name", "IP_address", "mask",
- "gateway", "IP_address_6", "prefix_6", "gateway_6", "MAC",
- "duplex", "state", "speed", "failover"]
- rows[1] = ["1", "5", "node1", ip_addr1, "255.255.255.0",
- gw, "", "", "", "01:23:45:67:89:00", "Full",
- "online", "1Gb/s", "no"]
- rows[2] = ["1", "5", "node1", "", "", "", "", "", "",
- "01:23:45:67:89:00", "Full", "online", "1Gb/s", "yes"]
- rows[3] = ["2", "5", "node1", "", "", "", "", "", "",
- "01:23:45:67:89:01", "Full", "unconfigured", "1Gb/s", "no"]
- rows[4] = ["2", "5", "node1", "", "", "", "", "", "",
- "01:23:45:67:89:01", "Full", "unconfigured", "1Gb/s", "yes"]
- rows[5] = ["3", "5", "node1", "", "", "", "", "", "", "", "",
- "unconfigured", "", "no"]
- rows[6] = ["3", "5", "node1", "", "", "", "", "", "", "", "",
- "unconfigured", "", "yes"]
- rows[7] = ["4", "5", "node1", "", "", "", "", "", "", "", "",
- "unconfigured", "", "no"]
- rows[8] = ["4", "5", "node1", "", "", "", "", "", "", "", "",
- "unconfigured", "", "yes"]
- rows[9] = ["1", "6", "node2", ip_addr2, "255.255.255.0",
- gw, "", "", "", "01:23:45:67:89:02", "Full",
- "online", "1Gb/s", "no"]
- rows[10] = ["1", "6", "node2", "", "", "", "", "", "",
- "01:23:45:67:89:02", "Full", "online", "1Gb/s", "yes"]
- rows[11] = ["2", "6", "node2", "", "", "", "", "", "",
- "01:23:45:67:89:03", "Full", "unconfigured", "1Gb/s", "no"]
- rows[12] = ["2", "6", "node2", "", "", "", "", "", "",
- "01:23:45:67:89:03", "Full", "unconfigured", "1Gb/s",
- "yes"]
- rows[13] = ["3", "6", "node2", "", "", "", "", "", "", "", "",
- "unconfigured", "", "no"]
- rows[14] = ["3", "6", "node2", "", "", "", "", "", "", "", "",
- "unconfigured", "", "yes"]
- rows[15] = ["4", "6", "node2", "", "", "", "", "", "", "", "",
- "unconfigured", "", "no"]
- rows[16] = ["4", "6", "node2", "", "", "", "", "", "", "", "",
- "unconfigured", "", "yes"]
-
- if self._next_cmd_error["lsportip"] == "header_mismatch":
- rows[0].pop(2)
- self._next_cmd_error["lsportip"] = ""
- if self._next_cmd_error["lsportip"] == "remove_field":
- for row in rows:
- row.pop(1)
- self._next_cmd_error["lsportip"] = ""
-
- return self._print_info_cmd(rows=rows, **kwargs)
-
- # Create a vdisk
- def _cmd_mkvdisk(self, **kwargs):
- # We only save the id/uid, name, and size - all else will be made up
- volume_info = {}
- volume_info["id"] = self._find_unused_id(self._volumes_list)
- volume_info["uid"] = ("ABCDEF" * 3) + ("0" * 14) + volume_info["id"]
-
- if "name" in kwargs:
- volume_info["name"] = kwargs["name"].strip('\'\"')
- else:
- volume_info["name"] = "vdisk" + volume_info["id"]
-
- # Assume size and unit are given, store it in bytes
- capacity = int(kwargs["size"])
- unit = kwargs["unit"]
-
- if unit == "b":
- cap_bytes = capacity
- elif unit == "kb":
- cap_bytes = capacity * pow(1024, 1)
- elif unit == "mb":
- cap_bytes = capacity * pow(1024, 2)
- elif unit == "gb":
- cap_bytes = capacity * pow(1024, 3)
- elif unit == "tb":
- cap_bytes = capacity * pow(1024, 4)
- elif unit == "pb":
- cap_bytes = capacity * pow(1024, 5)
- volume_info["cap_bytes"] = str(cap_bytes)
- volume_info["capacity"] = str(capacity) + unit.upper()
-
- if "easytier" in kwargs:
- if kwargs["easytier"] == "on":
- volume_info["easy_tier"] = "on"
- else:
- volume_info["easy_tier"] = "off"
-
- if "rsize" in kwargs:
- # Fake numbers
- volume_info["used_capacity"] = "0.75MB"
- volume_info["real_capacity"] = "36.98MB"
- volume_info["free_capacity"] = "36.23MB"
- volume_info["used_capacity_bytes"] = "786432"
- volume_info["real_capacity_bytes"] = "38776340"
- volume_info["free_capacity_bytes"] = "37989908"
- if "warning" in kwargs:
- volume_info["warning"] = kwargs["warning"].rstrip('%')
- else:
- volume_info["warning"] = "80"
- if "autoexpand" in kwargs:
- volume_info["autoexpand"] = "on"
- else:
- volume_info["autoexpand"] = "off"
- if "grainsize" in kwargs:
- volume_info["grainsize"] = kwargs["grainsize"]
- else:
- volume_info["grainsize"] = "32"
- if "compressed" in kwargs:
- if self._next_cmd_error["mkvdisk"] == "no_compression":
- self._next_cmd_error["mkvdisk"] = ""
- return self._errors["CMMVC7050E"]
- volume_info["compressed_copy"] = "yes"
- else:
- volume_info["compressed_copy"] = "no"
- else:
- volume_info["used_capacity"] = volume_info["capacity"]
- volume_info["real_capacity"] = volume_info["capacity"]
- volume_info["free_capacity"] = "0.00MB"
- volume_info["used_capacity_bytes"] = volume_info["cap_bytes"]
- volume_info["real_capacity_bytes"] = volume_info["cap_bytes"]
- volume_info["free_capacity_bytes"] = "0"
- volume_info["warning"] = ""
- volume_info["autoexpand"] = ""
- volume_info["grainsize"] = ""
- volume_info["compressed_copy"] = "no"
-
- if volume_info["name"] in self._volumes_list:
- return self._errors["CMMVC6035E"]
- else:
- self._volumes_list[volume_info["name"]] = volume_info
- return ("Virtual Disk, id [%s], successfully created" %
- (volume_info["id"]), "")
-
- # Delete a vdisk
- def _cmd_rmvdisk(self, **kwargs):
- force = 0
- if "force" in kwargs:
- force = 1
-
- if "obj" not in kwargs:
- return self._errors["CMMVC5701E"]
- vol_name = kwargs["obj"].strip('\'\"')
-
- if not vol_name in self._volumes_list:
- return self._errors["CMMVC5753E"]
-
- if force == 0:
- for k, mapping in self._mappings_list.iteritems():
- if mapping["vol"] == vol_name:
- return self._errors["CMMVC5840E"]
- for k, fcmap in self._fcmappings_list.iteritems():
- if ((fcmap["source"] == vol_name) or
- (fcmap["target"] == vol_name)):
- return self._errors["CMMVC5840E"]
-
- del self._volumes_list[vol_name]
- return ("", "")
-
- def _get_fcmap_info(self, vol_name):
- ret_vals = {
- "fc_id": "",
- "fc_name": "",
- "fc_map_count": "0",
- }
- for k, fcmap in self._fcmappings_list.iteritems():
- if ((fcmap["source"] == vol_name) or
- (fcmap["target"] == vol_name)):
- ret_vals["fc_id"] = fcmap["id"]
- ret_vals["fc_name"] = fcmap["name"]
- ret_vals["fc_map_count"] = "1"
- return ret_vals
-
- # List information about vdisks
- def _cmd_lsvdisk(self, **kwargs):
- if "obj" not in kwargs:
- rows = []
- rows.append(["id", "name", "IO_group_id", "IO_group_name",
- "status", "mdisk_grp_id", "mdisk_grp_name",
- "capacity", "type", "FC_id", "FC_name", "RC_id",
- "RC_name", "vdisk_UID", "fc_map_count", "copy_count",
- "fast_write_state", "se_copy_count", "RC_change"])
-
- for k, vol in self._volumes_list.iteritems():
- if (("filtervalue" not in kwargs) or
- (kwargs["filtervalue"] == "name=" + vol["name"])):
- fcmap_info = self._get_fcmap_info(vol["name"])
-
- if "bytes" in kwargs:
- cap = vol["cap_bytes"]
- else:
- cap = vol["capacity"]
- rows.append([str(vol["id"]), vol["name"], "0", "io_grp0",
- "online", "0",
- self._flags["storwize_svc_volpool_name"],
- cap, "striped",
- fcmap_info["fc_id"], fcmap_info["fc_name"],
- "", "", vol["uid"],
- fcmap_info["fc_map_count"], "1", "empty",
- "1", "no"])
-
- return self._print_info_cmd(rows=rows, **kwargs)
-
- else:
- if kwargs["obj"] not in self._volumes_list:
- return self._errors["CMMVC5754E"]
- vol = self._volumes_list[kwargs["obj"]]
- fcmap_info = self._get_fcmap_info(vol["name"])
- if "bytes" in kwargs:
- cap = vol["cap_bytes"]
- cap_u = vol["used_capacity_bytes"]
- cap_r = vol["real_capacity_bytes"]
- cap_f = vol["free_capacity_bytes"]
- else:
- cap = vol["capacity"]
- cap_u = vol["used_capacity"]
- cap_r = vol["real_capacity"]
- cap_f = vol["free_capacity"]
- rows = []
-
- rows.append(["id", str(vol["id"])])
- rows.append(["name", vol["name"]])
- rows.append(["IO_group_id", "0"])
- rows.append(["IO_group_name", "io_grp0"])
- rows.append(["status", "online"])
- rows.append(["mdisk_grp_id", "0"])
- rows.append(["mdisk_grp_name",
- self._flags["storwize_svc_volpool_name"]])
- rows.append(["capacity", cap])
- rows.append(["type", "striped"])
- rows.append(["formatted", "no"])
- rows.append(["mdisk_id", ""])
- rows.append(["mdisk_name", ""])
- rows.append(["FC_id", fcmap_info["fc_id"]])
- rows.append(["FC_name", fcmap_info["fc_name"]])
- rows.append(["RC_id", ""])
- rows.append(["RC_name", ""])
- rows.append(["vdisk_UID", vol["uid"]])
- rows.append(["throttling", "0"])
-
- if self._next_cmd_error["lsvdisk"] == "blank_pref_node":
- rows.append(["preferred_node_id", ""])
- self._next_cmd_error["lsvdisk"] = ""
- elif self._next_cmd_error["lsvdisk"] == "no_pref_node":
- self._next_cmd_error["lsvdisk"] = ""
- else:
- rows.append(["preferred_node_id", "6"])
- rows.append(["fast_write_state", "empty"])
- rows.append(["cache", "readwrite"])
- rows.append(["udid", ""])
- rows.append(["fc_map_count", fcmap_info["fc_map_count"]])
- rows.append(["sync_rate", "50"])
- rows.append(["copy_count", "1"])
- rows.append(["se_copy_count", "0"])
- rows.append(["mirror_write_priority", "latency"])
- rows.append(["RC_change", "no"])
- rows.append(["used_capacity", cap_u])
- rows.append(["real_capacity", cap_r])
- rows.append(["free_capacity", cap_f])
- rows.append(["autoexpand", vol["autoexpand"]])
- rows.append(["warning", vol["warning"]])
- rows.append(["grainsize", vol["grainsize"]])
- rows.append(["easy_tier", vol["easy_tier"]])
- rows.append(["compressed_copy", vol["compressed_copy"]])
-
- if "nohdr" in kwargs:
- for index in range(len(rows)):
- rows[index] = " ".join(rows[index][1:])
-
- if "delim" in kwargs:
- for index in range(len(rows)):
- rows[index] = kwargs["delim"].join(rows[index])
-
- return ("%s" % "\n".join(rows), "")
-
- # Make a host
- def _cmd_mkhost(self, **kwargs):
- host_info = {}
- host_info["id"] = self._find_unused_id(self._hosts_list)
-
- if "name" in kwargs:
- host_name = kwargs["name"].strip('\'\"')
- else:
- host_name = "host" + str(host_info["id"])
- host_info["host_name"] = host_name
-
- if "iscsiname" not in kwargs:
- return self._errors["CMMVC5707E"]
- host_info["iscsi_name"] = kwargs["iscsiname"].strip('\'\"')
-
- if self._is_invalid_name(host_name):
- return self._errors["CMMVC6527E"]
-
- if host_name in self._hosts_list:
- return self._errors["CMMVC6035E"]
-
- for k, v in self._hosts_list.iteritems():
- if v["iscsi_name"] == host_info["iscsi_name"]:
- return self._errors["CMMVC6581E"]
-
- self._hosts_list[host_name] = host_info
- return ("Host, id [%s], successfully created" %
- (host_info["id"]), "")
-
- # Remove a host
- def _cmd_rmhost(self, **kwargs):
- if "obj" not in kwargs:
- return self._errors["CMMVC5701E"]
-
- host_name = kwargs["obj"].strip('\'\"')
- if host_name not in self._hosts_list:
- return self._errors["CMMVC5753E"]
-
- for k, v in self._mappings_list.iteritems():
- if (v["host"] == host_name):
- return self._errors["CMMVC5871E"]
-
- del self._hosts_list[host_name]
- return ("", "")
-
- # List information about hosts
- def _cmd_lshost(self, **kwargs):
- if "obj" not in kwargs:
- rows = []
- rows.append(["id", "name", "port_count", "iogrp_count", "status"])
-
- found = False
- for k, host in self._hosts_list.iteritems():
- filterstr = "name=" + host["host_name"]
- if (("filtervalue" not in kwargs) or
- (kwargs["filtervalue"] == filterstr)):
- rows.append([host["id"], host["host_name"], "1", "4",
- "offline"])
- found = True
- if found:
- return self._print_info_cmd(rows=rows, **kwargs)
- else:
- return ("", "")
- else:
- if kwargs["obj"] not in self._hosts_list:
- return self._errors["CMMVC5754E"]
- host = self._hosts_list[kwargs["obj"]]
- rows = []
- rows.append(["id", host["id"]])
- rows.append(["name", host["host_name"]])
- rows.append(["port_count", "1"])
- rows.append(["type", "generic"])
- rows.append(["mask", "1111"])
- rows.append(["iogrp_count", "4"])
- rows.append(["status", "offline"])
- rows.append(["iscsi_name", host["iscsi_name"]])
- rows.append(["node_logged_in_count", "0"])
- rows.append(["state", "offline"])
-
- if "nohdr" in kwargs:
- for index in range(len(rows)):
- rows[index] = " ".join(rows[index][1:])
-
- if "delim" in kwargs:
- for index in range(len(rows)):
- rows[index] = kwargs["delim"].join(rows[index])
-
- return ("%s" % "\n".join(rows), "")
-
- # Create a vdisk-host mapping
- def _cmd_mkvdiskhostmap(self, **kwargs):
- mapping_info = {}
- mapping_info["id"] = self._find_unused_id(self._mappings_list)
-
- if "host" not in kwargs:
- return self._errors["CMMVC5707E"]
- mapping_info["host"] = kwargs["host"].strip('\'\"')
-
- if "scsi" not in kwargs:
- return self._errors["CMMVC5707E"]
- mapping_info["lun"] = kwargs["scsi"].strip('\'\"')
-
- if "obj" not in kwargs:
- return self._errors["CMMVC5707E"]
- mapping_info["vol"] = kwargs["obj"].strip('\'\"')
-
- if not mapping_info["vol"] in self._volumes_list:
- return self._errors["CMMVC5753E"]
-
- if not mapping_info["host"] in self._hosts_list:
- return self._errors["CMMVC5754E"]
-
- if mapping_info["vol"] in self._mappings_list:
- return self._errors["CMMVC6071E"]
-
- for k, v in self._mappings_list.iteritems():
- if ((v["host"] == mapping_info["host"]) and
- (v["lun"] == mapping_info["lun"])):
- return self._errors["CMMVC5879E"]
-
- self._mappings_list[mapping_info["vol"]] = mapping_info
- return ("Virtual Disk to Host map, id [%s], successfully created"
- % (mapping_info["id"]), "")
-
- # Delete a vdisk-host mapping
- def _cmd_rmvdiskhostmap(self, **kwargs):
- if "host" not in kwargs:
- return self._errors["CMMVC5707E"]
- host = kwargs["host"].strip('\'\"')
-
- if "obj" not in kwargs:
- return self._errors["CMMVC5701E"]
- vol = kwargs["obj"].strip('\'\"')
-
- if not vol in self._mappings_list:
- return self._errors["CMMVC5753E"]
-
- if self._mappings_list[vol]["host"] != host:
- return self._errors["CMMVC5753E"]
-
- del self._mappings_list[vol]
- return ("", "")
-
- # List information about vdisk-host mappings
- def _cmd_lshostvdiskmap(self, **kwargs):
- index = 1
- no_hdr = 0
- delimeter = ""
- host_name = kwargs["obj"]
-
- if host_name not in self._hosts_list:
- return self._errors["CMMVC5754E"]
-
- rows = []
- rows.append(["id", "name", "SCSI_id", "vdisk_id", "vdisk_name",
- "vdisk_UID"])
-
- for k, mapping in self._mappings_list.iteritems():
- if (host_name == "") or (mapping["host"] == host_name):
- volume = self._volumes_list[mapping["vol"]]
- rows.append([mapping["id"], mapping["host"],
- mapping["lun"], volume["id"],
- volume["name"], volume["uid"]])
-
- return self._print_info_cmd(rows=rows, **kwargs)
-
- # Create a FlashCopy mapping
- def _cmd_mkfcmap(self, **kwargs):
- source = ""
- target = ""
-
- if "source" not in kwargs:
- return self._errors["CMMVC5707E"]
- source = kwargs["source"].strip('\'\"')
- if not source in self._volumes_list:
- return self._errors["CMMVC5754E"]
-
- if "target" not in kwargs:
- return self._errors["CMMVC5707E"]
- target = kwargs["target"].strip('\'\"')
- if not target in self._volumes_list:
- return self._errors["CMMVC5754E"]
-
- if source == target:
- return self._errors["CMMVC6303E"]
-
- if (self._volumes_list[source]["cap_bytes"] !=
- self._volumes_list[target]["cap_bytes"]):
- return self._errors["CMMVC5924E"]
-
- fcmap_info = {}
- fcmap_info["source"] = source
- fcmap_info["target"] = target
- fcmap_info["id"] = self._find_unused_id(self._fcmappings_list)
- fcmap_info["name"] = "fcmap" + fcmap_info["id"]
- fcmap_info["status"] = "idle_or_copied"
- fcmap_info["progress"] = "0"
- self._fcmappings_list[target] = fcmap_info
-
- return("FlashCopy Mapping, id [" + fcmap_info["id"] +
- "], successfully created", "")
-
- # Same function used for both prestartfcmap and startfcmap
- def _cmd_gen_startfcmap(self, mode, **kwargs):
- if "obj" not in kwargs:
- return self._errors["CMMVC5701E"]
- id_num = kwargs["obj"]
-
- if mode == "pre":
- if self._next_cmd_error["prestartfcmap"] == "bad_id":
- id_num = -1
- self._next_cmd_error["prestartfcmap"] = ""
- else:
- if self._next_cmd_error["startfcmap"] == "bad_id":
- id_num = -1
- self._next_cmd_error["startfcmap"] = ""
-
- for k, fcmap in self._fcmappings_list.iteritems():
- if fcmap["id"] == id_num:
- if mode == "pre":
- fcmap["status"] = "preparing"
- else:
- fcmap["status"] = "copying"
- fcmap["progress"] = "0"
- return ("", "")
- return self._errors["CMMVC5753E"]
-
- # Same function used for both stopfcmap and rmfcmap
- # Assumes it is called with "-force <fc_map_id>"
- def _cmd_stoprmfcmap(self, mode, **kwargs):
- if "obj" not in kwargs:
- return self._errors["CMMVC5701E"]
- id_num = kwargs["obj"]
-
- if self._next_cmd_error["rmfcmap"] == "bad_id":
- id_num = -1
- self._next_cmd_error["rmfcmap"] = ""
-
- to_delete = None
- found = False
- for k, fcmap in self._fcmappings_list.iteritems():
- if fcmap["id"] == id_num:
- found = True
- if mode == "rm":
- to_delete = k
-
- if to_delete:
- del self._fcmappings_list[to_delete]
-
- if found:
- return ("", "")
- else:
- return self._errors["CMMVC5753E"]
-
- def _cmd_lsfcmap(self, **kwargs):
- rows = []
- rows.append(["id", "name", "source_vdisk_id", "source_vdisk_name",
- "target_vdisk_id", "target_vdisk_name", "group_id",
- "group_name", "status", "progress", "copy_rate",
- "clean_progress", "incremental", "partner_FC_id",
- "partner_FC_name", "restoring", "start_time",
- "rc_controlled"])
-
- # Assume we always get a filtervalue argument
- filter_key = kwargs["filtervalue"].split("=")[0]
- filter_value = kwargs["filtervalue"].split("=")[1]
- to_delete = []
- for k, v in self._fcmappings_list.iteritems():
- if str(v[filter_key]) == filter_value:
- source = self._volumes_list[v["source"]]
- target = self._volumes_list[v["target"]]
- old_status = v["status"]
- if old_status == "preparing":
- new_status = "prepared"
- if self._next_cmd_error["lsfcmap"] == "bogus_prepare":
- new_status = "bogus"
- elif (old_status == "copying") and (v["progress"] == "0"):
- new_status = "copying"
- v["progress"] = "50"
- elif (old_status == "copying") and (v["progress"] == "50"):
- new_status = "idle_or_copied"
- to_delete.append(k)
- else:
- new_status = old_status
- v["status"] = new_status
-
- if ((self._next_cmd_error["lsfcmap"] == "speed_up") or
- (self._next_cmd_error["lsfcmap"] == "bogus_prepare")):
- print_status = new_status
- self._next_cmd_error["lsfcmap"] = ""
- else:
- print_status = old_status
-
- rows.append([v["id"], v["name"], source["id"],
- source["name"], target["id"], target["name"], "",
- "", print_status, v["progress"], "50", "100",
- "off", "", "", "no", "", "no"])
-
- for d in to_delete:
- del self._fcmappings_list[k]
-
- return self._print_info_cmd(rows=rows, **kwargs)
-
- # The main function to run commands on the management simulator
- def execute_command(self, cmd, check_exit_code=True):
- try:
- kwargs = self._cmd_to_dict(cmd)
- except IndexError:
- return self._errors["CMMVC5707E"]
-
- command = kwargs["cmd"]
- del kwargs["cmd"]
- arg_list = cmd.split()
-
- if command == "lsmdiskgrp":
- out, err = self._cmd_lsmdiskgrp(**kwargs)
- elif command == "lsnodecanister":
- out, err = self._cmd_lsnodecanister(**kwargs)
- elif command == "lsportip":
- out, err = self._cmd_lsportip(**kwargs)
- elif command == "mkvdisk":
- out, err = self._cmd_mkvdisk(**kwargs)
- elif command == "rmvdisk":
- out, err = self._cmd_rmvdisk(**kwargs)
- elif command == "lsvdisk":
- out, err = self._cmd_lsvdisk(**kwargs)
- elif command == "mkhost":
- out, err = self._cmd_mkhost(**kwargs)
- elif command == "rmhost":
- out, err = self._cmd_rmhost(**kwargs)
- elif command == "lshost":
- out, err = self._cmd_lshost(**kwargs)
- elif command == "mkvdiskhostmap":
- out, err = self._cmd_mkvdiskhostmap(**kwargs)
- elif command == "rmvdiskhostmap":
- out, err = self._cmd_rmvdiskhostmap(**kwargs)
- elif command == "lshostvdiskmap":
- out, err = self._cmd_lshostvdiskmap(**kwargs)
- elif command == "mkfcmap":
- out, err = self._cmd_mkfcmap(**kwargs)
- elif command == "prestartfcmap":
- out, err = self._cmd_gen_startfcmap(mode="pre", **kwargs)
- elif command == "startfcmap":
- out, err = self._cmd_gen_startfcmap(mode="start", **kwargs)
- elif command == "stopfcmap":
- out, err = self._cmd_stoprmfcmap(mode="stop", **kwargs)
- elif command == "rmfcmap":
- out, err = self._cmd_stoprmfcmap(mode="rm", **kwargs)
- elif command == "lsfcmap":
- out, err = self._cmd_lsfcmap(**kwargs)
- else:
- out, err = ("", "ERROR: Unsupported command")
-
- if (check_exit_code) and (len(err) != 0):
- raise exception.ProcessExecutionError(exit_code=1,
- stdout=out,
- stderr=err,
- cmd=' '.join(cmd))
-
- return (out, err)
-
- # After calling this function, the next call to the specified command will
- # result in in the error specified
- def error_injection(self, cmd, error):
- self._next_cmd_error[cmd] = error
-
-
-class StorwizeSVCFakeDriver(storwize_svc.StorwizeSVCDriver):
- def set_fake_storage(self, fake):
- self.fake_storage = fake
-
- def _run_ssh(self, cmd, check_exit_code=True):
- try:
- LOG.debug(_('Run CLI command: %s') % cmd)
- ret = self.fake_storage.execute_command(cmd, check_exit_code)
- (stdout, stderr) = ret
- LOG.debug(_('CLI output:\n stdout: %(out)s\n stderr: %(err)s') %
- {'out': stdout, 'err': stderr})
-
- except exception.ProcessExecutionError as e:
- with excutils.save_and_reraise_exception():
- LOG.debug(_('CLI Exception output:\n stdout: %(out)s\n '
- 'stderr: %(err)s') % {'out': e.stdout,
- 'err': e.stderr})
-
- return ret
-
-
-class StorwizeSVCDriverTestCase(test.TestCase):
- def setUp(self):
- super(StorwizeSVCDriverTestCase, self).setUp()
- self.USESIM = 1
- if self.USESIM == 1:
- self.flags(
- san_ip="hostname",
- san_login="user",
- san_password="pass",
- storwize_svc_flashcopy_timeout="20",
- )
- self.sim = StorwizeSVCManagementSimulator("volpool")
- self.driver = StorwizeSVCFakeDriver()
- self.driver.set_fake_storage(self.sim)
- else:
- self.flags(
- san_ip="-1.-1.-1.-1",
- san_login="user",
- san_password="password",
- storwize_svc_volpool_name="pool",
- )
- self.driver = storwize_svc.StorwizeSVCDriver()
-
- self.driver.do_setup(None)
- self.driver.check_for_setup_error()
-
- def test_storwize_svc_volume_tests(self):
- self.flags(storwize_svc_vol_rsize="-1")
- volume = {}
- volume["name"] = "test1_volume%s" % random.randint(10000, 99999)
- volume["size"] = 10
- volume["id"] = 1
- self.driver.create_volume(volume)
- # Make sure that the volume has been created
- is_volume_defined = self.driver._is_volume_defined(volume["name"])
- self.assertEqual(is_volume_defined, True)
- self.driver.delete_volume(volume)
-
- if self.USESIM == 1:
- self.flags(storwize_svc_vol_rsize="2%")
- self.flags(storwize_svc_vol_compression=True)
- self.driver.create_volume(volume)
- is_volume_defined = self.driver._is_volume_defined(volume["name"])
- self.assertEqual(is_volume_defined, True)
- self.driver.delete_volume(volume)
- FLAGS.reset()
-
- def test_storwize_svc_ip_connectivity(self):
- # Check for missing san_ip
- self.flags(san_ip=None)
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
-
- if self.USESIM != 1:
- # Check for invalid ip
- self.flags(san_ip="-1.-1.-1.-1")
- self.assertRaises(socket.gaierror,
- self.driver.check_for_setup_error)
-
- # Check for unreachable IP
- self.flags(san_ip="1.1.1.1")
- self.assertRaises(socket.error,
- self.driver.check_for_setup_error)
-
- def test_storwize_svc_connectivity(self):
- # Make sure we detect if the pool doesn't exist
- no_exist_pool = "i-dont-exist-%s" % random.randint(10000, 99999)
- self.flags(storwize_svc_volpool_name=no_exist_pool)
- self.assertRaises(exception.InvalidInput,
- self.driver.check_for_setup_error)
- FLAGS.reset()
-
- # Check the case where the user didn't configure IP addresses
- # as well as receiving unexpected results from the storage
- if self.USESIM == 1:
- self.sim.error_injection("lsnodecanister", "header_mismatch")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.check_for_setup_error)
- self.sim.error_injection("lsnodecanister", "remove_field")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.check_for_setup_error)
- self.sim.error_injection("lsportip", "ip_no_config")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.check_for_setup_error)
- self.sim.error_injection("lsportip", "header_mismatch")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.check_for_setup_error)
- self.sim.error_injection("lsportip", "remove_field")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.check_for_setup_error)
-
- # Check with bad parameters
- self.flags(san_password=None)
- self.flags(san_private_key=None)
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_vol_rsize="invalid")
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_vol_warning="invalid")
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_vol_autoexpand="invalid")
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_vol_grainsize=str(42))
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_flashcopy_timeout=str(601))
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- self.flags(storwize_svc_vol_compression=True)
- self.flags(storwize_svc_vol_rsize="-1")
- self.assertRaises(exception.InvalidInput,
- self.driver._check_flags)
- FLAGS.reset()
-
- # Finally, check with good parameters
- self.driver.check_for_setup_error()
-
- def test_storwize_svc_flashcopy(self):
- volume1 = {}
- volume1["name"] = "test1_volume%s" % random.randint(10000, 99999)
- volume1["size"] = 10
- volume1["id"] = 10
- self.driver.create_volume(volume1)
-
- snapshot = {}
- snapshot["name"] = "snap_volume%s" % random.randint(10000, 99999)
- snapshot["volume_name"] = volume1["name"]
-
- # Test timeout and volume cleanup
- self.flags(storwize_svc_flashcopy_timeout=str(1))
- self.assertRaises(exception.InvalidSnapshot,
- self.driver.create_snapshot, snapshot)
- is_volume_defined = self.driver._is_volume_defined(snapshot["name"])
- self.assertEqual(is_volume_defined, False)
- FLAGS.reset()
-
- # Test bogus statuses
- if self.USESIM == 1:
- self.sim.error_injection("lsfcmap", "bogus_prepare")
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.create_snapshot, snapshot)
-
- # Test prestartfcmap, startfcmap, and rmfcmap failing
- if self.USESIM == 1:
- self.sim.error_injection("prestartfcmap", "bad_id")
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.create_snapshot, snapshot)
- self.sim.error_injection("lsfcmap", "speed_up")
- self.sim.error_injection("startfcmap", "bad_id")
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.create_snapshot, snapshot)
- self.sim.error_injection("prestartfcmap", "bad_id")
- self.sim.error_injection("rmfcmap", "bad_id")
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.create_snapshot, snapshot)
-
- # Test successful snapshot
- self.driver.create_snapshot(snapshot)
-
- # Ensure snapshot is defined
- is_volume_defined = self.driver._is_volume_defined(snapshot["name"])
- self.assertEqual(is_volume_defined, True)
-
- # Try to create a snapshot from an non-existing volume - should fail
- snapshot2 = {}
- snapshot2["name"] = "snap_volume%s" % random.randint(10000, 99999)
- snapshot2["volume_name"] = "undefined-vol"
- self.assertRaises(exception.VolumeNotFound,
- self.driver.create_snapshot,
- snapshot2)
-
- # Create volume from snapshot
- volume2 = {}
- volume2["name"] = "snap2vol_volume%s" % random.randint(10000, 99999)
-
- # Create volume from snapshot into an existsing volume
- self.assertRaises(exception.InvalidSnapshot,
- self.driver.create_volume_from_snapshot,
- volume1,
- snapshot)
-
- # Try to create a volume from a non-existing snapshot
- self.assertRaises(exception.SnapshotNotFound,
- self.driver.create_volume_from_snapshot,
- volume2,
- snapshot2)
-
- # Fail the snapshot
- if self.USESIM == 1:
- self.sim.error_injection("prestartfcmap", "bad_id")
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.create_volume_from_snapshot, volume2, snapshot)
-
- # Succeed
- if self.USESIM == 1:
- self.sim.error_injection("lsfcmap", "speed_up")
- self.driver.create_volume_from_snapshot(volume2, snapshot)
-
- # Ensure volume is defined
- is_volume_defined = self.driver._is_volume_defined(volume2["name"])
- self.assertEqual(is_volume_defined, True)
-
- self.driver._delete_volume(volume2, True)
- self.driver._delete_snapshot(snapshot, True)
-
- # Check with target with different size
- volume3 = {}
- volume3["name"] = "test3_volume%s" % random.randint(10000, 99999)
- volume3["size"] = 11
- volume3["id"] = 11
- self.driver.create_volume(volume3)
- snapshot["name"] = volume3["name"]
- self.assertRaises(exception.InvalidSnapshot,
- self.driver.create_snapshot, snapshot)
- self.driver._delete_volume(volume1, True)
- self.driver._delete_volume(volume3, True)
-
- # Snapshot volume that doesn't exist
- snapshot = {}
- snapshot["name"] = "snap_volume%s" % random.randint(10000, 99999)
- snapshot["volume_name"] = "no_exist"
- self.assertRaises(exception.VolumeNotFound,
- self.driver.create_snapshot, snapshot)
-
- def test_storwize_svc_volumes(self):
- # Create a first volume
- volume = {}
- volume["name"] = "test1_volume%s" % random.randint(10000, 99999)
- volume["size"] = 10
- volume["id"] = 1
-
- self.driver.create_volume(volume)
-
- self.driver.ensure_export(None, volume)
-
- # Do nothing
- self.driver.create_export(None, volume)
- self.driver.remove_export(None, volume)
- self.assertRaises(NotImplementedError,
- self.driver.check_for_export, None, volume["id"])
-
- # Make sure volume attributes are as they should be
- attributes = self.driver._get_volume_attributes(volume["name"])
- attr_size = float(attributes["capacity"]) / 1073741824 # bytes to GB
- self.assertEqual(attr_size, float(volume["size"]))
- pool = storwize_svc.FLAGS.storwize_svc_volpool_name
- self.assertEqual(attributes["mdisk_grp_name"], pool)
-
- # Try to create the volume again (should fail)
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.create_volume, volume)
-
- # Try to delete a volume that doesn't exist (should not fail)
- vol_no_exist = {"name": "i_dont_exist"}
- self.driver.delete_volume(vol_no_exist)
- # Ensure export for volume that doesn't exist (should not fail)
- self.driver.ensure_export(None, vol_no_exist)
-
- # Delete the volume
- self.driver.delete_volume(volume)
-
- def _create_test_vol(self):
- volume = {}
- volume["name"] = "testparam_volume%s" % random.randint(10000, 99999)
- volume["size"] = 1
- volume["id"] = 1
- self.driver.create_volume(volume)
-
- attrs = self.driver._get_volume_attributes(volume["name"])
- self.driver.delete_volume(volume)
- return attrs
-
- def test_storwize_svc_volume_params(self):
- # Option test matrix
- # Option Value Covered by test #
- # rsize -1 1
- # rsize 2% 2,3
- # warning 0 2
- # warning 80% 3
- # autoexpand True 2
- # autoexpand False 3
- # grainsize 32 2
- # grainsize 256 3
- # compression True 4
- # compression False 2,3
- # easytier True 1,3
- # easytier False 2
-
- # Test 1
- self.flags(storwize_svc_vol_rsize="-1")
- self.flags(storwize_svc_vol_easytier=True)
- attrs = self._create_test_vol()
- self.assertEquals(attrs["free_capacity"], "0")
- self.assertEquals(attrs["easy_tier"], "on")
- FLAGS.reset()
-
- # Test 2
- self.flags(storwize_svc_vol_rsize="2%")
- self.flags(storwize_svc_vol_compression=False)
- self.flags(storwize_svc_vol_warning="0")
- self.flags(storwize_svc_vol_autoexpand=True)
- self.flags(storwize_svc_vol_grainsize="32")
- self.flags(storwize_svc_vol_easytier=False)
- attrs = self._create_test_vol()
- self.assertNotEqual(attrs["capacity"], attrs["real_capacity"])
- self.assertEquals(attrs["compressed_copy"], "no")
- self.assertEquals(attrs["warning"], "0")
- self.assertEquals(attrs["autoexpand"], "on")
- self.assertEquals(attrs["grainsize"], "32")
- self.assertEquals(attrs["easy_tier"], "off")
- FLAGS.reset()
-
- # Test 3
- self.flags(storwize_svc_vol_rsize="2%")
- self.flags(storwize_svc_vol_compression=False)
- self.flags(storwize_svc_vol_warning="80%")
- self.flags(storwize_svc_vol_autoexpand=False)
- self.flags(storwize_svc_vol_grainsize="256")
- self.flags(storwize_svc_vol_easytier=True)
- attrs = self._create_test_vol()
- self.assertNotEqual(attrs["capacity"], attrs["real_capacity"])
- self.assertEquals(attrs["compressed_copy"], "no")
- self.assertEquals(attrs["warning"], "80")
- self.assertEquals(attrs["autoexpand"], "off")
- self.assertEquals(attrs["grainsize"], "256")
- self.assertEquals(attrs["easy_tier"], "on")
- FLAGS.reset()
-
- # Test 4
- self.flags(storwize_svc_vol_rsize="2%")
- self.flags(storwize_svc_vol_compression=True)
- try:
- attrs = self._create_test_vol()
- self.assertNotEqual(attrs["capacity"], attrs["real_capacity"])
- self.assertEquals(attrs["compressed_copy"], "yes")
- except exception.ProcessExecutionError as e:
- if "CMMVC7050E" not in e.stderr:
- raise exception.ProcessExecutionError(exit_code=e.exit_code,
- stdout=e.stdout,
- stderr=e.stderr,
- cmd=e.cmd)
- if self.USESIM == 1:
- self.sim.error_injection("mkvdisk", "no_compression")
- self.assertRaises(exception.ProcessExecutionError,
- self._create_test_vol)
- FLAGS.reset()
-
- def test_storwize_svc_unicode_host_and_volume_names(self):
- volume1 = {}
- volume1["name"] = u"unicode1_volume%s" % random.randint(10000, 99999)
- volume1["size"] = 2
- volume1["id"] = 1
- self.driver.create_volume(volume1)
- # Make sure that the volumes have been created
- is_volume_defined = self.driver._is_volume_defined(volume1["name"])
- self.assertEqual(is_volume_defined, True)
- conn = {}
- conn["initiator"] = u"unicode:init:%s" % random.randint(10000, 99999)
- conn["ip"] = "10.10.10.10" # Bogus ip for testing
- self.driver.initialize_connection(volume1, conn)
- self.driver.terminate_connection(volume1, conn)
- self.driver.delete_volume(volume1)
-
- def test_storwize_svc_host_maps(self):
- # Create two volumes to be used in mappings
- volume1 = {}
- volume1["name"] = "test1_volume%s" % random.randint(10000, 99999)
- volume1["size"] = 2
- volume1["id"] = 1
- self.driver.create_volume(volume1)
- volume2 = {}
- volume2["name"] = "test2_volume%s" % random.randint(10000, 99999)
- volume2["size"] = 2
- volume2["id"] = 1
- self.driver.create_volume(volume2)
-
- # Check case where no hosts exist
- if self.USESIM == 1:
- ret = self.driver._get_host_from_iscsiname("foo")
- self.assertEquals(ret, None)
- ret = self.driver._is_host_defined("foo")
- self.assertEquals(ret, False)
-
- # Make sure that the volumes have been created
- is_volume_defined = self.driver._is_volume_defined(volume1["name"])
- self.assertEqual(is_volume_defined, True)
- is_volume_defined = self.driver._is_volume_defined(volume2["name"])
- self.assertEqual(is_volume_defined, True)
-
- # Initialize connection from the first volume to a host
- # Add some characters to the initiator name that should be converted
- # when used for the host name
- conn = {}
- conn["initiator"] = "test:init:%s" % random.randint(10000, 99999)
- conn["ip"] = "10.10.10.10" # Bogus ip for testing
- self.driver.initialize_connection(volume1, conn)
-
- # Initialize again, should notice it and do nothing
- self.driver.initialize_connection(volume1, conn)
-
- # Try to delete the 1st volume (should fail because it is mapped)
- self.assertRaises(exception.ProcessExecutionError,
- self.driver.delete_volume, volume1)
-
- # Test no preferred node
- self.driver.terminate_connection(volume1, conn)
- if self.USESIM == 1:
- self.sim.error_injection("lsvdisk", "no_pref_node")
- self.driver.initialize_connection(volume1, conn)
-
- # Initialize connection from the second volume to the host with no
- # preferred node set if in simulation mode, otherwise, just
- # another initialize connection.
- if self.USESIM == 1:
- self.sim.error_injection("lsvdisk", "blank_pref_node")
- self.driver.initialize_connection(volume2, conn)
-
- # Try to remove connection from host that doesn't exist (should fail)
- conn_no_exist = {"initiator": "i_dont_exist"}
- self.assertRaises(exception.VolumeBackendAPIException,
- self.driver.terminate_connection, volume1, conn_no_exist)
-
- # Try to remove connection from volume that isn't mapped (should print
- # message but NOT fail)
- vol_no_exist = {"name": "i_dont_exist"}
- self.driver.terminate_connection(vol_no_exist, conn)
-
- # Remove the mapping from the 1st volume and delete it
- self.driver.terminate_connection(volume1, conn)
- self.driver.delete_volume(volume1)
- vol_def = self.driver._is_volume_defined(volume1["name"])
- self.assertEqual(vol_def, False)
-
- # Make sure our host still exists
- host_name = self.driver._get_host_from_iscsiname(conn["initiator"])
- host_def = self.driver._is_host_defined(host_name)
- self.assertEquals(host_def, True)
-
- # Remove the mapping from the 2nd volume and delete it. The host should
- # be automatically removed because there are no more mappings.
- self.driver.terminate_connection(volume2, conn)
- self.driver.delete_volume(volume2)
- vol_def = self.driver._is_volume_defined(volume2["name"])
- self.assertEqual(vol_def, False)
-
- # Check if our host still exists (it should not)
- ret = self.driver._get_host_from_iscsiname(conn["initiator"])
- self.assertEquals(ret, None)
- ret = self.driver._is_host_defined(host_name)
- self.assertEquals(ret, False)
diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
deleted file mode 100644
index 7b14d8a99..000000000
--- a/nova/tests/test_volume.py
+++ /dev/null
@@ -1,931 +0,0 @@
-# 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.
-"""
-Tests for Volume Code.
-
-"""
-
-import cStringIO
-import datetime
-
-import mox
-import os
-import shutil
-import tempfile
-
-from nova import context
-from nova import db
-from nova import exception
-from nova import flags
-from nova.openstack.common import importutils
-from nova.openstack.common.notifier import api as notifier_api
-from nova.openstack.common.notifier import test_notifier
-from nova.openstack.common import rpc
-import nova.policy
-from nova import quota
-from nova import test
-from nova.tests.image import fake as fake_image
-import nova.volume.api
-from nova.volume import iscsi
-
-QUOTAS = quota.QUOTAS
-
-
-FLAGS = flags.FLAGS
-
-
-class VolumeTestCase(test.TestCase):
- """Test Case for volumes."""
-
- def setUp(self):
- super(VolumeTestCase, self).setUp()
- self.compute = importutils.import_object(FLAGS.compute_manager)
- vol_tmpdir = tempfile.mkdtemp()
- self.flags(compute_driver='nova.virt.fake.FakeDriver',
- volumes_dir=vol_tmpdir,
- notification_driver=[test_notifier.__name__])
- self.stubs.Set(iscsi.TgtAdm, '_get_target', self.fake_get_target)
- self.volume = importutils.import_object(FLAGS.volume_manager)
- self.context = context.get_admin_context()
- instance = db.instance_create(self.context, {})
- self.instance_id = instance['id']
- self.instance_uuid = instance['uuid']
- test_notifier.NOTIFICATIONS = []
- fake_image.stub_out_image_service(self.stubs)
-
- def tearDown(self):
- try:
- shutil.rmtree(FLAGS.volumes_dir)
- except OSError:
- pass
- db.instance_destroy(self.context, self.instance_uuid)
- notifier_api._reset_drivers()
- super(VolumeTestCase, self).tearDown()
-
- def fake_get_target(obj, iqn):
- return 1
-
- @staticmethod
- def _create_volume(size=0, snapshot_id=None, image_id=None, metadata=None):
- """Create a volume object."""
- vol = {}
- vol['size'] = size
- vol['snapshot_id'] = snapshot_id
- vol['image_id'] = image_id
- vol['user_id'] = 'fake'
- vol['project_id'] = 'fake'
- vol['availability_zone'] = FLAGS.storage_availability_zone
- vol['status'] = "creating"
- vol['attach_status'] = "detached"
- if metadata is not None:
- vol['metadata'] = metadata
- return db.volume_create(context.get_admin_context(), vol)
-
- def test_ec2_uuid_mapping(self):
- ec2_vol = db.ec2_volume_create(context.get_admin_context(),
- 'aaaaaaaa-bbbb-bbbb-bbbb-aaaaaaaaaaaa', 5)
- self.assertEqual(5, ec2_vol['id'])
- self.assertEqual('aaaaaaaa-bbbb-bbbb-bbbb-aaaaaaaaaaaa',
- db.get_volume_uuid_by_ec2_id(context.get_admin_context(), 5))
-
- ec2_vol = db.ec2_volume_create(context.get_admin_context(),
- 'aaaaaaaa-bbbb-bbbb-bbbb-aaaaaaaaaaaa', 1)
- self.assertEqual(1, ec2_vol['id'])
-
- ec2_vol = db.ec2_volume_create(context.get_admin_context(),
- 'aaaaaaaa-bbbb-bbbb-bbbb-aaaaaaaaazzz')
- self.assertEqual(6, ec2_vol['id'])
-
- def test_create_delete_volume(self):
- """Test volume can be created and deleted."""
- # Need to stub out reserve, commit, and rollback
- def fake_reserve(context, expire=None, **deltas):
- return ["RESERVATION"]
-
- def fake_commit(context, reservations):
- pass
-
- def fake_rollback(context, reservations):
- pass
-
- self.stubs.Set(QUOTAS, "reserve", fake_reserve)
- self.stubs.Set(QUOTAS, "commit", fake_commit)
- self.stubs.Set(QUOTAS, "rollback", fake_rollback)
-
- volume = self._create_volume()
- volume_id = volume['id']
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
- self.volume.create_volume(self.context, volume_id)
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
- self.assertEqual(volume_id, db.volume_get(context.get_admin_context(),
- volume_id).id)
-
- self.volume.delete_volume(self.context, volume_id)
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 4)
- self.assertRaises(exception.NotFound,
- db.volume_get,
- self.context,
- volume_id)
-
- def test_create_delete_volume_with_metadata(self):
- """Test volume can be created and deleted."""
- test_meta = {'fake_key': 'fake_value'}
- volume = self._create_volume('0', None, metadata=test_meta)
- volume_id = volume['id']
- self.volume.create_volume(self.context, volume_id)
- result_meta = {
- volume.volume_metadata[0].key: volume.volume_metadata[0].value}
- self.assertEqual(result_meta, test_meta)
-
- self.volume.delete_volume(self.context, volume_id)
- self.assertRaises(exception.NotFound,
- db.volume_get,
- self.context,
- volume_id)
-
- def _do_test_create_over_quota(self, resource, expected):
- """Test volume creation over quota."""
-
- def fake_reserve(context, **deltas):
- kwargs = dict(overs=[resource],
- quotas=dict(gigabytes=1000, volumes=10),
- usages=dict(gigabytes=dict(reserved=1, in_use=999),
- volumes=dict(reserved=1, in_use=9)))
- raise exception.OverQuota(**kwargs)
-
- def fake_commit(context, reservations):
- self.fail('should not commit over quota')
-
- self.stubs.Set(QUOTAS, 'reserve', fake_reserve)
- self.stubs.Set(QUOTAS, 'commit', fake_commit)
-
- volume_api = nova.volume.api.API()
-
- self.assertRaises(expected,
- volume_api.create,
- self.context,
- 2,
- 'name',
- 'description')
-
- def test_create_volumes_over_quota(self):
- self._do_test_create_over_quota('volumes',
- exception.VolumeLimitExceeded)
-
- def test_create_gigabytes_over_quota(self):
- self._do_test_create_over_quota('gigabytes',
- exception.VolumeSizeTooLarge)
-
- def test_delete_busy_volume(self):
- """Test volume survives deletion if driver reports it as busy."""
- volume = self._create_volume()
- volume_id = volume['id']
- self.volume.create_volume(self.context, volume_id)
-
- self.mox.StubOutWithMock(self.volume.driver, 'delete_volume')
- self.volume.driver.delete_volume(mox.IgnoreArg()).AndRaise(
- exception.VolumeIsBusy)
- self.mox.ReplayAll()
- res = self.volume.delete_volume(self.context, volume_id)
- self.assertEqual(True, res)
- volume_ref = db.volume_get(context.get_admin_context(), volume_id)
- self.assertEqual(volume_id, volume_ref.id)
- self.assertEqual("available", volume_ref.status)
-
- self.mox.UnsetStubs()
- self.volume.delete_volume(self.context, volume_id)
-
- def test_create_volume_from_snapshot(self):
- """Test volume can be created from a snapshot."""
- volume_src = self._create_volume()
- self.volume.create_volume(self.context, volume_src['id'])
- snapshot_id = self._create_snapshot(volume_src['id'])
- self.volume.create_snapshot(self.context, volume_src['id'],
- snapshot_id)
- volume_dst = self._create_volume(0, snapshot_id)
- self.volume.create_volume(self.context, volume_dst['id'], snapshot_id)
- self.assertEqual(volume_dst['id'],
- db.volume_get(
- context.get_admin_context(),
- volume_dst['id']).id)
- self.assertEqual(snapshot_id, db.volume_get(
- context.get_admin_context(),
- volume_dst['id']).snapshot_id)
-
- self.volume.delete_volume(self.context, volume_dst['id'])
- self.volume.delete_snapshot(self.context, snapshot_id)
- self.volume.delete_volume(self.context, volume_src['id'])
-
- def test_too_big_volume(self):
- """Ensure failure if a too large of a volume is requested."""
- # FIXME(vish): validation needs to move into the data layer in
- # volume_create
- return True
- try:
- volume = self._create_volume('1001')
- self.volume.create_volume(self.context, volume)
- self.fail("Should have thrown TypeError")
- except TypeError:
- pass
-
- def test_run_attach_detach_volume(self):
- """Make sure volume can be attached and detached from instance."""
- inst = {}
- inst['image_id'] = 1
- inst['reservation_id'] = 'r-fakeres'
- inst['launch_time'] = '10'
- inst['user_id'] = 'fake'
- inst['project_id'] = 'fake'
- inst['instance_type_id'] = '2' # m1.tiny
- inst['ami_launch_index'] = 0
- instance = db.instance_create(self.context, {})
- instance_id = instance['id']
- instance_uuid = instance['uuid']
- mountpoint = "/dev/sdf"
- volume = self._create_volume()
- volume_id = volume['id']
- self.volume.create_volume(self.context, volume_id)
- if FLAGS.fake_tests:
- db.volume_attached(self.context, volume_id, instance_uuid,
- mountpoint)
- else:
- self.compute.attach_volume(self.context,
- instance_uuid,
- volume_id,
- mountpoint)
- vol = db.volume_get(context.get_admin_context(), volume_id)
- self.assertEqual(vol['status'], "in-use")
- self.assertEqual(vol['attach_status'], "attached")
- self.assertEqual(vol['mountpoint'], mountpoint)
- self.assertEqual(vol['instance_uuid'], instance_uuid)
- self.assertNotEqual(vol['attach_time'], None)
-
- self.assertRaises(exception.VolumeAttached,
- self.volume.delete_volume,
- self.context,
- volume_id)
- if FLAGS.fake_tests:
- db.volume_detached(self.context, volume_id)
- else:
- self.compute.detach_volume(self.context,
- instance_uuid,
- volume_id)
- vol = db.volume_get(self.context, volume_id)
- self.assertEqual(vol['status'], "available")
- self.assertEqual(vol['attach_time'], None)
-
- self.volume.delete_volume(self.context, volume_id)
- self.assertRaises(exception.VolumeNotFound,
- db.volume_get,
- self.context,
- volume_id)
- db.instance_destroy(self.context, instance_uuid)
-
- def test_concurrent_volumes_get_different_targets(self):
- """Ensure multiple concurrent volumes get different targets."""
- volume_ids = []
- targets = []
-
- def _check(volume_id):
- """Make sure targets aren't duplicated."""
- volume_ids.append(volume_id)
- admin_context = context.get_admin_context()
- iscsi_target = db.volume_get_iscsi_target_num(admin_context,
- volume_id)
- self.assert_(iscsi_target not in targets)
- targets.append(iscsi_target)
-
- total_slots = FLAGS.iscsi_num_targets
- for _index in xrange(total_slots):
- self._create_volume()
- for volume_id in volume_ids:
- self.volume.delete_volume(self.context, volume_id)
-
- def test_multi_node(self):
- # TODO(termie): Figure out how to test with two nodes,
- # each of them having a different FLAG for storage_node
- # This will allow us to test cross-node interactions
- pass
-
- @staticmethod
- def _create_snapshot(volume_id, size='0'):
- """Create a snapshot object."""
- snap = {}
- snap['volume_size'] = size
- snap['user_id'] = 'fake'
- snap['project_id'] = 'fake'
- snap['volume_id'] = volume_id
- snap['status'] = "creating"
- return db.snapshot_create(context.get_admin_context(), snap)['id']
-
- def test_create_delete_snapshot(self):
- """Test snapshot can be created and deleted."""
- volume = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
- self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
- self.assertEqual(snapshot_id,
- db.snapshot_get(context.get_admin_context(),
- snapshot_id).id)
-
- self.volume.delete_snapshot(self.context, snapshot_id)
- self.assertRaises(exception.NotFound,
- db.snapshot_get,
- self.context,
- snapshot_id)
- self.volume.delete_volume(self.context, volume['id'])
-
- def test_cant_delete_volume_in_use(self):
- """Test volume can't be deleted in invalid stats."""
- # create a volume and assign to host
- volume = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- volume['status'] = 'in-use'
- volume['host'] = 'fakehost'
-
- volume_api = nova.volume.api.API()
-
- # 'in-use' status raises InvalidVolume
- self.assertRaises(exception.InvalidVolume,
- volume_api.delete,
- self.context,
- volume)
-
- # clean up
- self.volume.delete_volume(self.context, volume['id'])
-
- def test_force_delete_volume(self):
- """Test volume can be forced to delete."""
- # create a volume and assign to host
- volume = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- volume['status'] = 'error_deleting'
- volume['host'] = 'fakehost'
-
- volume_api = nova.volume.api.API()
-
- # 'error_deleting' volumes can't be deleted
- self.assertRaises(exception.InvalidVolume,
- volume_api.delete,
- self.context,
- volume)
-
- # delete with force
- volume_api.delete(self.context, volume, force=True)
-
- # status is deleting
- volume = db.volume_get(context.get_admin_context(), volume['id'])
- self.assertEquals(volume['status'], 'deleting')
-
- # clean up
- self.volume.delete_volume(self.context, volume['id'])
-
- def test_cant_delete_volume_with_snapshots(self):
- """Test snapshot can be created and deleted."""
- volume = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
- self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
- self.assertEqual(snapshot_id,
- db.snapshot_get(context.get_admin_context(),
- snapshot_id).id)
-
- volume['status'] = 'available'
- volume['host'] = 'fakehost'
-
- volume_api = nova.volume.api.API()
-
- self.assertRaises(exception.InvalidVolume,
- volume_api.delete,
- self.context,
- volume)
- self.volume.delete_snapshot(self.context, snapshot_id)
- self.volume.delete_volume(self.context, volume['id'])
-
- def test_can_delete_errored_snapshot(self):
- """Test snapshot can be created and deleted."""
- volume = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
- self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
- snapshot = db.snapshot_get(context.get_admin_context(),
- snapshot_id)
-
- volume_api = nova.volume.api.API()
-
- snapshot['status'] = 'badstatus'
- self.assertRaises(exception.InvalidVolume,
- volume_api.delete_snapshot,
- self.context,
- snapshot)
-
- snapshot['status'] = 'error'
- self.volume.delete_snapshot(self.context, 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 = self._create_volume()
- self.volume.create_volume(self.context, volume['id'])
- db.volume_attached(self.context, volume['id'], self.instance_uuid,
- '/dev/sda1')
-
- volume_api = nova.volume.api.API()
- volume = volume_api.get(self.context, volume['id'])
- self.assertRaises(exception.InvalidVolume,
- volume_api.create_snapshot,
- self.context, volume,
- 'fake_name', 'fake_description')
- snapshot_ref = volume_api.create_snapshot_force(self.context,
- volume,
- 'fake_name',
- 'fake_description')
- db.snapshot_destroy(self.context, snapshot_ref['id'])
- db.volume_destroy(self.context, volume['id'])
-
- def test_delete_busy_snapshot(self):
- """Test snapshot can be created and deleted."""
- volume = self._create_volume()
- volume_id = volume['id']
- self.volume.create_volume(self.context, volume_id)
- snapshot_id = self._create_snapshot(volume_id)
- self.volume.create_snapshot(self.context, volume_id, snapshot_id)
-
- self.mox.StubOutWithMock(self.volume.driver, 'delete_snapshot')
- self.volume.driver.delete_snapshot(mox.IgnoreArg()).AndRaise(
- exception.SnapshotIsBusy)
- self.mox.ReplayAll()
- self.volume.delete_snapshot(self.context, snapshot_id)
- snapshot_ref = db.snapshot_get(self.context, snapshot_id)
- self.assertEqual(snapshot_id, snapshot_ref.id)
- self.assertEqual("available", snapshot_ref.status)
-
- self.mox.UnsetStubs()
- self.volume.delete_snapshot(self.context, snapshot_id)
- self.volume.delete_volume(self.context, volume_id)
-
- def test_create_volume_usage_notification(self):
- """Ensure create volume generates appropriate usage notification"""
- volume = self._create_volume()
- volume_id = volume['id']
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
- self.volume.create_volume(self.context, volume_id)
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
- msg = test_notifier.NOTIFICATIONS[0]
- self.assertEquals(msg['event_type'], 'volume.create.start')
- payload = msg['payload']
- self.assertEquals(payload['status'], 'creating')
- msg = test_notifier.NOTIFICATIONS[1]
- self.assertEquals(msg['priority'], 'INFO')
- self.assertEquals(msg['event_type'], 'volume.create.end')
- payload = msg['payload']
- self.assertEquals(payload['tenant_id'], volume['project_id'])
- self.assertEquals(payload['user_id'], volume['user_id'])
- self.assertEquals(payload['volume_id'], volume['id'])
- self.assertEquals(payload['status'], 'available')
- self.assertEquals(payload['size'], volume['size'])
- self.assertTrue('display_name' in payload)
- self.assertTrue('snapshot_id' in payload)
- self.assertTrue('launched_at' in payload)
- self.assertTrue('created_at' in payload)
- self.volume.delete_volume(self.context, volume_id)
-
- def _do_test_create_volume_with_size(self, size):
- def fake_reserve(context, expire=None, **deltas):
- return ["RESERVATION"]
-
- def fake_commit(context, reservations):
- pass
-
- def fake_rollback(context, reservations):
- pass
-
- self.stubs.Set(QUOTAS, "reserve", fake_reserve)
- self.stubs.Set(QUOTAS, "commit", fake_commit)
- self.stubs.Set(QUOTAS, "rollback", fake_rollback)
-
- volume_api = nova.volume.api.API()
-
- volume = volume_api.create(self.context,
- size,
- 'name',
- 'description')
- self.assertEquals(volume['size'], int(size))
-
- def test_create_volume_int_size(self):
- """Test volume creation with int size."""
- self._do_test_create_volume_with_size(2)
-
- def test_create_volume_string_size(self):
- """Test volume creation with string size."""
- self._do_test_create_volume_with_size('2')
-
- def test_create_volume_with_bad_size(self):
- def fake_reserve(context, expire=None, **deltas):
- return ["RESERVATION"]
-
- def fake_commit(context, reservations):
- pass
-
- def fake_rollback(context, reservations):
- pass
-
- self.stubs.Set(QUOTAS, "reserve", fake_reserve)
- self.stubs.Set(QUOTAS, "commit", fake_commit)
- self.stubs.Set(QUOTAS, "rollback", fake_rollback)
-
- volume_api = nova.volume.api.API()
-
- self.assertRaises(exception.InvalidInput,
- volume_api.create,
- self.context,
- '2Gb',
- 'name',
- 'description')
-
- def test_begin_roll_detaching_volume(self):
- """Test begin_detaching and roll_detaching functions."""
- volume = self._create_volume()
- volume_api = nova.volume.api.API()
- volume_api.begin_detaching(self.context, volume)
- volume = db.volume_get(self.context, volume['id'])
- self.assertEqual(volume['status'], "detaching")
- volume_api.roll_detaching(self.context, volume)
- volume = db.volume_get(self.context, volume['id'])
- self.assertEqual(volume['status'], "in-use")
-
- def _create_volume_from_image(self, expected_status,
- fakeout_copy_image_to_volume=False):
- """Call copy image to volume, Test the status of volume after calling
- copying image to volume."""
- def fake_local_path(volume):
- return dst_path
-
- def fake_copy_image_to_volume(context, volume, image_id):
- pass
-
- dst_fd, dst_path = tempfile.mkstemp()
- os.close(dst_fd)
- self.stubs.Set(self.volume.driver, 'local_path', fake_local_path)
- if fakeout_copy_image_to_volume:
- self.stubs.Set(self.volume, '_copy_image_to_volume',
- fake_copy_image_to_volume)
-
- image_id = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
- volume_id = 1
- # creating volume testdata
- db.volume_create(self.context, {'id': volume_id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'creating',
- 'instance_uuid': None,
- 'host': 'dummy'})
- try:
- self.volume.create_volume(self.context,
- volume_id,
- image_id=image_id)
-
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], expected_status)
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
- os.unlink(dst_path)
-
- def test_create_volume_from_image_status_downloading(self):
- """Verify that before copying image to volume, it is in downloading
- state."""
- self._create_volume_from_image('downloading', True)
-
- def test_create_volume_from_image_status_available(self):
- """Verify that before copying image to volume, it is in available
- state."""
- self._create_volume_from_image('available')
-
- def test_create_volume_from_image_exception(self):
- """Verify that create volume from image, the volume status is
- 'downloading'."""
- dst_fd, dst_path = tempfile.mkstemp()
- os.close(dst_fd)
-
- self.stubs.Set(self.volume.driver, 'local_path', lambda x: dst_path)
-
- image_id = 'aaaaaaaa-0000-0000-0000-000000000000'
- # creating volume testdata
- volume_id = 1
- db.volume_create(self.context, {'id': volume_id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'creating',
- 'host': 'dummy'})
-
- self.assertRaises(exception.ImageNotFound,
- self.volume.create_volume,
- self.context,
- volume_id,
- None,
- image_id)
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], "error")
- # cleanup
- db.volume_destroy(self.context, volume_id)
- os.unlink(dst_path)
-
- def test_copy_volume_to_image_status_available(self):
- dst_fd, dst_path = tempfile.mkstemp()
- os.close(dst_fd)
-
- def fake_local_path(volume):
- return dst_path
-
- self.stubs.Set(self.volume.driver, 'local_path', fake_local_path)
-
- image_id = '70a599e0-31e7-49b7-b260-868f441e862b'
- # creating volume testdata
- volume_id = 1
- db.volume_create(self.context, {'id': volume_id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'uploading',
- 'instance_uuid': None,
- 'host': 'dummy'})
-
- try:
- # start test
- self.volume.copy_volume_to_image(self.context,
- volume_id,
- image_id)
-
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], 'available')
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
- os.unlink(dst_path)
-
- def test_copy_volume_to_image_status_use(self):
- dst_fd, dst_path = tempfile.mkstemp()
- os.close(dst_fd)
-
- def fake_local_path(volume):
- return dst_path
-
- self.stubs.Set(self.volume.driver, 'local_path', fake_local_path)
-
- #image_id = '70a599e0-31e7-49b7-b260-868f441e862b'
- image_id = 'a440c04b-79fa-479c-bed1-0b816eaec379'
- # creating volume testdata
- volume_id = 1
- db.volume_create(self.context,
- {'id': volume_id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'uploading',
- 'instance_uuid':
- 'b21f957d-a72f-4b93-b5a5-45b1161abb02',
- 'host': 'dummy'})
-
- try:
- # start test
- self.volume.copy_volume_to_image(self.context,
- volume_id,
- image_id)
-
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], 'in-use')
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
- os.unlink(dst_path)
-
- def test_copy_volume_to_image_exception(self):
- dst_fd, dst_path = tempfile.mkstemp()
- os.close(dst_fd)
-
- def fake_local_path(volume):
- return dst_path
-
- self.stubs.Set(self.volume.driver, 'local_path', fake_local_path)
-
- image_id = 'aaaaaaaa-0000-0000-0000-000000000000'
- # creating volume testdata
- volume_id = 1
- db.volume_create(self.context, {'id': volume_id,
- 'updated_at': datetime.datetime(1, 1, 1, 1, 1, 1),
- 'display_description': 'Test Desc',
- 'size': 20,
- 'status': 'in-use',
- 'host': 'dummy'})
-
- try:
- # start test
- self.assertRaises(exception.ImageNotFound,
- self.volume.copy_volume_to_image,
- self.context,
- volume_id,
- image_id)
-
- volume = db.volume_get(self.context, volume_id)
- self.assertEqual(volume['status'], 'available')
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
- os.unlink(dst_path)
-
- def test_create_volume_from_exact_sized_image(self):
- """Verify that an image which is exactly the same size as the
- volume, will work correctly."""
- class _FakeImageService:
- def __init__(self, db_driver=None, image_service=None):
- pass
-
- def show(self, context, image_id):
- return {'size': 2 * 1024 * 1024 * 1024}
-
- image_id = '70a599e0-31e7-49b7-b260-868f441e862b'
-
- try:
- volume_id = None
- volume_api = nova.volume.api.API(
- image_service=_FakeImageService())
- volume = volume_api.create(self.context, 2, 'name', 'description',
- image_id=1)
- volume_id = volume['id']
- self.assertEqual(volume['status'], 'creating')
-
- finally:
- # cleanup
- db.volume_destroy(self.context, volume_id)
-
- def test_create_volume_from_oversized_image(self):
- """Verify that an image which is too big will fail correctly."""
- class _FakeImageService:
- def __init__(self, db_driver=None, image_service=None):
- pass
-
- def show(self, context, image_id):
- return {'size': 2 * 1024 * 1024 * 1024 + 1}
-
- image_id = '70a599e0-31e7-49b7-b260-868f441e862b'
-
- volume_api = nova.volume.api.API(image_service=_FakeImageService())
-
- self.assertRaises(exception.InvalidInput,
- volume_api.create,
- self.context, 2,
- 'name', 'description', image_id=1)
-
-
-class DriverTestCase(test.TestCase):
- """Base Test class for Drivers."""
- driver_name = "nova.volume.driver.FakeBaseDriver"
-
- def setUp(self):
- super(DriverTestCase, self).setUp()
- vol_tmpdir = tempfile.mkdtemp()
- self.flags(volume_driver=self.driver_name,
- volumes_dir=vol_tmpdir)
- self.volume = importutils.import_object(FLAGS.volume_manager)
- self.context = context.get_admin_context()
- self.output = ""
- self.stubs.Set(iscsi.TgtAdm, '_get_target', self.fake_get_target)
-
- def _fake_execute(_command, *_args, **_kwargs):
- """Fake _execute."""
- return self.output, None
- self.volume.driver.set_execute(_fake_execute)
-
- instance = db.instance_create(self.context, {})
- self.instance_id = instance['id']
- self.instance_uuid = instance['uuid']
-
- def tearDown(self):
- try:
- shutil.rmtree(FLAGS.volumes_dir)
- except OSError:
- pass
- super(DriverTestCase, self).tearDown()
-
- def fake_get_target(obj, iqn):
- return 1
-
- def _attach_volume(self):
- """Attach volumes to an instance."""
- return []
-
- def _detach_volume(self, volume_id_list):
- """Detach volumes from an instance."""
- for volume_id in volume_id_list:
- db.volume_detached(self.context, volume_id)
- self.volume.delete_volume(self.context, volume_id)
-
-
-class VolumeDriverTestCase(DriverTestCase):
- """Test case for VolumeDriver"""
- driver_name = "nova.volume.driver.VolumeDriver"
-
- def test_delete_busy_volume(self):
- """Test deleting a busy volume."""
- self.stubs.Set(self.volume.driver, '_volume_not_present',
- lambda x: False)
- self.stubs.Set(self.volume.driver, '_delete_volume',
- lambda x, y: False)
- # Want DriverTestCase._fake_execute to return 'o' so that
- # volume.driver.delete_volume() raises the VolumeIsBusy exception.
- self.output = 'o'
- self.assertRaises(exception.VolumeIsBusy,
- self.volume.driver.delete_volume,
- {'name': 'test1', 'size': 1024})
- # when DriverTestCase._fake_execute returns something other than
- # 'o' volume.driver.delete_volume() does not raise an exception.
- self.output = 'x'
- self.volume.driver.delete_volume({'name': 'test1', 'size': 1024})
-
-
-class ISCSITestCase(DriverTestCase):
- """Test Case for ISCSIDriver"""
- driver_name = "nova.volume.driver.ISCSIDriver"
-
- def _attach_volume(self):
- """Attach volumes to an instance. """
- volume_id_list = []
- for index in xrange(3):
- vol = {}
- vol['size'] = 0
- vol_ref = db.volume_create(self.context, vol)
- self.volume.create_volume(self.context, vol_ref['id'])
- vol_ref = db.volume_get(self.context, vol_ref['id'])
-
- # each volume has a different mountpoint
- mountpoint = "/dev/sd" + chr((ord('b') + index))
- db.volume_attached(self.context, vol_ref['id'], self.instance_uuid,
- mountpoint)
- volume_id_list.append(vol_ref['id'])
-
- return volume_id_list
-
- def test_check_for_export_with_no_volume(self):
- self.volume.check_for_export(self.context, self.instance_id)
-
-
-class VolumePolicyTestCase(test.TestCase):
-
- def setUp(self):
- super(VolumePolicyTestCase, self).setUp()
-
- nova.policy.reset()
- nova.policy.init()
-
- self.context = context.get_admin_context()
-
- def tearDown(self):
- super(VolumePolicyTestCase, self).tearDown()
- nova.policy.reset()
-
- def _set_rules(self, rules):
- nova.common.policy.set_brain(nova.common.policy.HttpBrain(rules))
-
- def test_check_policy(self):
- self.mox.StubOutWithMock(nova.policy, 'enforce')
- target = {
- 'project_id': self.context.project_id,
- 'user_id': self.context.user_id,
- }
- nova.policy.enforce(self.context, 'volume:attach', target)
- self.mox.ReplayAll()
- nova.volume.api.check_policy(self.context, 'attach')
-
- def test_check_policy_with_target(self):
- self.mox.StubOutWithMock(nova.policy, 'enforce')
- target = {
- 'project_id': self.context.project_id,
- 'user_id': self.context.user_id,
- 'id': 2,
- }
- nova.policy.enforce(self.context, 'volume:attach', target)
- self.mox.ReplayAll()
- nova.volume.api.check_policy(self.context, 'attach', {'id': 2})
diff --git a/nova/tests/test_volume_types.py b/nova/tests/test_volume_types.py
deleted file mode 100644
index 5e178d5e1..000000000
--- a/nova/tests/test_volume_types.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Zadara Storage Inc.
-# Copyright (c) 2011 OpenStack LLC.
-# 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.
-"""
-Unit Tests for volume types code
-"""
-import time
-
-from nova import context
-from nova.db.sqlalchemy import models
-from nova.db.sqlalchemy import session as sql_session
-from nova import exception
-from nova import flags
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume import volume_types
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger(__name__)
-
-
-class VolumeTypeTestCase(test.TestCase):
- """Test cases for volume type code"""
- def setUp(self):
- super(VolumeTypeTestCase, self).setUp()
-
- self.ctxt = context.get_admin_context()
- self.vol_type1_name = str(int(time.time()))
- self.vol_type1_specs = dict(
- type="physical drive",
- drive_type="SAS",
- size="300",
- rpm="7200",
- visible="True")
-
- def test_volume_type_create_then_destroy(self):
- """Ensure volume types can be created and deleted"""
- prev_all_vtypes = volume_types.get_all_types(self.ctxt)
-
- volume_types.create(self.ctxt,
- self.vol_type1_name,
- self.vol_type1_specs)
- new = volume_types.get_volume_type_by_name(self.ctxt,
- self.vol_type1_name)
-
- LOG.info(_("Given data: %s"), self.vol_type1_specs)
- LOG.info(_("Result data: %s"), new)
-
- for k, v in self.vol_type1_specs.iteritems():
- self.assertEqual(v, new['extra_specs'][k],
- 'one of fields does not match')
-
- new_all_vtypes = volume_types.get_all_types(self.ctxt)
- self.assertEqual(len(prev_all_vtypes) + 1,
- len(new_all_vtypes),
- 'drive type was not created')
-
- volume_types.destroy(self.ctxt, self.vol_type1_name)
- new_all_vtypes = volume_types.get_all_types(self.ctxt)
- self.assertEqual(prev_all_vtypes,
- new_all_vtypes,
- 'drive type was not deleted')
-
- def test_get_all_volume_types(self):
- """Ensures that all volume types can be retrieved"""
- session = sql_session.get_session()
- total_volume_types = session.query(models.VolumeTypes).count()
- vol_types = volume_types.get_all_types(self.ctxt)
- self.assertEqual(total_volume_types, len(vol_types))
-
- def test_non_existent_vol_type_shouldnt_delete(self):
- """Ensures that volume type creation fails with invalid args"""
- self.assertRaises(exception.VolumeTypeNotFoundByName,
- volume_types.destroy, self.ctxt, "sfsfsdfdfs")
-
- def test_repeated_vol_types_shouldnt_raise(self):
- """Ensures that volume duplicates don't raise"""
- new_name = self.vol_type1_name + "dup"
- volume_types.create(self.ctxt, new_name)
- volume_types.destroy(self.ctxt, new_name)
- volume_types.create(self.ctxt, new_name)
-
- def test_invalid_volume_types_params(self):
- """Ensures that volume type creation fails with invalid args"""
- self.assertRaises(exception.InvalidVolumeType,
- volume_types.destroy, self.ctxt, None)
- self.assertRaises(exception.InvalidVolumeType,
- volume_types.get_volume_type, self.ctxt, None)
- self.assertRaises(exception.InvalidVolumeType,
- volume_types.get_volume_type_by_name,
- self.ctxt, None)
-
- def test_volume_type_get_by_id_and_name(self):
- """Ensure volume types get returns same entry"""
- volume_types.create(self.ctxt,
- self.vol_type1_name,
- self.vol_type1_specs)
- new = volume_types.get_volume_type_by_name(self.ctxt,
- self.vol_type1_name)
-
- new2 = volume_types.get_volume_type(self.ctxt, new['id'])
- self.assertEqual(new, new2)
-
- def test_volume_type_search_by_extra_spec(self):
- """Ensure volume types get by extra spec returns correct type"""
- volume_types.create(self.ctxt, "type1", {"key1": "val1",
- "key2": "val2"})
- volume_types.create(self.ctxt, "type2", {"key2": "val2",
- "key3": "val3"})
- volume_types.create(self.ctxt, "type3", {"key3": "another_value",
- "key4": "val4"})
-
- vol_types = volume_types.get_all_types(self.ctxt,
- search_opts={'extra_specs': {"key1": "val1"}})
- LOG.info("vol_types: %s" % vol_types)
- self.assertEqual(len(vol_types), 1)
- self.assertTrue("type1" in vol_types.keys())
- self.assertEqual(vol_types['type1']['extra_specs'],
- {"key1": "val1", "key2": "val2"})
-
- vol_types = volume_types.get_all_types(self.ctxt,
- search_opts={'extra_specs': {"key2": "val2"}})
- LOG.info("vol_types: %s" % vol_types)
- self.assertEqual(len(vol_types), 2)
- self.assertTrue("type1" in vol_types.keys())
- self.assertTrue("type2" in vol_types.keys())
-
- vol_types = volume_types.get_all_types(self.ctxt,
- search_opts={'extra_specs': {"key3": "val3"}})
- LOG.info("vol_types: %s" % vol_types)
- self.assertEqual(len(vol_types), 1)
- self.assertTrue("type2" in vol_types.keys())
-
- def test_volume_type_search_by_extra_spec_multiple(self):
- """Ensure volume types get by extra spec returns correct type"""
- volume_types.create(self.ctxt, "type1", {"key1": "val1",
- "key2": "val2",
- "key3": "val3"})
- volume_types.create(self.ctxt, "type2", {"key2": "val2",
- "key3": "val3"})
- volume_types.create(self.ctxt, "type3", {"key1": "val1",
- "key3": "val3",
- "key4": "val4"})
-
- vol_types = volume_types.get_all_types(self.ctxt,
- search_opts={'extra_specs': {"key1": "val1",
- "key3": "val3"}})
- LOG.info("vol_types: %s" % vol_types)
- self.assertEqual(len(vol_types), 2)
- self.assertTrue("type1" in vol_types.keys())
- self.assertTrue("type3" in vol_types.keys())
- self.assertEqual(vol_types['type1']['extra_specs'],
- {"key1": "val1", "key2": "val2", "key3": "val3"})
- self.assertEqual(vol_types['type3']['extra_specs'],
- {"key1": "val1", "key3": "val3", "key4": "val4"})
diff --git a/nova/tests/test_volume_types_extra_specs.py b/nova/tests/test_volume_types_extra_specs.py
deleted file mode 100644
index ed7840e0a..000000000
--- a/nova/tests/test_volume_types_extra_specs.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Zadara Storage Inc.
-# Copyright (c) 2011 OpenStack LLC.
-# Copyright 2011 University of Southern California
-# 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.
-"""
-Unit Tests for volume types extra specs code
-"""
-
-from nova import context
-from nova import db
-from nova import test
-
-
-class VolumeTypeExtraSpecsTestCase(test.TestCase):
-
- def setUp(self):
- super(VolumeTypeExtraSpecsTestCase, self).setUp()
- self.context = context.get_admin_context()
- self.vol_type1 = dict(name="TEST: Regular volume test")
- self.vol_type1_specs = dict(vol_extra1="value1",
- vol_extra2="value2",
- vol_extra3=3)
- self.vol_type1['extra_specs'] = self.vol_type1_specs
- ref = db.volume_type_create(self.context, self.vol_type1)
- self.volume_type1_id = ref.id
- for k, v in self.vol_type1_specs.iteritems():
- self.vol_type1_specs[k] = str(v)
-
- self.vol_type2_noextra = dict(name="TEST: Volume type without extra")
- ref = db.volume_type_create(self.context, self.vol_type2_noextra)
- self.vol_type2_id = ref.id
-
- def tearDown(self):
- # Remove the volume type from the database
- db.volume_type_destroy(context.get_admin_context(),
- self.vol_type1['name'])
- db.volume_type_destroy(context.get_admin_context(),
- self.vol_type2_noextra['name'])
- super(VolumeTypeExtraSpecsTestCase, self).tearDown()
-
- def test_volume_type_specs_get(self):
- expected_specs = self.vol_type1_specs.copy()
- actual_specs = db.volume_type_extra_specs_get(
- context.get_admin_context(),
- self.volume_type1_id)
- self.assertEquals(expected_specs, actual_specs)
-
- def test_volume_type_extra_specs_delete(self):
- expected_specs = self.vol_type1_specs.copy()
- del expected_specs['vol_extra2']
- db.volume_type_extra_specs_delete(context.get_admin_context(),
- self.volume_type1_id,
- 'vol_extra2')
- actual_specs = db.volume_type_extra_specs_get(
- context.get_admin_context(),
- self.volume_type1_id)
- self.assertEquals(expected_specs, actual_specs)
-
- def test_volume_type_extra_specs_update(self):
- expected_specs = self.vol_type1_specs.copy()
- expected_specs['vol_extra3'] = "4"
- db.volume_type_extra_specs_update_or_create(
- context.get_admin_context(),
- self.volume_type1_id,
- dict(vol_extra3=4))
- actual_specs = db.volume_type_extra_specs_get(
- context.get_admin_context(),
- self.volume_type1_id)
- self.assertEquals(expected_specs, actual_specs)
-
- def test_volume_type_extra_specs_create(self):
- expected_specs = self.vol_type1_specs.copy()
- expected_specs['vol_extra4'] = 'value4'
- expected_specs['vol_extra5'] = 'value5'
- db.volume_type_extra_specs_update_or_create(
- context.get_admin_context(),
- self.volume_type1_id,
- dict(vol_extra4="value4",
- vol_extra5="value5"))
- actual_specs = db.volume_type_extra_specs_get(
- context.get_admin_context(),
- self.volume_type1_id)
- self.assertEquals(expected_specs, actual_specs)
-
- def test_volume_type_get_with_extra_specs(self):
- volume_type = db.volume_type_get(
- context.get_admin_context(),
- self.volume_type1_id)
- self.assertEquals(volume_type['extra_specs'],
- self.vol_type1_specs)
-
- volume_type = db.volume_type_get(
- context.get_admin_context(),
- self.vol_type2_id)
- self.assertEquals(volume_type['extra_specs'], {})
-
- def test_volume_type_get_by_name_with_extra_specs(self):
- volume_type = db.volume_type_get_by_name(
- context.get_admin_context(),
- self.vol_type1['name'])
- self.assertEquals(volume_type['extra_specs'],
- self.vol_type1_specs)
-
- volume_type = db.volume_type_get_by_name(
- context.get_admin_context(),
- self.vol_type2_noextra['name'])
- self.assertEquals(volume_type['extra_specs'], {})
-
- def test_volume_type_get_all(self):
- expected_specs = self.vol_type1_specs.copy()
-
- types = db.volume_type_get_all(context.get_admin_context())
-
- self.assertEquals(
- types[self.vol_type1['name']]['extra_specs'], expected_specs)
-
- self.assertEquals(
- types[self.vol_type2_noextra['name']]['extra_specs'], {})
diff --git a/nova/tests/test_volume_utils.py b/nova/tests/test_volume_utils.py
deleted file mode 100644
index 89ad7c3db..000000000
--- a/nova/tests/test_volume_utils.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.
-
-"""Tests For miscellaneous util methods used with volume."""
-
-from nova import context
-from nova import db
-from nova import flags
-from nova.openstack.common import importutils
-from nova.openstack.common import log as logging
-from nova.openstack.common.notifier import api as notifier_api
-from nova.openstack.common.notifier import test_notifier
-from nova import test
-from nova.tests import fake_network
-from nova.volume import utils as volume_utils
-
-
-LOG = logging.getLogger(__name__)
-FLAGS = flags.FLAGS
-
-
-class UsageInfoTestCase(test.TestCase):
-
- def setUp(self):
- super(UsageInfoTestCase, self).setUp()
- self.flags(compute_driver='nova.virt.fake.FakeDriver',
- host='fake',
- notification_driver=[test_notifier.__name__])
- fake_network.set_stub_network_methods(self.stubs)
-
- self.volume = importutils.import_object(FLAGS.volume_manager)
- self.user_id = 'fake'
- self.project_id = 'fake'
- self.snapshot_id = 'fake'
- self.volume_size = 0
- self.context = context.RequestContext(self.user_id, self.project_id)
- test_notifier.NOTIFICATIONS = []
-
- def tearDown(self):
- notifier_api._reset_drivers()
- super(UsageInfoTestCase, self).tearDown()
-
- def _create_volume(self, params={}):
- """Create a test volume"""
- vol = {}
- vol['snapshot_id'] = self.snapshot_id
- vol['user_id'] = self.user_id
- vol['project_id'] = self.project_id
- vol['host'] = FLAGS.host
- vol['availability_zone'] = FLAGS.storage_availability_zone
- vol['status'] = "creating"
- vol['attach_status'] = "detached"
- vol['size'] = self.volume_size
- vol.update(params)
- return db.volume_create(self.context, vol)['id']
-
- def test_notify_usage_exists(self):
- """Ensure 'exists' notification generates appropriate usage data."""
- volume_id = self._create_volume()
- volume = db.volume_get(self.context, volume_id)
- volume_utils.notify_usage_exists(self.context, volume)
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 1)
- msg = test_notifier.NOTIFICATIONS[0]
- self.assertEquals(msg['priority'], 'INFO')
- self.assertEquals(msg['event_type'], 'volume.exists')
- payload = msg['payload']
- self.assertEquals(payload['tenant_id'], self.project_id)
- self.assertEquals(payload['user_id'], self.user_id)
- self.assertEquals(payload['snapshot_id'], self.snapshot_id)
- self.assertEquals(payload['volume_id'], volume.id)
- self.assertEquals(payload['size'], self.volume_size)
- for attr in ('display_name', 'created_at', 'launched_at',
- 'status', 'audit_period_beginning',
- 'audit_period_ending'):
- self.assertTrue(attr in payload,
- msg="Key %s not in payload" % attr)
- db.volume_destroy(context.get_admin_context(), volume['id'])
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index a7bfa7548..11e8844c4 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -170,7 +170,7 @@ class XenAPIVolumeTestCase(stubs.XenAPITestBase):
vol['user_id'] = 'fake'
vol['project_id'] = 'fake'
vol['host'] = 'localhost'
- vol['availability_zone'] = FLAGS.storage_availability_zone
+ vol['availability_zone'] = FLAGS.node_availability_zone
vol['status'] = "creating"
vol['attach_status'] = "detached"
return db.volume_create(self.context, vol)
diff --git a/nova/tests/test_xensm.py b/nova/tests/test_xensm.py
deleted file mode 100644
index 2f2108aa4..000000000
--- a/nova/tests/test_xensm.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2010 Citrix Systems, Inc.
-#
-# 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.
-
-"""Test suite for Xen Storage Manager Volume Driver."""
-
-
-from nova import context
-from nova import db
-from nova import exception
-from nova import flags
-from nova.openstack.common import log as logging
-from nova.tests.xenapi import stubs
-from nova.virt.xenapi import fake as xenapi_fake
-from nova.volume import xensm
-
-LOG = logging.getLogger(__name__)
-
-FLAGS = flags.FLAGS
-
-
-class XenSMTestCase(stubs.XenAPITestBase):
- """Unit tests for Xen Storage Manager Volume operations."""
-
- def _get_sm_backend_params(self):
- config_params = ("name_label=testsmbackend "
- "server=localhost "
- "serverpath=/tmp/nfspath")
- params = dict(flavor_id=1,
- sr_uuid=None,
- sr_type='nfs',
- config_params=config_params)
- return params
-
- def setUp(self):
- super(XenSMTestCase, self).setUp()
- self.user_id = 'fake'
- self.project_id = 'fake'
- self.context = context.RequestContext(self.user_id, self.project_id)
- self.flags(compute_driver='xenapi.XenAPIDriver',
- xenapi_connection_url='http://test_url',
- xenapi_connection_username='test_user',
- xenapi_connection_password='test_pass')
- stubs.stubout_session(self.stubs, xenapi_fake.SessionBase)
- xenapi_fake.reset()
- self.driver = xensm.XenSMDriver()
- self.driver.db = db
-
- def _setup_step(self, ctxt):
- # Create a fake backend conf
- params = self._get_sm_backend_params()
- beconf = db.sm_backend_conf_create(ctxt,
- params)
- # Call setup, the one time operation that will create a backend SR
- self.driver.do_setup(ctxt)
- return beconf
-
- def test_do_setup(self):
- ctxt = context.get_admin_context()
- beconf = self._setup_step(ctxt)
- beconf = db.sm_backend_conf_get(ctxt, beconf['id'])
- self.assertIsInstance(beconf['sr_uuid'], basestring)
-
- def _create_volume(self, size=0):
- """Create a volume object."""
- vol = {}
- vol['size'] = size
- vol['user_id'] = 'fake'
- vol['project_id'] = 'fake'
- vol['host'] = 'localhost'
- vol['availability_zone'] = FLAGS.storage_availability_zone
- vol['status'] = "creating"
- vol['attach_status'] = "detached"
- return db.volume_create(self.context, vol)
-
- def test_create_volume(self):
- ctxt = context.get_admin_context()
- beconf = self._setup_step(ctxt)
- volume = self._create_volume()
- self.driver.create_volume(volume)
- db.sm_volume_get(ctxt, volume['id'])
-
- def test_local_path(self):
- ctxt = context.get_admin_context()
- volume = self._create_volume()
- val = self.driver.local_path(volume)
- self.assertIsInstance(val, basestring)
-
- def test_delete_volume(self):
- ctxt = context.get_admin_context()
- beconf = self._setup_step(ctxt)
- volume = self._create_volume()
- self.driver.create_volume(volume)
- self.driver.delete_volume(volume)
- self.assertRaises(exception.NotFound,
- db.sm_volume_get,
- ctxt,
- volume['id'])
-
- def test_delete_volume_raises_notfound(self):
- ctxt = context.get_admin_context()
- beconf = self._setup_step(ctxt)
- self.assertRaises(exception.NotFound,
- self.driver.delete_volume,
- {'id': "FA15E-1D"})
-
- def _get_expected_conn(self, beconf, vol):
- expected = {}
- expected['volume_id'] = unicode(vol['id'])
- expected['flavor_id'] = beconf['flavor_id']
- expected['sr_uuid'] = unicode(beconf['sr_uuid'])
- expected['sr_type'] = unicode(beconf['sr_type'])
- return expected
-
- def test_initialize_connection(self):
- ctxt = context.get_admin_context()
- beconf = self._setup_step(ctxt)
- beconf = db.sm_backend_conf_get(ctxt, beconf['id'])
- volume = self._create_volume()
- self.driver.create_volume(volume)
- expected = self._get_expected_conn(beconf, volume)
- conn = self.driver.initialize_connection(volume, 'fakeConnector')
- res = {}
- for key in ['volume_id', 'flavor_id', 'sr_uuid', 'sr_type']:
- res[key] = conn['data'][key]
- self.assertDictMatch(expected, res)
- self.assertEqual(set(conn['data']['introduce_sr_keys']),
- set([u'sr_type', u'server', u'serverpath']))
diff --git a/nova/tests/volume/test_HpSanISCSIDriver.py b/nova/tests/volume/test_HpSanISCSIDriver.py
deleted file mode 100644
index d6d3f3488..000000000
--- a/nova/tests/volume/test_HpSanISCSIDriver.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# Copyright 2012 OpenStack LLC
-#
-# 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 exception
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume import san
-
-LOG = logging.getLogger(__name__)
-
-
-class HpSanISCSITestCase(test.TestCase):
-
- def setUp(self):
- super(HpSanISCSITestCase, self).setUp()
- self.stubs.Set(san.HpSanISCSIDriver, "_cliq_run",
- self._fake_cliq_run)
- self.stubs.Set(san.HpSanISCSIDriver, "_get_iscsi_properties",
- self._fake_get_iscsi_properties)
- self.driver = san.HpSanISCSIDriver()
- self.volume_name = "fakevolume"
- self.connector = {'ip': '10.0.0.2',
- 'initiator': 'iqn.1993-08.org.debian:01:222',
- 'host': 'fakehost'}
- self.properties = {'target_discoverd': True,
- 'target_portal': '10.0.1.6:3260',
- 'target_iqn':
- 'iqn.2003-10.com.lefthandnetworks:group01:25366:fakev',
- 'volume_id': 1}
-
- def _fake_get_iscsi_properties(self, volume):
- return self.properties
-
- def _fake_cliq_run(self, verb, cliq_args):
- """Return fake results for the various methods."""
-
- def create_volume(cliq_args):
- """
- input = "createVolume description="fake description"
- clusterName=Cluster01 volumeName=fakevolume
- thinProvision=0 output=XML size=1GB"
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded."
- name="CliqSuccess" processingTime="181" result="0"/>
- </gauche>"""
- self.assertEqual(cliq_args['volumeName'], self.volume_name)
- self.assertEqual(cliq_args['thinProvision'], '1')
- self.assertEqual(cliq_args['size'], '1GB')
- return output, None
-
- def delete_volume(cliq_args):
- """
- input = "deleteVolume volumeName=fakevolume prompt=false
- output=XML"
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded."
- name="CliqSuccess" processingTime="164" result="0"/>
- </gauche>"""
- self.assertEqual(cliq_args['volumeName'], self.volume_name)
- self.assertEqual(cliq_args['prompt'], 'false')
- return output, None
-
- def assign_volume(cliq_args):
- """
- input = "assignVolumeToServer volumeName=fakevolume
- serverName=fakehost
- output=XML"
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded."
- name="CliqSuccess" processingTime="174" result="0"/>
- </gauche>"""
- self.assertEqual(cliq_args['volumeName'], self.volume_name)
- self.assertEqual(cliq_args['serverName'], self.connector['host'])
- return output, None
-
- def unassign_volume(cliq_args):
- """
- input = "unassignVolumeToServer volumeName=fakevolume
- serverName=fakehost output=XML
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded."
- name="CliqSuccess" processingTime="205" result="0"/>
- </gauche>"""
- self.assertEqual(cliq_args['volumeName'], self.volume_name)
- self.assertEqual(cliq_args['serverName'], self.connector['host'])
- return output, None
-
- def get_cluster_info(cliq_args):
- """
- input = "getClusterInfo clusterName=Cluster01 searchDepth=1
- verbose=0 output=XML"
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded." name="CliqSuccess"
- processingTime="1164" result="0">
- <cluster blockSize="1024" description=""
- maxVolumeSizeReplication1="622957690"
- maxVolumeSizeReplication2="311480287"
- minVolumeSize="262144" name="Cluster01"
- pageSize="262144" spaceTotal="633697992"
- storageNodeCount="2" unprovisionedSpace="622960574"
- useVip="true">
- <nsm ipAddress="10.0.1.7" name="111-vsa"/>
- <nsm ipAddress="10.0.1.8" name="112-vsa"/>
- <vip ipAddress="10.0.1.6" subnetMask="255.255.255.0"/>
- </cluster></response></gauche>"""
- return output, None
-
- def get_volume_info(cliq_args):
- """
- input = "getVolumeInfo volumeName=fakevolume output=XML"
- """
- output = """<gauche version="1.0">
- <response description="Operation succeeded." name="CliqSuccess"
- processingTime="87" result="0">
- <volume autogrowPages="4" availability="online"
- blockSize="1024" bytesWritten="0" checkSum="false"
- clusterName="Cluster01" created="2011-02-08T19:56:53Z"
- deleting="false" description="" groupName="Group01"
- initialQuota="536870912" isPrimary="true"
- iscsiIqn="iqn.2003-10.com.lefthandnetworks:group01:25366:fakev"
- maxSize="6865387257856" md5="9fa5c8b2cca54b2948a63d833097e1ca"
- minReplication="1" name="vol-b" parity="0" replication="2"
- reserveQuota="536870912" scratchQuota="4194304"
- serialNumber="9fa5c8b2cca54b2948a63d8"
- size="1073741824" stridePages="32" thinProvision="true">
- <status description="OK" value="2"/>
- <permission access="rw" authGroup="api-1"
- chapName="chapusername" chapRequired="true"
- id="25369" initiatorSecret="" iqn=""
- iscsiEnabled="true" loadBalance="true"
- targetSecret="supersecret"/>
- </volume></response></gauche>"""
- return output, None
-
- def test_error(cliq_args):
- output = """<gauche version="1.0">
- <response description="Volume '134234' not found."
- name="CliqVolumeNotFound" processingTime="1083"
- result="8000100c"/>
- </gauche>"""
- return output, None
-
- self.assertEqual(cliq_args['output'], 'XML')
- try:
- verbs = {'createVolume': create_volume,
- 'deleteVolume': delete_volume,
- 'assignVolumeToServer': assign_volume,
- 'unassignVolumeToServer': unassign_volume,
- 'getClusterInfo': get_cluster_info,
- 'getVolumeInfo': get_volume_info,
- 'testError': test_error}
- except KeyError:
- raise NotImplementedError()
-
- return verbs[verb](cliq_args)
-
- def test_create_volume(self):
- volume = {'name': self.volume_name, 'size': 1}
- model_update = self.driver.create_volume(volume)
- expected_iqn = "iqn.2003-10.com.lefthandnetworks:group01:25366:fakev 0"
- expected_location = "10.0.1.6:3260,1 %s" % expected_iqn
- self.assertEqual(model_update['provider_location'], expected_location)
-
- def test_delete_volume(self):
- volume = {'name': self.volume_name}
- self.driver.delete_volume(volume)
-
- def test_initialize_connection(self):
- volume = {'name': self.volume_name}
- result = self.driver.initialize_connection(volume, self.connector)
- self.assertEqual(result['driver_volume_type'], 'iscsi')
- self.assertDictMatch(result['data'], self.properties)
-
- def test_terminate_connection(self):
- volume = {'name': self.volume_name}
- self.driver.terminate_connection(volume, self.connector)
-
- def test_create_snapshot(self):
- try:
- self.driver.create_snapshot("")
- except NotImplementedError:
- pass
-
- def test_create_volume_from_snapshot(self):
- try:
- self.driver.create_volume_from_snapshot("", "")
- except NotImplementedError:
- pass
-
- def test_cliq_error(self):
- try:
- self.driver._cliq_run_xml("testError", {})
- except exception.NovaException:
- pass